Message ID | 1625718546-14969-1-git-send-email-sean.wang@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] mt76: mt7921: fix mgmt frame using unexpected bitrate | expand |
On Thu, 2021-07-08 at 12:29 +0800, sean.wang@mediatek.com wrote: > From: Sean Wang <sean.wang@mediatek.com> > > Fix the current driver mgmt frame is not respecting the basic rates > field > provided by the AP and then unconditionally is using the lowest (1 or > 6 > Mbps) rate. > > For example, if the AP only supported basic rate {24, 36, 48, 54} > Mbps, > mt7921 cannot send mgmt frame with the rate not in the group. So, > instead, we pick up the lowest basic rate the AP can support to send. > > The patch also fixed up the hw_value in ieee80211_rate for MT7921 > hardware. > > Fixes: 163f4d22c118 ("mt76: mt7921: add MAC support") > Signed-off-by: Sean Wang <sean.wang@mediatek.com> > --- > .../net/wireless/mediatek/mt76/mt7921/init.c | 19 +++++++++++++++-- > .../net/wireless/mediatek/mt76/mt7921/mac.c | 21 +++++++++++++++ > ---- > .../wireless/mediatek/mt76/mt7921/mt7921.h | 14 +++++++++++++ > 3 files changed, 48 insertions(+), 6 deletions(-) > > > + int i, offset = 0; > + > + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) > + offset = 4; > + > + i = ffs(vif->bss_conf.basic_rates) - 1; > + rate = &mt7921_rates[offset + i]; > + > + return rate->hw_value; > +} > + > void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, > struct sk_buff *skb, struct mt76_wcid *wcid, > struct ieee80211_key_conf *key, bool beacon) > @@ -815,10 +831,7 @@ void mt7921_mac_write_txwi(struct mt7921_dev > *dev, __le32 *txwi, > /* hardware won't add HTC for mgmt/ctrl frame */ > txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); > > - if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) > - rate = MT7921_5G_RATE_DEFAULT; > - else > - rate = MT7921_2G_RATE_DEFAULT; > + rate = mt7921_default_basic_rates(dev, vif); .... > > \ > + .bitrate = _rate, \ > + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ > + .hw_value = (MT_PHY_TYPE_CCK << 6) | (_idx), \ > + .hw_value_short = (MT_PHY_TYPE_CCK << 6) | (4 + _idx), \ > +} > + > +#define MT7921_OFDM_RATE(_idx, _rate) { > \ > + .bitrate = _rate, \ > + .hw_value = (MT_PHY_TYPE_OFDM << 6) | (_idx), \ > + .hw_value_short = (MT_PHY_TYPE_OFDM << 6) | (_idx), \ > +} > + Nice catching. I shifted the wrong offset while bringing up mt7915, but I used the correct offset in TxD resulting in this mt7921 issue. Can you do me a favor to fix the offset of mt7915 as well? Ryder
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index a9ce10b98827..ee57f268c29c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -24,6 +24,21 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; +struct ieee80211_rate mt7921_rates[] = { + MT7921_CCK_RATE(0, 10), + MT7921_CCK_RATE(1, 20), + MT7921_CCK_RATE(2, 55), + MT7921_CCK_RATE(3, 110), + MT7921_OFDM_RATE(11, 60), + MT7921_OFDM_RATE(15, 90), + MT7921_OFDM_RATE(10, 120), + MT7921_OFDM_RATE(14, 180), + MT7921_OFDM_RATE(9, 240), + MT7921_OFDM_RATE(13, 360), + MT7921_OFDM_RATE(8, 480), + MT7921_OFDM_RATE(12, 540), +}; + static void mt7921_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) @@ -227,8 +242,8 @@ int mt7921_register_device(struct mt7921_dev *dev) mt76_set_stream_caps(&dev->mphy, true); mt7921_set_stream_he_caps(&dev->phy); - ret = mt76_register_device(&dev->mt76, true, mt76_rates, - ARRAY_SIZE(mt76_rates)); + ret = mt76_register_device(&dev->mt76, true, mt7921_rates, + ARRAY_SIZE(mt7921_rates)); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 7fe2e3a50428..76985a6b3be5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -749,6 +749,22 @@ static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi) FIELD_PREP(MT_TXD5_PID, pid)); } +static u16 +mt7921_default_basic_rates(struct mt7921_dev *dev, struct ieee80211_vif *vif) +{ + struct mt76_phy *mphy = &dev->mphy; + struct ieee80211_rate *rate; + int i, offset = 0; + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + offset = 4; + + i = ffs(vif->bss_conf.basic_rates) - 1; + rate = &mt7921_rates[offset + i]; + + return rate->hw_value; +} + void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, bool beacon) @@ -815,10 +831,7 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, /* hardware won't add HTC for mgmt/ctrl frame */ txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); - if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) - rate = MT7921_5G_RATE_DEFAULT; - else - rate = MT7921_2G_RATE_DEFAULT; + rate = mt7921_default_basic_rates(dev, vif); val = MT_TXD6_FIXED_BW | FIELD_PREP(MT_TXD6_TX_RATE, rate); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 2d8bd6bfc820..6ef69f5e8f42 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -45,6 +45,19 @@ #define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM #define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1) +#define MT7921_CCK_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ + .hw_value = (MT_PHY_TYPE_CCK << 6) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_CCK << 6) | (4 + _idx), \ +} + +#define MT7921_OFDM_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .hw_value = (MT_PHY_TYPE_OFDM << 6) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_OFDM << 6) | (_idx), \ +} + #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) #define to_rcpi(rssi) (2 * (rssi) + 220) @@ -241,6 +254,7 @@ static inline u8 mt7921_lmac_mapping(struct mt7921_dev *dev, u8 ac) extern const struct ieee80211_ops mt7921_ops; extern struct pci_driver mt7921_pci_driver; +extern struct ieee80211_rate mt7921_rates[12]; u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);