| From de92f88f5c00cf1069df00bb89f50281b0b2d05e Mon Sep 17 00:00:00 2001 |
| From: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| Date: Fri, 12 May 2023 16:24:53 +0800 |
| Subject: [PATCH 37/39] wifi: mt76: mt7996: add beacon duplicate tx mode |
| support |
| |
| Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| --- |
| mt76_connac_mcu.h | 1 + |
| mt7996/init.c | 6 ++++-- |
| mt7996/mac.c | 11 ----------- |
| mt7996/main.c | 18 +++++++++--------- |
| mt7996/mcu.c | 30 ++++++++++++++++++++++++++++++ |
| mt7996/mcu.h | 20 ++++++++++++++++++++ |
| mt7996/mt7996.h | 8 +++++--- |
| 7 files changed, 69 insertions(+), 25 deletions(-) |
| |
| diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h |
| index bfec420..4bb9508 100644 |
| --- a/mt76_connac_mcu.h |
| +++ b/mt76_connac_mcu.h |
| @@ -1224,6 +1224,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_TESTMODE_CTRL = 0x46, |
| MCU_UNI_CMD_RRO = 0x57, |
| MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58, |
| diff --git a/mt7996/init.c b/mt7996/init.c |
| index 1072874..9eba689 100644 |
| --- a/mt7996/init.c |
| +++ b/mt7996/init.c |
| @@ -351,6 +351,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) |
| 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); |
| @@ -459,11 +460,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); |
| } |
| } |
| |
| diff --git a/mt7996/mac.c b/mt7996/mac.c |
| index 724af82..05269e7 100644 |
| --- a/mt7996/mac.c |
| +++ b/mt7996/mac.c |
| @@ -252,17 +252,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); |
| -} |
| - |
| static void |
| mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, |
| struct ieee80211_radiotap_he *he, |
| diff --git a/mt7996/main.c b/mt7996/main.c |
| index 20b89a7..2ed66e6 100644 |
| --- a/mt7996/main.c |
| +++ b/mt7996/main.c |
| @@ -544,24 +544,25 @@ 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, 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 = mt7996_hw_phy(hw); |
| + |
| + /* 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->mt76.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; |
| diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| index a5c473a..b34c6b7 100644 |
| --- a/mt7996/mcu.c |
| +++ b/mt7996/mcu.c |
| @@ -4056,6 +4056,36 @@ 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; |
| + req.spe_idx = 0; |
| + } |
| + |
| + 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 { |
| diff --git a/mt7996/mcu.h b/mt7996/mcu.h |
| index eb63441..e32767e 100644 |
| --- a/mt7996/mcu.h |
| +++ b/mt7996/mcu.h |
| @@ -771,4 +771,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 rsv[1]; |
| +} __packed; |
| + |
| #endif |
| diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
| index f78f1fd..286fc1e 100644 |
| --- a/mt7996/mt7996.h |
| +++ b/mt7996/mt7996.h |
| @@ -48,7 +48,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 |
| @@ -256,6 +256,8 @@ struct mt7996_phy { |
| |
| u8 rdd_state; |
| |
| + u16 beacon_rate; |
| + |
| u32 rx_ampdu_ts; |
| u32 ampdu_ref; |
| |
| @@ -539,6 +541,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, u8 val); |
| @@ -606,8 +610,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, |
| -- |
| 2.18.0 |
| |