developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame^] | 1 | From d5f1a204501372080b078364e41762992e81eec6 Mon Sep 17 00:00:00 2001 |
| 2 | From: Howard Hsu <howard-yh.hsu@mediatek.com> |
| 3 | Date: Mon, 8 May 2023 09:03:50 +0800 |
| 4 | Subject: [PATCH 025/116] mtk: wifi: mt76: mt7996: enable SCS feature for |
| 5 | mt7996 driver |
| 6 | |
| 7 | Enable Smart Carrier Sense algorithn by default to improve performance |
| 8 | in a noisy environment. |
| 9 | |
| 10 | Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com> |
| 11 | --- |
| 12 | mt76_connac_mcu.h | 1 + |
| 13 | mt7996/init.c | 1 + |
| 14 | mt7996/mac.c | 2 + |
| 15 | mt7996/main.c | 7 +++ |
| 16 | mt7996/mcu.c | 105 +++++++++++++++++++++++++++++++++++++++++++ |
| 17 | mt7996/mcu.h | 6 +++ |
| 18 | mt7996/mt7996.h | 15 +++++++ |
| 19 | mt7996/mtk_debugfs.c | 11 +++++ |
| 20 | 8 files changed, 148 insertions(+) |
| 21 | |
| 22 | diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h |
| 23 | index c785edb80..d8830dc25 100644 |
| 24 | --- a/mt76_connac_mcu.h |
| 25 | +++ b/mt76_connac_mcu.h |
| 26 | @@ -1262,6 +1262,7 @@ enum { |
| 27 | MCU_UNI_CMD_GET_STAT_INFO = 0x23, |
| 28 | MCU_UNI_CMD_SNIFFER = 0x24, |
| 29 | MCU_UNI_CMD_SR = 0x25, |
| 30 | + MCU_UNI_CMD_SCS = 0x26, |
| 31 | MCU_UNI_CMD_ROC = 0x27, |
| 32 | MCU_UNI_CMD_SET_DBDC_PARMS = 0x28, |
| 33 | MCU_UNI_CMD_TXPOWER = 0x2b, |
| 34 | diff --git a/mt7996/init.c b/mt7996/init.c |
| 35 | index 201daf110..6a394c364 100644 |
| 36 | --- a/mt7996/init.c |
| 37 | +++ b/mt7996/init.c |
| 38 | @@ -1415,6 +1415,7 @@ int mt7996_register_device(struct mt7996_dev *dev) |
| 39 | dev->mt76.phy.priv = &dev->phy; |
| 40 | INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work); |
| 41 | INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work); |
| 42 | + INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll); |
| 43 | INIT_LIST_HEAD(&dev->sta_rc_list); |
| 44 | INIT_LIST_HEAD(&dev->twt_list); |
| 45 | |
| 46 | diff --git a/mt7996/mac.c b/mt7996/mac.c |
| 47 | index 603f6c0d7..c9f45abef 100644 |
| 48 | --- a/mt7996/mac.c |
| 49 | +++ b/mt7996/mac.c |
| 50 | @@ -1795,6 +1795,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev) |
| 51 | cancel_delayed_work_sync(&phy2->mt76->mac_work); |
| 52 | if (phy3) |
| 53 | cancel_delayed_work_sync(&phy3->mt76->mac_work); |
| 54 | + cancel_delayed_work_sync(&dev->scs_work); |
| 55 | |
| 56 | mutex_lock(&dev->mt76.mutex); |
| 57 | for (i = 0; i < 10; i++) { |
| 58 | @@ -1830,6 +1831,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev) |
| 59 | ieee80211_queue_delayed_work(phy3->mt76->hw, |
| 60 | &phy3->mt76->mac_work, |
| 61 | MT7996_WATCHDOG_TIME); |
| 62 | + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); |
| 63 | } |
| 64 | |
| 65 | void mt7996_mac_reset_work(struct work_struct *work) |
| 66 | diff --git a/mt7996/main.c b/mt7996/main.c |
| 67 | index 479940095..57865f1de 100644 |
| 68 | --- a/mt7996/main.c |
| 69 | +++ b/mt7996/main.c |
| 70 | @@ -81,11 +81,17 @@ int mt7996_run(struct ieee80211_hw *hw) |
| 71 | if (ret) |
| 72 | goto out; |
| 73 | |
| 74 | + ret = mt7996_mcu_set_scs(phy, SCS_ENABLE); |
| 75 | + if (ret) |
| 76 | + goto out; |
| 77 | + |
| 78 | set_bit(MT76_STATE_RUNNING, &phy->mt76->state); |
| 79 | |
| 80 | ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, |
| 81 | MT7996_WATCHDOG_TIME); |
| 82 | |
| 83 | + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); |
| 84 | + |
| 85 | if (!running) |
| 86 | mt7996_mac_reset_counters(phy); |
| 87 | |
| 88 | @@ -113,6 +119,7 @@ static void mt7996_stop(struct ieee80211_hw *hw) |
| 89 | struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| 90 | |
| 91 | cancel_delayed_work_sync(&phy->mt76->mac_work); |
| 92 | + cancel_delayed_work_sync(&dev->scs_work); |
| 93 | |
| 94 | mutex_lock(&dev->mt76.mutex); |
| 95 | |
| 96 | diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| 97 | index a006b0e34..2650dc6ff 100644 |
| 98 | --- a/mt7996/mcu.c |
| 99 | +++ b/mt7996/mcu.c |
| 100 | @@ -4813,3 +4813,108 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da |
| 101 | return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TXPOWER), |
| 102 | &req, sizeof(req), false); |
| 103 | } |
| 104 | + |
| 105 | +int mt7996_mcu_set_scs_stats(struct mt7996_phy *phy) |
| 106 | +{ |
| 107 | + struct mt7996_scs_ctrl ctrl = phy->scs_ctrl; |
| 108 | + struct { |
| 109 | + u8 band_idx; |
| 110 | + u8 _rsv[3]; |
| 111 | + |
| 112 | + __le16 tag; |
| 113 | + __le16 len; |
| 114 | + |
| 115 | + u8 _rsv2[6]; |
| 116 | + s8 min_rssi; |
| 117 | + u8 _rsv3; |
| 118 | + } __packed req = { |
| 119 | + .band_idx = phy->mt76->band_idx, |
| 120 | + .tag = cpu_to_le16(UNI_CMD_SCS_SEND_DATA), |
| 121 | + .len = cpu_to_le16(sizeof(req) - 4), |
| 122 | + |
| 123 | + .min_rssi = ctrl.sta_min_rssi, |
| 124 | + }; |
| 125 | + |
| 126 | + return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS), |
| 127 | + &req, sizeof(req), false); |
| 128 | +} |
| 129 | + |
| 130 | +void mt7996_sta_rssi_work(void *data, struct ieee80211_sta *sta) |
| 131 | +{ |
| 132 | + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; |
| 133 | + struct mt7996_phy *poll_phy = (struct mt7996_phy *) data; |
| 134 | + |
| 135 | + if (poll_phy->scs_ctrl.sta_min_rssi > msta->ack_signal) |
| 136 | + poll_phy->scs_ctrl.sta_min_rssi = msta->ack_signal; |
| 137 | +} |
| 138 | + |
| 139 | +void mt7996_mcu_scs_sta_poll(struct work_struct *work) |
| 140 | +{ |
| 141 | + struct mt7996_dev *dev = container_of(work, struct mt7996_dev, |
| 142 | + scs_work.work); |
| 143 | + bool scs_enable_flag = false; |
| 144 | + u8 i; |
| 145 | + |
| 146 | + for (i = 0; i < __MT_MAX_BAND; i++) { |
| 147 | + struct mt7996_phy *phy; |
| 148 | + |
| 149 | + switch (i) { |
| 150 | + case MT_BAND0: |
| 151 | + phy = dev->mphy.priv; |
| 152 | + break; |
| 153 | + case MT_BAND1: |
| 154 | + phy = mt7996_phy2(dev); |
| 155 | + break; |
| 156 | + case MT_BAND2: |
| 157 | + phy = mt7996_phy3(dev); |
| 158 | + break; |
| 159 | + default: |
| 160 | + phy = NULL; |
| 161 | + break; |
| 162 | + } |
| 163 | + |
| 164 | + if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state) || |
| 165 | + !phy->scs_ctrl.scs_enable) |
| 166 | + continue; |
| 167 | + |
| 168 | + ieee80211_iterate_stations_atomic(phy->mt76->hw, |
| 169 | + mt7996_sta_rssi_work, phy); |
| 170 | + |
| 171 | + scs_enable_flag = true; |
| 172 | + if (mt7996_mcu_set_scs_stats(phy)) |
| 173 | + dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n"); |
| 174 | + phy->scs_ctrl.sta_min_rssi = 0; |
| 175 | + } |
| 176 | + |
| 177 | + if (scs_enable_flag) |
| 178 | + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); |
| 179 | +} |
| 180 | + |
| 181 | + |
| 182 | +int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable) |
| 183 | +{ |
| 184 | + struct mt7996_dev *dev = phy->dev; |
| 185 | + struct { |
| 186 | + u8 band_idx; |
| 187 | + u8 _rsv[3]; |
| 188 | + |
| 189 | + __le16 tag; |
| 190 | + __le16 len; |
| 191 | + |
| 192 | + u8 scs_enable; |
| 193 | + u8 _rsv2[3]; |
| 194 | + } __packed req = { |
| 195 | + .band_idx = phy->mt76->band_idx, |
| 196 | + .tag = cpu_to_le16(UNI_CMD_SCS_ENABLE), |
| 197 | + .len = cpu_to_le16(sizeof(req) - 4), |
| 198 | + .scs_enable = enable, |
| 199 | + }; |
| 200 | + |
| 201 | + phy->scs_ctrl.scs_enable = enable; |
| 202 | + |
| 203 | + if (enable == SCS_ENABLE) |
| 204 | + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); |
| 205 | + |
| 206 | + return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS), |
| 207 | + &req, sizeof(req), false); |
| 208 | +} |
| 209 | diff --git a/mt7996/mcu.h b/mt7996/mcu.h |
| 210 | index d5ac2b38e..5953b25e8 100644 |
| 211 | --- a/mt7996/mcu.h |
| 212 | +++ b/mt7996/mcu.h |
| 213 | @@ -966,6 +966,12 @@ enum pp_mode { |
| 214 | PP_USR_MODE, |
| 215 | }; |
| 216 | |
| 217 | +enum { |
| 218 | + UNI_CMD_SCS_SEND_DATA, |
| 219 | + UNI_CMD_SCS_SET_PD_THR_RANGE = 2, |
| 220 | + UNI_CMD_SCS_ENABLE, |
| 221 | +}; |
| 222 | + |
| 223 | #define MT7996_PATCH_SEC GENMASK(31, 24) |
| 224 | #define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8) |
| 225 | #define MT7996_PATCH_AES_KEY GENMASK(7, 0) |
| 226 | diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
| 227 | index 5e2d8bef0..186af3c1d 100644 |
| 228 | --- a/mt7996/mt7996.h |
| 229 | +++ b/mt7996/mt7996.h |
| 230 | @@ -234,6 +234,16 @@ struct mt7996_hif { |
| 231 | int irq; |
| 232 | }; |
| 233 | |
| 234 | +struct mt7996_scs_ctrl { |
| 235 | + u8 scs_enable; |
| 236 | + s8 sta_min_rssi; |
| 237 | +}; |
| 238 | + |
| 239 | +enum { |
| 240 | + SCS_DISABLE = 0, |
| 241 | + SCS_ENABLE, |
| 242 | +}; |
| 243 | + |
| 244 | struct mt7996_wed_rro_addr { |
| 245 | u32 head_low; |
| 246 | u32 head_high : 4; |
| 247 | @@ -284,6 +294,8 @@ struct mt7996_phy { |
| 248 | u8 pp_mode; |
| 249 | u16 punct_bitmap; |
| 250 | |
| 251 | + struct mt7996_scs_ctrl scs_ctrl; |
| 252 | + |
| 253 | #ifdef CONFIG_NL80211_TESTMODE |
| 254 | struct { |
| 255 | u32 *reg_backup; |
| 256 | @@ -330,6 +342,7 @@ struct mt7996_dev { |
| 257 | struct work_struct rc_work; |
| 258 | struct work_struct dump_work; |
| 259 | struct work_struct reset_work; |
| 260 | + struct delayed_work scs_work; |
| 261 | wait_queue_head_t reset_wait; |
| 262 | struct { |
| 263 | u32 state; |
| 264 | @@ -604,6 +617,8 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy); |
| 265 | #ifdef CONFIG_NL80211_TESTMODE |
| 266 | void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb); |
| 267 | #endif |
| 268 | +int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable); |
| 269 | +void mt7996_mcu_scs_sta_poll(struct work_struct *work); |
| 270 | |
| 271 | static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev) |
| 272 | { |
| 273 | diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c |
| 274 | index 8baf27c76..9b4d5f68c 100644 |
| 275 | --- a/mt7996/mtk_debugfs.c |
| 276 | +++ b/mt7996/mtk_debugfs.c |
| 277 | @@ -2430,6 +2430,16 @@ static int mt7996_token_read(struct seq_file *s, void *data) |
| 278 | return 0; |
| 279 | } |
| 280 | |
| 281 | +static int |
| 282 | +mt7996_scs_enable_set(void *data, u64 val) |
| 283 | +{ |
| 284 | + struct mt7996_phy *phy = data; |
| 285 | + |
| 286 | + return mt7996_mcu_set_scs(phy, (u8) val); |
| 287 | +} |
| 288 | +DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL, |
| 289 | + mt7996_scs_enable_set, "%lld\n"); |
| 290 | + |
| 291 | int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
| 292 | { |
| 293 | struct mt7996_dev *dev = phy->dev; |
| 294 | @@ -2500,6 +2510,7 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
| 295 | debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, mt7996_token_read); |
| 296 | |
| 297 | debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); |
| 298 | + debugfs_create_file("scs_enable", 0200, dir, phy, &fops_scs_enable); |
| 299 | |
| 300 | return 0; |
| 301 | } |
| 302 | -- |
| 303 | 2.39.2 |
| 304 | |