mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
wifi: mt76: mt7996: support more options for mt7996_set_bitrate_mask()
Add support to configure parameters at runtime, such as mcs, gi, and he_ltf. Note that EHT mode does not support this feature yet. Co-developed-by: MeiChia Chiu <[email protected]> Signed-off-by: MeiChia Chiu <[email protected]> Signed-off-by: Howard Hsu <[email protected]> Signed-off-by: Shayne Chen <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
committed by
Felix Fietkau
parent
751b054891
commit
fea1e10c77
+133
-2
@@ -1624,6 +1624,132 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
|||||||
MCU_WM_UNI_CMD(RA), true);
|
MCU_WM_UNI_CMD(RA), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta, void *data, u32 field)
|
||||||
|
{
|
||||||
|
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||||
|
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||||
|
struct sta_phy *phy = data;
|
||||||
|
struct sta_rec_ra_fixed *ra;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct tlv *tlv;
|
||||||
|
|
||||||
|
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||||
|
&msta->wcid,
|
||||||
|
MT7996_STA_UPDATE_MAX_SIZE);
|
||||||
|
if (IS_ERR(skb))
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
|
||||||
|
tlv = mt76_connac_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:
|
||||||
|
case RATE_PARAM_FIXED_MCS:
|
||||||
|
case RATE_PARAM_FIXED_GI:
|
||||||
|
case RATE_PARAM_FIXED_HE_LTF:
|
||||||
|
if (phy)
|
||||||
|
ra->phy = *phy;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ra->field = cpu_to_le32(field);
|
||||||
|
|
||||||
|
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||||
|
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
struct mt7996_vif *mvif = (struct mt7996_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, _ht, _he) \
|
||||||
|
do { \
|
||||||
|
u8 i, gi = mask->control[band]._gi; \
|
||||||
|
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
|
||||||
|
phy.sgi = gi; \
|
||||||
|
phy.he_ltf = mask->control[band].he_ltf; \
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
|
||||||
|
if (!mask->control[band]._mcs[i]) \
|
||||||
|
continue; \
|
||||||
|
nrates += hweight16(mask->control[band]._mcs[i]); \
|
||||||
|
phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
|
||||||
|
if (_ht) \
|
||||||
|
phy.mcs += 8 * i; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
if (sta->deflink.he_cap.has_he) {
|
||||||
|
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
|
||||||
|
} else if (sta->deflink.vht_cap.vht_supported) {
|
||||||
|
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
|
||||||
|
} else if (sta->deflink.ht_cap.ht_supported) {
|
||||||
|
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 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 = mt7996_mcu_set_fixed_field(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 mt7996_sta *msta = (struct mt7996_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 = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
|
||||||
|
if (sta->deflink.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 = mt7996_mcu_set_fixed_field(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 = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
|
||||||
|
RATE_PARAM_FIXED_HE_LTF);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
||||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
||||||
@@ -1733,6 +1859,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||||
&msta->wcid,
|
&msta->wcid,
|
||||||
@@ -1752,8 +1879,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||||||
*/
|
*/
|
||||||
mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
|
mt7996_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_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Reference in New Issue
Block a user