wifi: mt76: connac: add beacon duplicate TX mode support for mt7996
authorStanleyYP Wang <StanleyYP.Wang@mediatek.com>
Mon, 23 Oct 2023 15:38:48 +0000 (23:38 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 7 Dec 2023 17:50:21 +0000 (18:50 +0100)
For connac3 chipsets, setting of spe_idx is moved from TX descriptor to
the fixed rate table. This patch implements the setting to support
duplicate TX mode for beacon.

Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/init.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 1d8680b153a7d8eba0bc4e02b7523466b9fae4b9..65844de6dccd50be4dc63c90f7dfec54b416046e 100644 (file)
@@ -1242,6 +1242,7 @@ enum {
        MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
        MCU_UNI_CMD_THERMAL = 0x35,
        MCU_UNI_CMD_VOW = 0x37,
+       MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
        MCU_UNI_CMD_RRO = 0x57,
        MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
        MCU_UNI_CMD_PER_STA_INFO = 0x6d,
index e2d08bf96eb05b8517794dea97a3bd433340520b..6a03cddaed04468db719f105f2fde133ec23ce9b 100644 (file)
@@ -354,6 +354,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
                IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
 
        phy->slottime = 9;
+       phy->beacon_rate = -1;
 
        hw->sta_data_size = sizeof(struct mt7996_sta);
        hw->vif_data_size = sizeof(struct mt7996_vif);
@@ -468,11 +469,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
 
        for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
                u16 rate = mt76_rates[i].hw_value;
-               u16 idx = MT7996_BASIC_RATES_TBL + i;
+               /* odd index for driver, even index for firmware */
+               u16 idx = MT7996_BASIC_RATES_TBL + 2 * 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);
+               mt7996_mcu_set_fixed_rate_table(&dev->phy, idx, rate, false);
        }
 }
 
index f653e93349f32530ac9c36532a028e2258ecdd9a..08747f7d54290beb35ab5f3b0ae307449e318c1a 100644 (file)
@@ -248,17 +248,6 @@ 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);
-}
-
 /* The HW does not translate the mac header to 802.3 for mesh point */
 static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
 {
index 33a9d50d3366a588de31de5bcd05902a33b08d3d..9f12b47eb2bf337c4daffa8dd000aa0842f1f85f 100644 (file)
@@ -522,24 +522,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
        struct mt76_phy *mphy = hw->priv;
        u16 rate;
-       u8 i, idx, ht;
+       u8 i, idx;
 
        rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
-       ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
 
-       if (beacon && ht) {
-               struct mt7996_dev *dev = mt7996_hw_dev(hw);
+       if (beacon) {
+               struct mt7996_phy *phy = mphy->priv;
+
+               /* odd index for driver, even index for firmware */
+               idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
+               if (phy->beacon_rate != rate)
+                       mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);
 
-               /* must odd index */
-               idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
-               mt7996_mac_set_fixed_rate_table(dev, idx, rate);
                return idx;
        }
 
        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 MT7996_BASIC_RATES_TBL + 2 * i;
 
        return mvif->basic_rates_idx;
 }
@@ -965,7 +966,6 @@ 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 48c7f4fe1bc7c98e6e7d68898727643c14d2470f..a13ff8f7be54ad9d1da1aeee79e6e0086dc32ca2 100644 (file)
@@ -4179,6 +4179,35 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
                                     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 }
 
+int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+                                   u16 rate_idx, bool beacon)
+{
+#define UNI_FIXED_RATE_TABLE_SET       0
+#define SPE_IXD_SELECT_TXD             0
+#define SPE_IXD_SELECT_BMC_WTBL                1
+       struct mt7996_dev *dev = phy->dev;
+       struct fixed_rate_table_ctrl req = {
+               .tag = cpu_to_le16(UNI_FIXED_RATE_TABLE_SET),
+               .len = cpu_to_le16(sizeof(req) - 4),
+               .table_idx = table_idx,
+               .rate_idx = cpu_to_le16(rate_idx),
+               .gi = 1,
+               .he_ltf = 1,
+       };
+       u8 band_idx = phy->mt76->band_idx;
+
+       if (beacon) {
+               req.spe_idx_sel = SPE_IXD_SELECT_TXD;
+               req.spe_idx = 24 + band_idx;
+               phy->beacon_rate = rate_idx;
+       } else {
+               req.spe_idx_sel = SPE_IXD_SELECT_BMC_WTBL;
+       }
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(FIXED_RATE_TABLE),
+                                &req, sizeof(req), false);
+}
+
 int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
 {
        struct {
index 4a73850db9c074cd53e0344bbf028f670891d183..a2700151ee1c0ddac377f7b95a8a7c969b649939 100644 (file)
@@ -801,4 +801,24 @@ enum {
 #define MT7996_SEC_KEY_IDX             GENMASK(2, 1)
 #define MT7996_SEC_IV                  BIT(3)
 
+struct fixed_rate_table_ctrl {
+       u8 _rsv[4];
+
+       __le16 tag;
+       __le16 len;
+
+       u8 table_idx;
+       u8 antenna_idx;
+       __le16 rate_idx;
+       u8 spe_idx_sel;
+       u8 spe_idx;
+       u8 gi;
+       u8 he_ltf;
+       bool ldpc;
+       bool txbf;
+       bool dynamic_bw;
+
+       u8 _rsv2;
+} __packed;
+
 #endif
index 61e0f905d9023e5636c9a66cc26d9bf802bd34d5..ed99432b2d03b6573a176ce2f39897eb3c60c4d3 100644 (file)
@@ -47,7 +47,7 @@
 #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
+#define MT7996_BASIC_RATES_TBL         31
 #define MT7996_BEACON_RATES_TBL                25
 
 #define MT7996_THERMAL_THROTTLE_MAX    100
@@ -217,6 +217,8 @@ struct mt7996_phy {
 
        u8 rdd_state;
 
+       u16 beacon_rate;
+
        u32 rx_ampdu_ts;
        u32 ampdu_ref;
 
@@ -472,6 +474,8 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
                       u8 rx_sel, u8 val);
 int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
                                     struct cfg80211_chan_def *chandef);
+int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+                                   u16 rate_idx, bool beacon);
 int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
 int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
 int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val);
@@ -538,8 +542,6 @@ 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,