Commit 70fd1333 authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau

mt76: mt7915: rework .set_bitrate_mask() to support more options

With this patch, driver can support single rate, (HE)GI and HE_LTF
configuration through .set_bitrate_mask().
Tested-by: default avatarMeiChia Chiu <meichia.chiu@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 2eec60dc
...@@ -89,7 +89,7 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask) ...@@ -89,7 +89,7 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
0, 5000); 0, 5000);
} }
static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw) u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw)
{ {
mt76_wr(dev, MT_WTBLON_TOP_WDUCR, mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
......
...@@ -172,6 +172,9 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) ...@@ -172,6 +172,9 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
int i; int i;
for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0);
mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0);
mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0), memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
sizeof(mvif->bitrate_mask.control[i].ht_mcs)); sizeof(mvif->bitrate_mask.control[i].ht_mcs));
...@@ -994,7 +997,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) ...@@ -994,7 +997,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
{ {
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_dev *dev = msta->vif->phy->dev; struct mt7915_dev *dev = msta->vif->phy->dev;
struct ieee80211_hw *hw = msta->vif->phy->mt76->hw;
u32 *changed = data; u32 *changed = data;
spin_lock_bh(&dev->sta_poll_lock); spin_lock_bh(&dev->sta_poll_lock);
...@@ -1002,8 +1004,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) ...@@ -1002,8 +1004,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
if (list_empty(&msta->rc_list)) if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list); list_add_tail(&msta->rc_list, &dev->sta_rc_list);
spin_unlock_bh(&dev->sta_poll_lock); spin_unlock_bh(&dev->sta_poll_lock);
ieee80211_queue_work(hw, &dev->rc_work);
} }
static void mt7915_sta_rc_update(struct ieee80211_hw *hw, static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
...@@ -1011,7 +1011,11 @@ static void mt7915_sta_rc_update(struct ieee80211_hw *hw, ...@@ -1011,7 +1011,11 @@ static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
u32 changed) u32 changed)
{ {
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = phy->dev;
mt7915_sta_rc_work(&changed, sta); mt7915_sta_rc_work(&changed, sta);
ieee80211_queue_work(hw, &dev->rc_work);
} }
static int static int
...@@ -1019,22 +1023,22 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -1019,22 +1023,22 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask) const struct cfg80211_bitrate_mask *mask)
{ {
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
enum nl80211_band band = mvif->phy->mt76->chandef.chan->band; struct mt7915_phy *phy = mt7915_hw_phy(hw);
u32 changed; struct mt7915_dev *dev = phy->dev;
u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
if (mask->control[band].gi == NL80211_TXRATE_FORCE_LGI)
return -EINVAL;
changed = IEEE80211_RC_SUPP_RATES_CHANGED;
mvif->bitrate_mask = *mask; mvif->bitrate_mask = *mask;
/* Update firmware rate control to add a boundary on top of table /* if multiple rates across different preambles are given we can
* to limit the rate selection for each peer, so when set bitrates * reconfigure this info with all peers using sta_rec command with
* vht-mcs-5 1:9, which actually means nss = 1 mcs = 0~9. This only * the below exception cases.
* applies to data frames as for the other mgmt, mcast, bcast still * - single rate : if a rate is passed along with different preambles,
* use legacy rates as it is. * we select the highest one as fixed rate. i.e VHT MCS for VHT peers.
* - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
* then multiple MCS setting (MCS 4,5,6) is not supported.
*/ */
ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed); ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);
ieee80211_queue_work(hw, &dev->rc_work);
return 0; return 0;
} }
......
...@@ -2050,6 +2050,128 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, ...@@ -2050,6 +2050,128 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2); bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
} }
int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *data, u32 field)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct sta_phy *phy = data;
struct sta_rec_ra_fixed *ra;
struct sk_buff *skb;
struct tlv *tlv;
int len = sizeof(struct sta_req_hdr) + sizeof(*ra);
skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
if (IS_ERR(skb))
return PTR_ERR(skb);
tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
ra = (struct sta_rec_ra_fixed *)tlv;
switch (field) {
case RATE_PARAM_AUTO:
break;
case RATE_PARAM_FIXED_MCS:
case RATE_PARAM_FIXED_GI:
case RATE_PARAM_FIXED_HE_LTF:
ra->phy = *phy;
break;
default:
break;
}
ra->field = cpu_to_le32(field);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_EXT_CMD(STA_REC_UPDATE), true);
}
static int
mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
enum nl80211_band band = chandef->chan->band;
struct sta_phy phy = {};
int ret, nrates = 0;
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _he) \
do { \
u8 i, gi = mask->control[band]._gi; \
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
for (i = 0; i <= sta->bandwidth; i++) { \
phy.sgi |= gi << (i << (_he)); \
phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\
} \
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) \
nrates += hweight16(mask->control[band]._mcs[i]); \
phy.mcs = ffs(mask->control[band]._mcs[0]) - 1; \
} while (0)
if (sta->he_cap.has_he) {
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 1);
} else if (sta->vht_cap.vht_supported) {
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0);
} else if (sta->ht_cap.ht_supported) {
__sta_phy_bitrate_mask_check(ht_mcs, gi, 0);
} else {
nrates = hweight32(mask->control[band].legacy);
phy.mcs = ffs(mask->control[band].legacy) - 1;
}
#undef __sta_phy_bitrate_mask_check
/* fall back to auto rate control */
if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
mask->control[band].he_gi == GENMASK(7, 0) &&
mask->control[band].he_ltf == GENMASK(7, 0) &&
nrates != 1)
return 0;
/* fixed single rate */
if (nrates == 1) {
ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
RATE_PARAM_FIXED_MCS);
if (ret)
return ret;
}
/* fixed GI */
if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
mask->control[band].he_gi != GENMASK(7, 0)) {
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
u32 addr;
/* firmware updates only TXCMD but doesn't take WTBL into
* account, so driver should update here to reflect the
* actual txrate hardware sends out.
*/
addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
if (sta->he_cap.has_he)
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
else
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
RATE_PARAM_FIXED_GI);
if (ret)
return ret;
}
/* fixed HE_LTF */
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
RATE_PARAM_FIXED_HE_LTF);
if (ret)
return ret;
}
return 0;
}
static void static void
mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
struct ieee80211_vif *vif, struct ieee80211_sta *sta) struct ieee80211_vif *vif, struct ieee80211_sta *sta)
...@@ -2092,8 +2214,6 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ...@@ -2092,8 +2214,6 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
} }
if (sta->ht_cap.ht_supported) { if (sta->ht_cap.ht_supported) {
const u8 *mcs_mask = mask->control[band].ht_mcs;
ra->supp_mode |= MODE_HT; ra->supp_mode |= MODE_HT;
ra->af = sta->ht_cap.ampdu_factor; ra->af = sta->ht_cap.ampdu_factor;
ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
...@@ -2111,12 +2231,12 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ...@@ -2111,12 +2231,12 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC; cap |= STA_CAP_LDPC;
mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, mcs_mask); mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,
mask->control[band].ht_mcs);
ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
} }
if (sta->vht_cap.vht_supported) { if (sta->vht_cap.vht_supported) {
const u16 *mcs_mask = mask->control[band].vht_mcs;
u8 af; u8 af;
ra->supp_mode |= MODE_VHT; ra->supp_mode |= MODE_VHT;
...@@ -2137,7 +2257,8 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ...@@ -2137,7 +2257,8 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC; cap |= STA_CAP_VHT_LDPC;
mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mcs_mask); mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,
mask->control[band].vht_mcs);
} }
if (sta->he_cap.has_he) { if (sta->he_cap.has_he) {
...@@ -2154,6 +2275,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -2154,6 +2275,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct sk_buff *skb; struct sk_buff *skb;
int ret;
skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta,
MT7915_STA_UPDATE_MAX_SIZE); MT7915_STA_UPDATE_MAX_SIZE);
...@@ -2167,10 +2289,21 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -2167,10 +2289,21 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
if (sta->he_cap.has_he && changed) if (sta->he_cap.has_he && changed)
mt7915_mcu_sta_he_tlv(skb, sta, vif); mt7915_mcu_sta_he_tlv(skb, sta, vif);
/* sta_rec_ra accommodates BW, NSS and only MCS range format
* i.e 0-{7,8,9} for VHT.
*/
mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
return mt76_mcu_skb_send_msg(&dev->mt76, skb, ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_EXT_CMD(STA_REC_UPDATE), true); MCU_EXT_CMD(STA_REC_UPDATE), true);
if (ret)
return ret;
/* sta_rec_ra_fixed accommodates single rate, (HE)GI and HE_LTE,
* and updates as peer fixed rate parameters, which overrides
* sta_rec_ra and firmware rate control algorithm.
*/
return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta);
} }
static int static int
......
...@@ -886,7 +886,7 @@ struct sta_rec_sec { ...@@ -886,7 +886,7 @@ struct sta_rec_sec {
struct sec_key key[2]; struct sec_key key[2];
} __packed; } __packed;
struct ra_phy { struct sta_phy {
u8 type; u8 type;
u8 flag; u8 flag;
u8 stbc; u8 stbc;
...@@ -930,7 +930,7 @@ struct sta_rec_ra { ...@@ -930,7 +930,7 @@ struct sta_rec_ra {
__le32 sta_cap; __le32 sta_cap;
struct ra_phy phy; struct sta_phy phy;
} __packed; } __packed;
struct sta_rec_ra_fixed { struct sta_rec_ra_fixed {
...@@ -943,7 +943,7 @@ struct sta_rec_ra_fixed { ...@@ -943,7 +943,7 @@ struct sta_rec_ra_fixed {
u8 op_vht_rx_nss; u8 op_vht_rx_nss;
u8 op_vht_rx_nss_type; u8 op_vht_rx_nss_type;
struct ra_phy phy; struct sta_phy phy;
u8 spe_en; u8 spe_en;
u8 short_preamble; u8 short_preamble;
...@@ -951,8 +951,14 @@ struct sta_rec_ra_fixed { ...@@ -951,8 +951,14 @@ struct sta_rec_ra_fixed {
u8 mmps_mode; u8 mmps_mode;
} __packed; } __packed;
#define RATE_PARAM_FIXED 3 enum {
#define RATE_PARAM_AUTO 20 RATE_PARAM_FIXED = 3,
RATE_PARAM_FIXED_HE_LTF = 7,
RATE_PARAM_FIXED_MCS,
RATE_PARAM_FIXED_GI = 11,
RATE_PARAM_AUTO = 20,
};
#define RATE_CFG_MCS GENMASK(3, 0) #define RATE_CFG_MCS GENMASK(3, 0)
#define RATE_CFG_NSS GENMASK(7, 4) #define RATE_CFG_NSS GENMASK(7, 4)
#define RATE_CFG_GI GENMASK(11, 8) #define RATE_CFG_GI GENMASK(11, 8)
......
...@@ -418,6 +418,10 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif); ...@@ -418,6 +418,10 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif);
int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req); int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req);
int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev,
struct ieee80211_sta *sta, u32 rate); struct ieee80211_sta *sta, u32 rate);
int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *data, u32 field);
int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
...@@ -478,6 +482,7 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask) ...@@ -478,6 +482,7 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
} }
u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw);
bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask); bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);
void mt7915_mac_reset_counters(struct mt7915_phy *phy); void mt7915_mac_reset_counters(struct mt7915_phy *phy);
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment