blob: c0ce85d879eaaf58b9995107e53d38e9b7ae970b [file] [log] [blame]
developer064da3c2023-06-13 15:57:26 +08001From 18f990de206c3301d3ae72cfeef40dfb3b361fb0 Mon Sep 17 00:00:00 2001
2From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Mon, 8 May 2023 09:03:50 +0800
4Subject: [PATCH 36/39] wifi: mt76: mt7996: enable SCS feature for mt7996
5 driver
6
7Enable Smart Carrier Sense algorithn by default to improve performance
8in a noisy environment.
9
10Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
11---
12 mt76_connac_mcu.h | 1 +
13 mt7996/init.c | 1 +
14 mt7996/main.c | 7 +++
15 mt7996/mcu.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
16 mt7996/mcu.h | 6 +++
17 mt7996/mt7996.h | 16 ++++++
18 6 files changed, 154 insertions(+)
19
20diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
21index 97f874b..bfec420 100644
22--- a/mt76_connac_mcu.h
23+++ b/mt76_connac_mcu.h
24@@ -1213,6 +1213,7 @@ enum {
25 MCU_UNI_CMD_GET_MIB_INFO = 0x22,
26 MCU_UNI_CMD_SNIFFER = 0x24,
27 MCU_UNI_CMD_SR = 0x25,
28+ MCU_UNI_CMD_SCS = 0x26,
29 MCU_UNI_CMD_ROC = 0x27,
30 MCU_UNI_CMD_TXPOWER = 0x2b,
31 MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
32diff --git a/mt7996/init.c b/mt7996/init.c
33index 0825e0b..1072874 100644
34--- a/mt7996/init.c
35+++ b/mt7996/init.c
36@@ -1058,6 +1058,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
37 dev->mt76.phy.priv = &dev->phy;
38 INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
39 INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
40+ INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll);
41 INIT_LIST_HEAD(&dev->sta_rc_list);
42 INIT_LIST_HEAD(&dev->sta_poll_list);
43 INIT_LIST_HEAD(&dev->twt_list);
44diff --git a/mt7996/main.c b/mt7996/main.c
45index 520f250..20b89a7 100644
46--- a/mt7996/main.c
47+++ b/mt7996/main.c
48@@ -73,11 +73,17 @@ int mt7996_run(struct ieee80211_hw *hw)
49 if (ret)
50 goto out;
51
52+ ret = mt7996_mcu_set_scs(phy, SCS_ENABLE);
53+ if (ret)
54+ goto out;
55+
56 set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
57
58 ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
59 MT7996_WATCHDOG_TIME);
60
61+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
62+
63 if (!running)
64 mt7996_mac_reset_counters(phy);
65
66@@ -105,6 +111,7 @@ static void mt7996_stop(struct ieee80211_hw *hw)
67 struct mt7996_phy *phy = mt7996_hw_phy(hw);
68
69 cancel_delayed_work_sync(&phy->mt76->mac_work);
70+ cancel_delayed_work_sync(&dev->scs_work);
71
72 mutex_lock(&dev->mt76.mutex);
73
74diff --git a/mt7996/mcu.c b/mt7996/mcu.c
75index 9fb800a..a5c473a 100644
76--- a/mt7996/mcu.c
77+++ b/mt7996/mcu.c
78@@ -4190,3 +4190,126 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
79 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TXPOWER),
80 &req, sizeof(req), false);
81 }
82+
83+int mt7996_mcu_set_scs_stats(struct mt7996_phy *phy)
84+{
85+ struct mt7996_scs_ctrl ctrl = phy->scs_ctrl;
86+ struct {
87+ u8 band_idx;
88+ u8 _rsv[3];
89+
90+ __le16 tag;
91+ __le16 len;
92+
93+ u8 _rsv2[6];
94+ s8 min_rssi;
95+ u8 _rsv3;
96+ } __packed req = {
97+ .band_idx = phy->mt76->band_idx,
98+ .tag = cpu_to_le16(UNI_CMD_SCS_SEND_DATA),
99+ .len = cpu_to_le16(sizeof(req) - 4),
100+
101+ .min_rssi = ctrl.sta_min_rssi,
102+ };
103+
104+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
105+ &req, sizeof(req), false);
106+}
107+
108+void mt7996_sta_rssi_work(void *data, struct ieee80211_sta *sta)
109+{
110+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
111+ struct mt7996_dev *dev = (struct mt7996_dev *)data;
112+ struct mt7996_phy *poll_phy;
113+ u8 band_idx = msta->wcid.phy_idx;
114+
115+ switch (band_idx) {
116+ case MT_BAND0:
117+ poll_phy = dev->mphy.priv;
118+ break;
119+ case MT_BAND1:
120+ poll_phy = mt7996_phy2(dev);
121+ break;
122+ case MT_BAND2:
123+ poll_phy = mt7996_phy3(dev);
124+ break;
125+ default:
126+ poll_phy = NULL;
127+ break;
128+ }
129+
130+ if (!poll_phy->scs_ctrl.scs_enable)
131+ return;
132+
133+ if (poll_phy->scs_ctrl.sta_min_rssi > msta->ack_signal)
134+ poll_phy->scs_ctrl.sta_min_rssi = msta->ack_signal;
135+}
136+
137+void mt7996_mcu_scs_sta_poll(struct work_struct *work)
138+{
139+ struct mt7996_dev *dev = container_of(work, struct mt7996_dev,
140+ scs_work.work);
141+ bool scs_enable_flag = false;
142+ u8 i;
143+
144+ ieee80211_iterate_stations_atomic(dev->mphy.hw, mt7996_sta_rssi_work, dev);
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+ scs_enable_flag = true;
167+ if (mt7996_mcu_set_scs_stats(phy))
168+ dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n");
169+ phy->scs_ctrl.sta_min_rssi = 0;
170+ }
171+ }
172+
173+ if (scs_enable_flag)
174+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
175+}
176+
177+
178+int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
179+{
180+ struct mt7996_dev *dev = phy->dev;
181+ struct {
182+ u8 band_idx;
183+ u8 _rsv[3];
184+
185+ __le16 tag;
186+ __le16 len;
187+
188+ u8 scs_enable;
189+ u8 _rsv2[3];
190+ } __packed req = {
191+ .band_idx = phy->mt76->band_idx,
192+ .tag = cpu_to_le16(UNI_CMD_SCS_ENABLE),
193+ .len = cpu_to_le16(sizeof(req) - 4),
194+ .scs_enable = enable,
195+ };
196+
197+ phy->scs_ctrl.scs_enable = enable;
198+
199+ if (enable == SCS_ENABLE)
200+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ);
201+
202+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
203+ &req, sizeof(req), false);
204+}
205diff --git a/mt7996/mcu.h b/mt7996/mcu.h
206index eed7371..eb63441 100644
207--- a/mt7996/mcu.h
208+++ b/mt7996/mcu.h
209@@ -757,6 +757,12 @@ enum {
210 MT7996_SEC_MODE_MAX,
211 };
212
213+enum {
214+ UNI_CMD_SCS_SEND_DATA,
215+ UNI_CMD_SCS_SET_PD_THR_RANGE = 2,
216+ UNI_CMD_SCS_ENABLE,
217+};
218+
219 #define MT7996_PATCH_SEC GENMASK(31, 24)
220 #define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8)
221 #define MT7996_PATCH_AES_KEY GENMASK(7, 0)
222diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
223index 488f59c..f78f1fd 100644
224--- a/mt7996/mt7996.h
225+++ b/mt7996/mt7996.h
226@@ -222,6 +222,17 @@ struct mt7996_hif {
227 int irq;
228 };
229
230+
231+struct mt7996_scs_ctrl {
232+ u8 scs_enable;
233+ s8 sta_min_rssi;
234+};
235+
236+enum {
237+ SCS_DISABLE = 0,
238+ SCS_ENABLE,
239+};
240+
241 struct mt7996_phy {
242 struct mt76_phy *mt76;
243 struct mt7996_dev *dev;
244@@ -253,6 +264,8 @@ struct mt7996_phy {
245
246 bool has_aux_rx;
247
248+ struct mt7996_scs_ctrl scs_ctrl;
249+
250 #ifdef CONFIG_NL80211_TESTMODE
251 struct {
252 u32 *reg_backup;
253@@ -295,6 +308,7 @@ struct mt7996_dev {
254 struct work_struct rc_work;
255 struct work_struct dump_work;
256 struct work_struct reset_work;
257+ struct delayed_work scs_work;
258 wait_queue_head_t reset_wait;
259 struct {
260 u32 state;
261@@ -535,6 +549,8 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
262 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
263 void mt7996_mcu_exit(struct mt7996_dev *dev);
264 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
265+int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
266+void mt7996_mcu_scs_sta_poll(struct work_struct *work);
267
268 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
269 {
270--
2712.18.0
272