blob: 7b2b8dea6b4cee3733e9c5f3821360dc5f9128f3 [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From a2ca9b9f2be2bd336db4c3e6a2f6693d6e2236b4 Mon Sep 17 00:00:00 2001
2From: Allen Ye <allen.ye@mediatek.com>
3Date: Tue, 28 May 2024 15:39:06 +0800
4Subject: [PATCH 176/199] mtk: mt76: Add dynamic pp vendor and debug pp algo
5 cmd support
6
7Add dynamic pp vendor and debug pp algo cmd support.
81. Add support channel switch with a punct bitmap.
92. Add pp event for fw mode and trigger a channel switch by hostapd.
103. Add pp algo dump cmd to get current fw punct bitmap and mode.
11
12When extender sta have not connected to root ap and the chandef is null.
13mt76 just ignore the event. Once the sta connect to ap, the sta part would
14send a new fw cmd to update the pp bitmap.
15
16Signed-off-by: Allen Ye <allen.ye@mediatek.com>
17---
18 mt7996/mcu.c | 70 ++++++++++++++++++++++++++++-
19 mt7996/mcu.h | 38 ++++++++++++++++
20 mt7996/mt7996.h | 2 +
21 mt7996/mtk_debugfs.c | 14 ++++++
22 mt7996/vendor.c | 103 +++++++++++++++++++++++++++++++------------
23 mt7996/vendor.h | 8 +++-
24 6 files changed, 205 insertions(+), 30 deletions(-)
25
26diff --git a/mt7996/mcu.c b/mt7996/mcu.c
27index adb71bf5..00bc675e 100644
28--- a/mt7996/mcu.c
29+++ b/mt7996/mcu.c
30@@ -1280,6 +1280,39 @@ mt7996_mcu_wed_rro_event(struct mt7996_dev *dev, struct sk_buff *skb)
31 }
32 }
33
34+void
35+mt7996_dump_pp_statistic_event(struct mt7996_dev *dev,
36+ struct mt7996_mcu_pp_alg_ctrl_event *event)
37+{
38+ u32 unit_time = le32_to_cpu(event->pp_timer_intv);
39+
40+ dev_info(dev->mt76.dev, "band idx = %u\n", le32_to_cpu(event->band_idx));
41+ dev_info(dev->mt76.dev, "x2 value = %u\n", le32_to_cpu(event->thr_x2_value));
42+ dev_info(dev->mt76.dev, "x2 shift = %u\n", le32_to_cpu(event->thr_x2_shift));
43+ dev_info(dev->mt76.dev, "x3 value = %u\n", le32_to_cpu(event->thr_x3_value));
44+ dev_info(dev->mt76.dev, "x3 shift = %u\n", le32_to_cpu(event->thr_x3_shift));
45+ dev_info(dev->mt76.dev, "x4 value = %u\n", le32_to_cpu(event->thr_x4_value));
46+ dev_info(dev->mt76.dev, "x4 shift = %u\n", le32_to_cpu(event->thr_x4_shift));
47+ dev_info(dev->mt76.dev, "x5 value = %u\n", le32_to_cpu(event->thr_x5_value));
48+ dev_info(dev->mt76.dev, "x5 shift = %u\n", le32_to_cpu(event->thr_x5_shift));
49+ dev_info(dev->mt76.dev, "x6 value = %u\n", le32_to_cpu(event->thr_x6_value));
50+ dev_info(dev->mt76.dev, "x6 shift = %u\n", le32_to_cpu(event->thr_x6_shift));
51+ dev_info(dev->mt76.dev, "x7 value = %u\n", le32_to_cpu(event->thr_x7_value));
52+ dev_info(dev->mt76.dev, "x7 shift = %u\n", le32_to_cpu(event->thr_x7_shift));
53+ dev_info(dev->mt76.dev, "x8 value = %u\n", le32_to_cpu(event->thr_x8_value));
54+ dev_info(dev->mt76.dev, "x8 shift = %u\n", le32_to_cpu(event->thr_x8_shift));
55+ dev_info(dev->mt76.dev, "sw_pp_time = %u (Unit: %u ms)\n",
56+ le32_to_cpu(event->sw_pp_time), unit_time);
57+ dev_info(dev->mt76.dev, "hw_pp_time = %u (Unit: %u ms)\n",
58+ le32_to_cpu(event->hw_pp_time), unit_time);
59+ dev_info(dev->mt76.dev, "no_pp_time = %u (Unit: %u ms)\n",
60+ le32_to_cpu(event->no_pp_time), unit_time);
61+ dev_info(dev->mt76.dev, "auto_bw_time = %u (Unit: %u ms)\n",
62+ le32_to_cpu(event->auto_bw_time), unit_time);
63+ dev_info(dev->mt76.dev, "punct_bitmap = 0x%04x\n",
64+ le16_to_cpu(event->punct_bitmap));
65+}
66+
67 static void
68 mt7996_mcu_pp_event(struct mt7996_dev *dev, struct sk_buff *skb)
69 {
70@@ -1306,9 +1339,13 @@ mt7996_mcu_pp_event(struct mt7996_dev *dev, struct sk_buff *skb)
71 if (phy->punct_bitmap == report_bitmap)
72 return;
73
74- if (phy->pp_mode == PP_FW_MODE)
75+ if (phy->pp_mode == PP_FW_MODE) {
76 phy->punct_bitmap = report_bitmap;
77-
78+ mt7996_vendor_pp_bitmap_update(phy, report_bitmap);
79+ }
80+ break;
81+ case UNI_EVENT_PP_TAG_ALG_CTRL:
82+ mt7996_dump_pp_statistic_event(dev, (struct mt7996_mcu_pp_alg_ctrl_event *)event);
83 break;
84 }
85 }
86@@ -6405,6 +6442,35 @@ int mt7996_mcu_set_pp_sta_dscb(struct mt7996_phy *phy,
87 &req, sizeof(req), false);
88 }
89
90+int mt7996_mcu_set_pp_alg_ctrl(struct mt7996_phy *phy, u8 action)
91+{
92+ struct mt7996_dev *dev = phy->dev;
93+ struct {
94+ u8 _rsv1[4];
95+
96+ __le16 tag;
97+ __le16 len;
98+
99+ __le32 pp_timer_intv;
100+ __le32 rsv2[14];
101+ u8 band_idx;
102+ u8 pp_action;
103+ u8 reset;
104+ u8 _rsv3;
105+ } __packed req = {
106+ .tag = cpu_to_le16(UNI_CMD_PP_ALG_CTRL),
107+ .len = cpu_to_le16(sizeof(req) - 4),
108+
109+ .pp_timer_intv = action == PP_ALG_SET_TIMER ? 2000 : 0,
110+ .band_idx = phy->mt76->band_idx,
111+ .pp_action = action,
112+ .reset = 0,
113+ };
114+
115+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP),
116+ &req, sizeof(req), false);
117+}
118+
119 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
120 {
121 struct mt7996_dev *dev = phy->dev;
122diff --git a/mt7996/mcu.h b/mt7996/mcu.h
123index 011b6c7a..01eb0ea1 100644
124--- a/mt7996/mcu.h
125+++ b/mt7996/mcu.h
126@@ -1162,6 +1162,7 @@ enum {
127
128 enum {
129 UNI_CMD_PP_EN_CTRL,
130+ UNI_CMD_PP_ALG_CTRL,
131 UNI_CMD_PP_DSCB_CTRL,
132 };
133
134@@ -1171,6 +1172,11 @@ enum pp_mode {
135 PP_USR_MODE,
136 };
137
138+enum pp_alg_action {
139+ PP_ALG_SET_TIMER,
140+ PP_ALG_GET_STATISTICS = 2,
141+};
142+
143 enum {
144 UNI_EVENT_PP_TAG_ALG_CTRL = 1,
145 UNI_EVENT_STATIC_PP_TAG_DSCB_IE,
146@@ -1204,6 +1210,38 @@ struct mt7996_mcu_pp_dscb_event {
147 u8 __rsv3[2];
148 } __packed;
149
150+struct mt7996_mcu_pp_alg_ctrl_event {
151+ struct mt7996_mcu_rxd rxd;
152+
153+ u8 __rsv1[4];
154+
155+ __le16 tag;
156+ __le16 len;
157+
158+ __le32 pp_timer_intv;
159+ __le32 thr_x2_value;
160+ __le32 thr_x2_shift;
161+ __le32 thr_x3_value;
162+ __le32 thr_x3_shift;
163+ __le32 thr_x4_value;
164+ __le32 thr_x4_shift;
165+ __le32 thr_x5_value;
166+ __le32 thr_x5_shift;
167+ __le32 thr_x6_value;
168+ __le32 thr_x6_shift;
169+ __le32 thr_x7_value;
170+ __le32 thr_x7_shift;
171+ __le32 thr_x8_value;
172+ __le32 thr_x8_shift;
173+ __le32 sw_pp_time;
174+ __le32 hw_pp_time;
175+ __le32 no_pp_time;
176+ __le32 auto_bw_time;
177+ u8 band_idx;
178+ u8 __rsv2;
179+ __le16 punct_bitmap;
180+} __packed;
181+
182 enum {
183 UNI_CMD_SCS_SEND_DATA,
184 UNI_CMD_SCS_SET_PD_THR_RANGE = 2,
185diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
186index f31d3f36..74c32827 100644
187--- a/mt7996/mt7996.h
188+++ b/mt7996/mt7996.h
189@@ -1278,6 +1278,7 @@ int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
190 int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, u8 mode, u16 bitmap);
191 int mt7996_mcu_set_pp_sta_dscb(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef,
192 u8 omac_idx);
193+int mt7996_mcu_set_pp_alg_ctrl(struct mt7996_phy *phy, u8 action);
194 int mt7996_mcu_set_eml_omn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 link_id,
195 struct ieee80211_sta *sta, struct mt7996_eml_omn *eml_omn);
196 #ifdef CONFIG_MAC80211_DEBUGFS
197@@ -1307,6 +1308,7 @@ int mt7996_mcu_set_muru_cfg(struct mt7996_dev *dev, void *data);
198 void mt7996_set_beacon_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
199 int mt7996_mcu_set_csi(struct mt7996_phy *phy, u8 mode,
200 u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
201+int mt7996_vendor_pp_bitmap_update(struct mt7996_phy *phy, u16 bitmap);
202 #endif
203
204 int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
205diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
206index b698c68a..093f3c69 100644
207--- a/mt7996/mtk_debugfs.c
208+++ b/mt7996/mtk_debugfs.c
209@@ -4368,6 +4368,18 @@ static const struct file_operations fops_muru_dbg_info = {
210 .llseek = default_llseek,
211 };
212
213+static int mt7996_pp_alg_show(struct seq_file *s, void *data)
214+{
215+ struct mt7996_phy *phy = s->private;
216+ struct mt7996_dev *dev = phy->dev;
217+
218+ dev_info(dev->mt76.dev, "pp_mode = %d\n", phy->pp_mode);
219+ mt7996_mcu_set_pp_alg_ctrl(phy, PP_ALG_GET_STATISTICS);
220+
221+ return 0;
222+}
223+DEFINE_SHOW_ATTRIBUTE(mt7996_pp_alg);
224+
225 void mt7996_mtk_init_band_debugfs(struct mt7996_phy *phy, struct dentry *dir)
226 {
227 /* agg */
228@@ -4390,6 +4402,8 @@ void mt7996_mtk_init_band_debugfs(struct mt7996_phy *phy, struct dentry *dir)
229
230 debugfs_create_file("thermal_enable", 0600, dir, phy, &fops_thermal_enable);
231 debugfs_create_file("scs_enable", 0200, dir, phy, &fops_scs_enable);
232+
233+ debugfs_create_file("pp_alg", 0200, dir, phy, &mt7996_pp_alg_fops);
234 }
235
236 void mt7996_mtk_init_dev_debugfs(struct mt7996_dev *dev, struct dentry *dir)
237diff --git a/mt7996/vendor.c b/mt7996/vendor.c
238index 33c682c0..d7973c5e 100644
239--- a/mt7996/vendor.c
240+++ b/mt7996/vendor.c
241@@ -96,7 +96,9 @@ ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
242 static struct nla_policy
243 pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
244 [MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
245- [MTK_VENDOR_ATTR_PP_BAND_IDX] = { .type = NLA_U8 },
246+ [MTK_VENDOR_ATTR_PP_LINK_ID] = { .type = NLA_U8 },
247+ [MTK_VENDOR_ATTR_PP_BITMAP] = { .type = NLA_U16 },
248+ [MTK_VENDOR_ATTR_PP_CURR_FREQ] = { .type = NLA_U32 },
249 };
250
251 static const struct nla_policy
252@@ -805,31 +807,44 @@ static int mt7996_vendor_pp_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
253 const void *data, int data_len)
254 {
255 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
256+ struct ieee80211_vif *vif = wdev_to_ieee80211_vif(wdev);
257 struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_PP_CTRL];
258 struct mt7996_dev *dev = mt7996_hw_dev(hw);
259 struct mt7996_phy *phy;
260- struct mt76_phy *mphy;
261 struct cfg80211_chan_def *chandef;
262+ struct mt7996_bss_conf *mconf;
263+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
264 int err;
265- u8 val8, band_idx = 0;
266+ u8 mode = 0, link_id = 0;
267+ u16 punct_bitmap = 0;
268
269 err = nla_parse(tb, MTK_VENDOR_ATTR_PP_CTRL_MAX, data, data_len,
270 pp_ctrl_policy, NULL);
271
272- if (tb[MTK_VENDOR_ATTR_PP_BAND_IDX]) {
273- band_idx = nla_get_u8(tb[MTK_VENDOR_ATTR_PP_BAND_IDX]);
274- }
275+ if (tb[MTK_VENDOR_ATTR_PP_MODE])
276+ mode = nla_get_u8(tb[MTK_VENDOR_ATTR_PP_MODE]);
277+ else
278+ return -EINVAL;
279
280- if (!mt7996_band_valid(dev, band_idx))
281- goto error;
282+ if (ieee80211_vif_is_mld(vif) && tb[MTK_VENDOR_ATTR_PP_LINK_ID]) {
283+ link_id = nla_get_u8(tb[MTK_VENDOR_ATTR_PP_LINK_ID]);
284+ if (link_id >= IEEE80211_LINK_UNSPECIFIED)
285+ return -EINVAL;
286+ }
287
288- mphy = dev->mt76.phys[band_idx];
289- if (!mphy)
290+ rcu_read_lock();
291+ mconf = rcu_dereference(mvif->link[link_id]);
292+ if (!mconf) {
293+ rcu_read_unlock();
294 goto error;
295+ }
296
297- phy = (struct mt7996_phy *)mphy->priv;
298- if (!phy)
299+ phy = mconf->phy;
300+ if (!phy) {
301+ rcu_read_unlock();
302 goto error;
303+ }
304+ rcu_read_unlock();
305
306 chandef = &phy->chanctx->chandef;
307 if (!chandef)
308@@ -838,28 +853,53 @@ static int mt7996_vendor_pp_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
309 if (chandef->chan->band == NL80211_BAND_2GHZ)
310 return 0;
311
312- if (tb[MTK_VENDOR_ATTR_PP_MODE]) {
313- val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_PP_MODE]);
314- switch (val8) {
315- case PP_DISABLE:
316- case PP_FW_MODE:
317- err = mt7996_mcu_set_pp_en(phy, val8, 0);
318- break;
319- case PP_USR_MODE:
320- /* handled by add_chanctx */
321- err = 0;
322- break;
323- default:
324- err = -EINVAL;
325- }
326+ switch (mode) {
327+ case PP_USR_MODE:
328+ if (tb[MTK_VENDOR_ATTR_PP_BITMAP])
329+ punct_bitmap = nla_get_u16(tb[MTK_VENDOR_ATTR_PP_BITMAP]);
330+ fallthrough;
331+ case PP_FW_MODE:
332+ case PP_DISABLE:
333+ err = mt7996_mcu_set_pp_en(phy, mode, punct_bitmap);
334+ break;
335+ default:
336+ return -EINVAL;
337 }
338
339 return err;
340 error:
341- dev_err(dev->mt76.dev, "Invalid band idx: %d\n", band_idx);
342+ dev_err(dev->mt76.dev, "Invalid link id: %d\n", link_id);
343 return -EINVAL;
344 }
345
346+int mt7996_vendor_pp_bitmap_update(struct mt7996_phy *phy, u16 bitmap)
347+{
348+ struct sk_buff *skb;
349+ struct mt76_phy *mphy = phy->mt76;
350+ struct cfg80211_chan_def *chandef = &phy->chanctx->chandef;
351+
352+ if (!chandef)
353+ return 0;
354+
355+ skb = cfg80211_vendor_event_alloc(mphy->hw->wiphy, NULL, 20,
356+ MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE,
357+ GFP_ATOMIC);
358+
359+ if (!skb)
360+ return -ENOMEM;
361+
362+ if (nla_put_u16(skb, MTK_VENDOR_ATTR_PP_BITMAP, bitmap) ||
363+ nla_put_u32(skb, MTK_VENDOR_ATTR_PP_CURR_FREQ,
364+ chandef->chan->center_freq)) {
365+ dev_kfree_skb(skb);
366+ return -ENOMEM;
367+ }
368+
369+ cfg80211_vendor_event(skb, GFP_ATOMIC);
370+
371+ return 0;
372+}
373+
374 static int mt7996_vendor_rfeature_ctrl(struct wiphy *wiphy,
375 struct wireless_dev *wdev,
376 const void *data,
377@@ -1490,10 +1530,19 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
378 },
379 };
380
381+static const struct nl80211_vendor_cmd_info mt7996_vendor_events[] = {
382+ [MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE] = {
383+ .vendor_id = MTK_NL80211_VENDOR_ID,
384+ .subcmd = MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE,
385+ },
386+};
387+
388 void mt7996_vendor_register(struct mt7996_phy *phy)
389 {
390 phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
391 phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
392+ phy->mt76->hw->wiphy->vendor_events = mt7996_vendor_events;
393+ phy->mt76->hw->wiphy->n_vendor_events = ARRAY_SIZE(mt7996_vendor_events);
394
395 INIT_LIST_HEAD(&phy->csi.list);
396 spin_lock_init(&phy->csi.lock);
397diff --git a/mt7996/vendor.h b/mt7996/vendor.h
398index 714f0b3e..ca4f00ad 100644
399--- a/mt7996/vendor.h
400+++ b/mt7996/vendor.h
401@@ -21,6 +21,10 @@ enum mtk_nl80211_vendor_subcmds {
402 MTK_NL80211_VENDOR_SUBCMD_EML_CTRL = 0xd3,
403 };
404
405+enum mtk_nl80211_vendor_events {
406+ MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE = 0x5,
407+};
408+
409 enum mtk_vendor_attr_edcca_ctrl {
410 MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
411
412@@ -222,7 +226,9 @@ enum mtk_vendor_attr_pp_ctrl {
413 MTK_VENDOR_ATTR_PP_CTRL_UNSPEC,
414
415 MTK_VENDOR_ATTR_PP_MODE,
416- MTK_VENDOR_ATTR_PP_BAND_IDX,
417+ MTK_VENDOR_ATTR_PP_LINK_ID,
418+ MTK_VENDOR_ATTR_PP_BITMAP,
419+ MTK_VENDOR_ATTR_PP_CURR_FREQ,
420
421 /* keep last */
422 NUM_MTK_VENDOR_ATTRS_PP_CTRL,
423--
4242.18.0
425