wifi: mt76: mt7996: enable BSS_CHANGED_BASIC_RATES support
authorRyder Lee <ryder.lee@mediatek.com>
Thu, 13 Apr 2023 20:23:31 +0000 (04:23 +0800)
committerFelix Fietkau <nbd@nbd.name>
Wed, 19 Apr 2023 08:09:43 +0000 (10:09 +0200)
The connac3 removes fixed rate fields to reduce txd size and introduces
global rate tables (64 entries) for rate setting. Driver needs to fill
the corresponding idx in MT_TXD6_TX_RATE while tx, and push mt76_rate
into predifined table at bootup stage so that  mvif->basic_rates_idx
can immediately switch out once setting changes.

spe_idx is also needed for fixed rate frames, and will be updated by
future patches.

Note that all table entries are shared across driver and firmware
(i.e.TxBF), hence adding MT7996_BASIC_RATES_TBL to reflect mapping
status.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7996/init.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.h
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
drivers/net/wireless/mediatek/mt76/mt7996/regs.h

index 19cdd06..90a92c1 100644 (file)
@@ -255,6 +255,20 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
        mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
 }
 
+static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
+               u16 rate = mt76_rates[i].hw_value;
+               u16 idx = MT7996_BASIC_RATES_TBL + i;
+
+               rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
+                      FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
+               mt7996_mac_set_fixed_rate_table(dev, idx, rate);
+       }
+}
+
 void mt7996_mac_init(struct mt7996_dev *dev)
 {
 #define HIF_TXD_V2_1   4
@@ -287,6 +301,8 @@ void mt7996_mac_init(struct mt7996_dev *dev)
 
        for (i = MT_BAND0; i <= MT_BAND2; i++)
                mt7996_mac_init_band(dev, i);
+
+       mt7996_mac_init_basic_rates(dev);
 }
 
 int mt7996_txbf_init(struct mt7996_dev *dev)
index 1e9452c..c8ada30 100644 (file)
@@ -252,6 +252,17 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
                mt76_clear(dev, addr, BIT(5));
 }
 
+void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+                                    u8 tbl_idx, u16 rate_idx)
+{
+       u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
+
+       mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
+       /* use wtbl spe idx */
+       mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
+       mt76_wr(dev, MT_WTBL_ITCR, ctrl);
+}
+
 static void
 mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
                                 struct ieee80211_radiotap_he *he,
@@ -985,7 +996,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_vif *vif = info->control.vif;
-       struct mt76_phy *mphy = &dev->mphy;
+       struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
        u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
        u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
        bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
@@ -997,15 +1008,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
                                         BSS_CHANGED_FILS_DISCOVERY));
 
        if (vif) {
-               struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-
                omac_idx = mvif->mt76.omac_idx;
                wmm_idx = mvif->mt76.wmm_idx;
                band_idx = mvif->mt76.band_idx;
        }
 
-       mphy = mt76_dev_phy(&dev->mt76, band_idx);
-
        if (inband_disc) {
                p_fmt = MT_TX_TYPE_FW;
                q_idx = MT_LMAC_ALTX0;
@@ -1063,18 +1070,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
                mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
 
        if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
-               /* Fixed rata is available just for 802.11 txd */
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-               bool multicast = is_multicast_ether_addr(hdr->addr1);
-               u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
-                                                       multicast);
-
-               /* fix to bw 20 */
-               val = MT_TXD6_FIXED_BW |
-                     FIELD_PREP(MT_TXD6_BW, 0) |
-                     FIELD_PREP(MT_TXD6_TX_RATE, rate);
-
-               txwi[6] |= cpu_to_le32(val);
+               u8 idx = mvif->basic_rates_idx;
+
+               txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx);
                txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
        }
 }
index 0318e16..b2bbe0e 100644 (file)
@@ -224,14 +224,11 @@ enum tx_mgnt_type {
 
 #define MT_TXD6_TX_SRC                 GENMASK(31, 30)
 #define MT_TXD6_VTA                    BIT(28)
-#define MT_TXD6_FIXED_BW               BIT(25)
-#define MT_TXD6_BW                     GENMASK(24, 22)
+#define MT_TXD6_BW                     GENMASK(25, 22)
 #define MT_TXD6_TX_RATE                        GENMASK(21, 16)
 #define MT_TXD6_TIMESTAMP_OFS_EN       BIT(15)
 #define MT_TXD6_TIMESTAMP_OFS_IDX      GENMASK(14, 10)
 #define MT_TXD6_MSDU_CNT               GENMASK(9, 4)
-#define MT_TXD6_SPE_ID_IDX             BIT(10)
-#define MT_TXD6_ANT_ID                 GENMASK(7, 4)
 #define MT_TXD6_DIS_MAT                        BIT(3)
 #define MT_TXD6_DAS                    BIT(2)
 #define MT_TXD6_AMSDU_CAP              BIT(1)
@@ -245,7 +242,7 @@ enum tx_mgnt_type {
 #define MT_TXD7_UDP_TCP_SUM            BIT(15)
 #define MT_TXD7_TX_TIME                        GENMASK(9, 0)
 
-#define MT_TX_RATE_STBC                        BIT(13)
+#define MT_TX_RATE_STBC                        BIT(14)
 #define MT_TX_RATE_NSS                 GENMASK(13, 10)
 #define MT_TX_RATE_MODE                        GENMASK(9, 6)
 #define MT_TX_RATE_SU_EXT_TONE         BIT(5)
index 7ddfcf6..1243e5f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "mt7996.h"
 #include "mcu.h"
+#include "mac.h"
 
 static bool mt7996_dev_running(struct mt7996_dev *dev)
 {
@@ -219,6 +220,11 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
                vif->offload_flags = 0;
        vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
 
+       if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
+               mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
+       else
+               mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;
+
        mt7996_init_bitrate_mask(vif);
 
        mt7996_mcu_add_bss_info(phy, vif, true);
@@ -496,11 +502,30 @@ mt7996_update_bss_color(struct ieee80211_hw *hw,
        }
 }
 
+static u8
+mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+       struct mt76_phy *mphy = hw->priv;
+       u16 rate;
+       u8 i, idx;
+
+       rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, false);
+
+       idx = FIELD_GET(MT_TX_RATE_IDX, rate);
+       for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
+               if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
+                       return MT7996_BASIC_RATES_TBL + i;
+
+       return mvif->basic_rates_idx;
+}
+
 static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    struct ieee80211_bss_conf *info,
                                    u64 changed)
 {
+       struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
        struct mt7996_phy *phy = mt7996_hw_phy(hw);
        struct mt7996_dev *dev = mt7996_hw_dev(hw);
 
@@ -532,6 +557,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
                }
        }
 
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               mvif->basic_rates_idx = mt7996_get_rates_table(hw, vif);
+
        if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
                mt7996_mcu_add_bss_info(phy, vif, true);
                mt7996_mcu_add_sta(dev, vif, NULL, true);
@@ -891,6 +919,7 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
        mt7996_set_stream_vht_txbf_caps(phy);
        mt7996_set_stream_he_eht_caps(phy);
 
+       /* TODO: update bmc_wtbl spe_idx when antenna changes */
        mutex_unlock(&dev->mt76.mutex);
 
        return 0;
index c99605a..3db74ae 100644 (file)
@@ -597,25 +597,23 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
 }
 
 static void
-mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7996_phy *phy)
+mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+                      struct mt7996_phy *phy)
 {
+       struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
        struct bss_rate_tlv *bmc;
        struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
        enum nl80211_band band = chandef->chan->band;
        struct tlv *tlv;
+       u8 idx = mvif->basic_rates_idx;
 
        tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc));
 
        bmc = (struct bss_rate_tlv *)tlv;
-       if (band == NL80211_BAND_2GHZ) {
-               bmc->short_preamble = true;
-       } else {
-               bmc->bc_trans = cpu_to_le16(0x8080);
-               bmc->mc_trans = cpu_to_le16(0x8080);
-               bmc->bc_fixed_rate = 1;
-               bmc->mc_fixed_rate = 1;
-               bmc->short_preamble = 1;
-       }
+
+       bmc->short_preamble = (band == NL80211_BAND_2GHZ);
+       bmc->bc_fixed_rate = idx;
+       bmc->mc_fixed_rate = idx;
 }
 
 static void
@@ -823,7 +821,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
 
        if (enable) {
                mt7996_mcu_bss_rfch_tlv(skb, vif, phy);
-               mt7996_mcu_bss_bmc_tlv(skb, phy);
+               mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
                mt7996_mcu_bss_ra_tlv(skb, vif, phy);
                mt7996_mcu_bss_txcmd_tlv(skb, true);
 
index 4001cf1..5cf5ea8 100644 (file)
@@ -43,6 +43,9 @@
 #define MT7996_MAX_STA_TWT_AGRT                8
 #define MT7996_MAX_QUEUE               (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
 
+/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+#define MT7996_BASIC_RATES_TBL         11
+
 struct mt7996_vif;
 struct mt7996_sta;
 struct mt7996_dfs_pulse;
@@ -120,6 +123,8 @@ struct mt7996_vif {
 
        struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
        struct cfg80211_bitrate_mask bitrate_mask;
+
+       u8 basic_rates_idx;
 };
 
 /* per-phy stats.  */
@@ -505,6 +510,8 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
 void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
 void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
                              struct ieee80211_vif *vif, bool enable);
+void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+                                    u8 tbl_idx, u16 rate_idx);
 void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
                           struct sk_buff *skb, struct mt76_wcid *wcid,
                           struct ieee80211_key_conf *key, int pid,
index 75f8562..d1d3d15 100644 (file)
@@ -228,6 +228,13 @@ enum base_rev {
 #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR         BIT(14)
 #define MT_WTBL_UPDATE_BUSY                    BIT(31)
 
+#define MT_WTBL_ITCR                           MT_WTBLON_TOP(0x3b0)
+#define MT_WTBL_ITCR_WR                                BIT(16)
+#define MT_WTBL_ITCR_EXEC                      BIT(31)
+#define MT_WTBL_ITDR0                          MT_WTBLON_TOP(0x3b8)
+#define MT_WTBL_ITDR1                          MT_WTBLON_TOP(0x3bc)
+#define MT_WTBL_SPE_IDX_SEL                    BIT(6)
+
 /* WTBL */
 #define MT_WTBL_BASE                           0x820d8000
 #define MT_WTBL_LMAC_ID                                GENMASK(14, 8)