blob: 19ea96886f51852dc98cd56a5816e4b80543efb2 [file] [log] [blame]
developer9237f442024-06-14 17:13:04 +08001From 501b857b081c10d3400c8b4374db346b238d3f72 Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 28 Dec 2022 22:24:25 +0800
developer9237f442024-06-14 17:13:04 +08004Subject: [PATCH 021/116] mtk: wifi: mt76: testmode: add basic testmode support
developer66e89bc2024-04-23 14:50:01 +08005
6Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer66e89bc2024-04-23 14:50:01 +08007
8Add testmode eeprom buffer mode support
9
developer66e89bc2024-04-23 14:50:01 +080010Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
11
12Fix power & freq offset issue for iTest power cal & tx/rx verifcation
131. Wait for fw to tx. Otherwise, iTest testing tool cannot get the
14accurate tx power.
152. In crystal mode, freq offset is set in 6G band and forwarded to 5G
16and 2G band. Therefore, we should avoid reseting freq offset to 0 when
176G interface is off.
18
developer66e89bc2024-04-23 14:50:01 +080019Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer66e89bc2024-04-23 14:50:01 +080020
21edcca return err in testmode; therefore, bypass it when we are in testmode idle state or testmode bf is on
22
developer66e89bc2024-04-23 14:50:01 +080023Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
24---
25 eeprom.c | 6 +-
26 mac80211.c | 3 +-
27 mt76.h | 36 +++
28 mt76_connac_mcu.h | 2 +
29 mt7996/Makefile | 1 +
30 mt7996/eeprom.c | 37 ++-
31 mt7996/eeprom.h | 1 +
32 mt7996/init.c | 8 +
33 mt7996/mac.c | 3 +-
34 mt7996/main.c | 27 ++
35 mt7996/mcu.c | 59 +++-
36 mt7996/mcu.h | 33 +++
37 mt7996/mt7996.h | 28 +-
38 mt7996/testmode.c | 740 ++++++++++++++++++++++++++++++++++++++++++++++
39 mt7996/testmode.h | 299 +++++++++++++++++++
40 testmode.c | 126 ++++++--
41 testmode.h | 87 +++++-
42 tools/fields.c | 102 ++++++-
43 18 files changed, 1548 insertions(+), 50 deletions(-)
44 create mode 100644 mt7996/testmode.c
45 create mode 100644 mt7996/testmode.h
46
47diff --git a/eeprom.c b/eeprom.c
developer9237f442024-06-14 17:13:04 +080048index 0bc66cc..a0047d7 100644
developer66e89bc2024-04-23 14:50:01 +080049--- a/eeprom.c
50+++ b/eeprom.c
51@@ -94,8 +94,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
52 }
53
54 #ifdef CONFIG_NL80211_TESTMODE
55- dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
56- dev->test_mtd.offset = offset;
57+ if (len == dev->eeprom.size) {
58+ dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
59+ dev->test_mtd.offset = offset;
60+ }
61 #endif
62
63 out_put_node:
64diff --git a/mac80211.c b/mac80211.c
developer9237f442024-06-14 17:13:04 +080065index d291caa..9a1eb47 100644
developer66e89bc2024-04-23 14:50:01 +080066--- a/mac80211.c
67+++ b/mac80211.c
developer9237f442024-06-14 17:13:04 +080068@@ -846,7 +846,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +080069 }
70
71 #ifdef CONFIG_NL80211_TESTMODE
72- if (phy->test.state == MT76_TM_STATE_RX_FRAMES) {
73+ if (!(phy->test.flag & MT_TM_FW_RX_COUNT) &&
74+ phy->test.state == MT76_TM_STATE_RX_FRAMES) {
75 phy->test.rx_stats.packets[q]++;
76 if (status->flag & RX_FLAG_FAILED_FCS_CRC)
77 phy->test.rx_stats.fcs_error[q]++;
78diff --git a/mt76.h b/mt76.h
developer9237f442024-06-14 17:13:04 +080079index b421a98..57b75fa 100644
developer66e89bc2024-04-23 14:50:01 +080080--- a/mt76.h
81+++ b/mt76.h
82@@ -700,14 +700,21 @@ struct mt76_testmode_ops {
83 int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
84 enum mt76_testmode_state new_state);
85 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
86+ void (*reset_rx_stats)(struct mt76_phy *phy);
87+ void (*tx_stop)(struct mt76_phy *phy);
88+ int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
89 };
90
91+#define MT_TM_FW_RX_COUNT BIT(0)
92+
93 struct mt76_testmode_data {
94 enum mt76_testmode_state state;
95
96 u32 param_set[DIV_ROUND_UP(NUM_MT76_TM_ATTRS, 32)];
97 struct sk_buff *tx_skb;
98
99+ u8 sku_en;
100+
101 u32 tx_count;
102 u16 tx_mpdu_len;
103
104@@ -717,6 +724,7 @@ struct mt76_testmode_data {
105 u8 tx_rate_sgi;
106 u8 tx_rate_ldpc;
107 u8 tx_rate_stbc;
108+ u16 tx_preamble_puncture;
109 u8 tx_ltf;
110
111 u8 tx_antenna_mask;
112@@ -726,6 +734,9 @@ struct mt76_testmode_data {
113 u32 tx_time;
114 u32 tx_ipg;
115
116+ bool ibf;
117+ bool ebf;
118+
119 u32 freq_offset;
120
121 u8 tx_power[4];
122@@ -740,7 +751,16 @@ struct mt76_testmode_data {
123 struct {
124 u64 packets[__MT_RXQ_MAX];
125 u64 fcs_error[__MT_RXQ_MAX];
126+ u64 len_mismatch;
127 } rx_stats;
128+ u8 flag;
129+
130+ struct {
131+ u8 type;
132+ u8 enable;
133+ } cfg;
134+
135+ u8 aid;
136 };
137
138 struct mt76_vif {
139@@ -1444,6 +1464,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
140 int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
141 int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
142
143+static inline void
144+mt76_testmode_param_set(struct mt76_testmode_data *td, u16 idx)
145+{
146+#ifdef CONFIG_NL80211_TESTMODE
147+ td->param_set[idx / 32] |= BIT(idx % 32);
148+#endif
149+}
150+
151+static inline bool
152+mt76_testmode_param_present(struct mt76_testmode_data *td, u16 idx)
153+{
154+#ifdef CONFIG_NL80211_TESTMODE
155+ return td->param_set[idx / 32] & BIT(idx % 32);
156+#endif
157+}
158+
159 static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
160 {
161 #ifdef CONFIG_NL80211_TESTMODE
162diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developer9237f442024-06-14 17:13:04 +0800163index 1e187a8..0b9c6c5 100644
developer66e89bc2024-04-23 14:50:01 +0800164--- a/mt76_connac_mcu.h
165+++ b/mt76_connac_mcu.h
developer9237f442024-06-14 17:13:04 +0800166@@ -1269,12 +1269,14 @@ enum {
developer66e89bc2024-04-23 14:50:01 +0800167 MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
168 MCU_UNI_CMD_RA = 0x2f,
169 MCU_UNI_CMD_MURU = 0x31,
170+ MCU_UNI_CMD_TESTMODE_RX_STAT = 0x32,
171 MCU_UNI_CMD_BF = 0x33,
172 MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
173 MCU_UNI_CMD_THERMAL = 0x35,
174 MCU_UNI_CMD_VOW = 0x37,
175 MCU_UNI_CMD_PP = 0x38,
176 MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
177+ MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
178 MCU_UNI_CMD_RRO = 0x57,
179 MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
180 MCU_UNI_CMD_PER_STA_INFO = 0x6d,
181diff --git a/mt7996/Makefile b/mt7996/Makefile
developer9237f442024-06-14 17:13:04 +0800182index a056b40..7bb17f4 100644
developer66e89bc2024-04-23 14:50:01 +0800183--- a/mt7996/Makefile
184+++ b/mt7996/Makefile
185@@ -8,5 +8,6 @@ mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
186 debugfs.o mmio.o
187
188 mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
189+mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
190
191 mt7996e-y += mtk_debugfs.o mtk_mcu.o
192diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
developer9237f442024-06-14 17:13:04 +0800193index 121a3c9..f9b9ca2 100644
developer66e89bc2024-04-23 14:50:01 +0800194--- a/mt7996/eeprom.c
195+++ b/mt7996/eeprom.c
196@@ -6,6 +6,11 @@
197 #include <linux/firmware.h>
198 #include "mt7996.h"
199 #include "eeprom.h"
200+#include <linux/moduleparam.h>
201+
202+static bool testmode_enable;
203+module_param(testmode_enable, bool, 0644);
204+MODULE_PARM_DESC(testmode_enable, "Enable testmode");
205
206 static int mt7996_check_eeprom(struct mt7996_dev *dev)
207 {
208@@ -43,6 +48,9 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
209
210 static char *mt7996_eeprom_name(struct mt7996_dev *dev)
211 {
212+ if (dev->testmode_enable)
213+ return MT7996_EEPROM_DEFAULT_TM;
214+
215 switch (mt76_chip(&dev->mt76)) {
216 case 0x7990:
217 if (dev->chip_sku == MT7996_SKU_404)
218@@ -92,21 +100,36 @@ out:
219 return ret;
220 }
221
222-static int mt7996_eeprom_load(struct mt7996_dev *dev)
223+int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev)
224 {
225+ u8 *eeprom;
226 int ret;
227
228+ /* load eeprom in flash or bin file mode to determine fw mode */
229 ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
230 if (ret < 0)
231 return ret;
232
233 if (ret) {
234 dev->flash_mode = true;
235- } else {
236- u8 free_block_num;
237- u32 block_num, i;
238- u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
239+ eeprom = dev->mt76.eeprom.data;
240+ /* testmode enable priority: eeprom field > module parameter */
241+ dev->testmode_enable = !mt7996_check_eeprom(dev) ? eeprom[MT_EE_TESTMODE_EN] :
242+ testmode_enable;
243+ }
244+
245+ return ret;
246+}
247+
248+static int mt7996_eeprom_load(struct mt7996_dev *dev)
249+{
250+ int ret;
251+ u8 free_block_num;
252+ u32 block_num, i;
253+ u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
254
255+ /* flash or bin file mode eeprom is loaded before mcu init */
256+ if (!dev->flash_mode) {
257 ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);
258 if (ret < 0)
259 return ret;
260@@ -118,8 +141,8 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
261 /* read eeprom data from efuse */
262 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
263 for (i = 0; i < block_num; i++) {
264- ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size);
265- if (ret < 0)
266+ ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
267+ if (ret && ret != -EINVAL)
268 return ret;
269 }
270 }
271diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
developer9237f442024-06-14 17:13:04 +0800272index 72c38ad..de3ff4e 100644
developer66e89bc2024-04-23 14:50:01 +0800273--- a/mt7996/eeprom.h
274+++ b/mt7996/eeprom.h
275@@ -14,6 +14,7 @@ enum mt7996_eeprom_field {
276 MT_EE_MAC_ADDR = 0x004,
277 MT_EE_MAC_ADDR2 = 0x00a,
278 MT_EE_WIFI_CONF = 0x190,
279+ MT_EE_TESTMODE_EN = 0x1af,
280 MT_EE_MAC_ADDR3 = 0x2c0,
281 MT_EE_RATE_DELTA_2G = 0x1400,
282 MT_EE_RATE_DELTA_5G = 0x147d,
283diff --git a/mt7996/init.c b/mt7996/init.c
developer9237f442024-06-14 17:13:04 +0800284index d58335a..440e26d 100644
developer66e89bc2024-04-23 14:50:01 +0800285--- a/mt7996/init.c
286+++ b/mt7996/init.c
287@@ -969,6 +969,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
288
289 set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
290
291+ ret = mt7996_eeprom_check_fw_mode(dev);
292+ if (ret < 0)
293+ return ret;
294+
295 ret = mt7996_mcu_init(dev);
296 if (ret)
297 return ret;
298@@ -1419,6 +1423,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
299
300 mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
301
302+#ifdef CONFIG_NL80211_TESTMODE
303+ dev->mt76.test_ops = &mt7996_testmode_ops;
304+#endif
305+
306 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
307 ARRAY_SIZE(mt76_rates));
308 if (ret)
309diff --git a/mt7996/mac.c b/mt7996/mac.c
developer9237f442024-06-14 17:13:04 +0800310index 1f53d23..603f6c0 100644
developer66e89bc2024-04-23 14:50:01 +0800311--- a/mt7996/mac.c
312+++ b/mt7996/mac.c
313@@ -685,7 +685,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
314 *info);
315 }
316
317- if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
318+ if (rxv && mode >= MT_PHY_TYPE_HE_SU && mode < MT_PHY_TYPE_EHT_SU &&
319+ !(status->flag & RX_FLAG_8023))
320 mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
321
322 if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
323diff --git a/mt7996/main.c b/mt7996/main.c
developer9237f442024-06-14 17:13:04 +0800324index e66c607..50c7f07 100644
developer66e89bc2024-04-23 14:50:01 +0800325--- a/mt7996/main.c
326+++ b/mt7996/main.c
327@@ -23,6 +23,18 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
328 return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
329 }
330
331+static void mt7996_testmode_disable_all(struct mt7996_dev *dev)
332+{
333+ struct mt7996_phy *phy;
334+ int i;
335+
336+ for (i = 0; i < __MT_MAX_BAND; i++) {
337+ phy = __mt7996_phy(dev, i);
338+ if (phy)
339+ mt76_testmode_set_state(phy->mt76, MT76_TM_STATE_OFF);
340+ }
341+}
342+
343 int mt7996_run(struct ieee80211_hw *hw)
344 {
345 struct mt7996_dev *dev = mt7996_hw_dev(hw);
346@@ -45,6 +57,8 @@ int mt7996_run(struct ieee80211_hw *hw)
347 }
348 }
349
350+ mt7996_testmode_disable_all(dev);
351+
352 mt7996_mac_enable_nf(dev, phy->mt76->band_idx);
353
354 ret = mt7996_mcu_set_rts_thresh(phy, 0x92b);
355@@ -303,6 +317,11 @@ int mt7996_set_channel(struct mt7996_phy *phy)
356
357 mt76_set_channel(phy->mt76);
358
359+ if (mt76_testmode_enabled(phy->mt76) || phy->mt76->test.bf_en) {
360+ mt7996_tm_update_channel(phy);
361+ goto out;
362+ }
363+
364 ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
365 if (ret)
366 goto out;
367@@ -411,6 +430,12 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
368 int ret;
369
370 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
371+ if (!mt76_testmode_enabled(phy->mt76) && !phy->mt76->test.bf_en) {
372+ ret = mt7996_mcu_edcca_enable(phy, true);
373+ if (ret)
374+ return ret;
375+ }
376+
377 ret = mt7996_mcu_set_pp_en(phy, PP_USR_MODE,
378 phy->mt76->chandef.punctured);
379 if (ret)
380@@ -1523,6 +1548,8 @@ const struct ieee80211_ops mt7996_ops = {
381 .sta_set_decap_offload = mt7996_sta_set_decap_offload,
382 .add_twt_setup = mt7996_mac_add_twt_setup,
383 .twt_teardown_request = mt7996_twt_teardown_request,
384+ CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
385+ CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
386 #ifdef CONFIG_MAC80211_DEBUGFS
387 .sta_add_debugfs = mt7996_sta_add_debugfs,
388 #endif
389diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer9237f442024-06-14 17:13:04 +0800390index 6c565c9..2bca86a 100644
developer66e89bc2024-04-23 14:50:01 +0800391--- a/mt7996/mcu.c
392+++ b/mt7996/mcu.c
393@@ -2865,8 +2865,12 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
394 {
395 int ret;
396
397- ret = __mt7996_load_ram(dev, "WM", fw_name(dev, FIRMWARE_WM),
398- MT7996_RAM_TYPE_WM);
399+ if (dev->testmode_enable)
400+ ret = __mt7996_load_ram(dev, "WM_TM", fw_name(dev, FIRMWARE_WM_TM),
401+ MT7996_RAM_TYPE_WM_TM);
402+ else
403+ ret = __mt7996_load_ram(dev, "WM", fw_name(dev, FIRMWARE_WM),
404+ MT7996_RAM_TYPE_WM);
405 if (ret)
406 return ret;
407
408@@ -3557,17 +3561,9 @@ int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
409 &req, sizeof(req), true);
410 }
411
412-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
413+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
414 {
415- struct {
416- u8 _rsv[4];
417-
418- __le16 tag;
419- __le16 len;
420- __le32 addr;
421- __le32 valid;
422- u8 data[16];
423- } __packed req = {
424+ struct mt7996_mcu_eeprom_info req = {
425 .tag = cpu_to_le16(UNI_EFUSE_ACCESS),
426 .len = cpu_to_le16(sizeof(req) - 4),
427 .addr = cpu_to_le32(round_down(offset,
428@@ -3576,6 +3572,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
429 struct sk_buff *skb;
430 bool valid;
431 int ret;
432+ u8 *buf = read_buf;
433
434 ret = mt76_mcu_send_and_get_msg(&dev->mt76,
435 MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
436@@ -3586,7 +3583,9 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
437 valid = le32_to_cpu(*(__le32 *)(skb->data + 16));
438 if (valid) {
439 u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
440- u8 *buf = (u8 *)dev->mt76.eeprom.data + addr;
441+
442+ if (!buf)
443+ buf = (u8 *)dev->mt76.eeprom.data + addr;
444
445 skb_pull(skb, 48);
446 memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
447@@ -4609,3 +4608,37 @@ int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, u8 mode, u16 bitmap)
448 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP),
449 &req, sizeof(req), false);
450 }
451+
452+int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
453+{
454+ struct mt7996_dev *dev = phy->dev;
455+ struct tx_power_ctrl req = {
456+ .tag = cpu_to_le16(power_ctrl_id),
457+ .len = cpu_to_le16(sizeof(req) - 4),
458+ .power_ctrl_id = power_ctrl_id,
459+ .band_idx = phy->mt76->band_idx,
460+ };
461+
462+ switch (power_ctrl_id) {
463+ case UNI_TXPOWER_SKU_POWER_LIMIT_CTRL:
464+ req.sku_enable = !!data;
465+ break;
466+ case UNI_TXPOWER_PERCENTAGE_CTRL:
467+ req.percentage_ctrl_enable = !!data;
468+ break;
469+ case UNI_TXPOWER_PERCENTAGE_DROP_CTRL:
470+ req.power_drop_level = data;
471+ break;
472+ case UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL:
473+ req.bf_backoff_enable = !!data;
474+ break;
475+ case UNI_TXPOWER_ATE_MODE_CTRL:
476+ req.ate_mode_enable = !!data;
477+ break;
478+ default:
479+ req.sku_enable = !!data;
480+ }
481+
482+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TXPOWER),
483+ &req, sizeof(req), false);
484+}
485diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer9237f442024-06-14 17:13:04 +0800486index 2052555..d5ac2b3 100644
developer66e89bc2024-04-23 14:50:01 +0800487--- a/mt7996/mcu.h
488+++ b/mt7996/mcu.h
489@@ -157,6 +157,16 @@ struct mt7996_mcu_eeprom {
490 __le16 buf_len;
491 } __packed;
492
493+struct mt7996_mcu_eeprom_info {
494+ u8 _rsv[4];
495+
496+ __le16 tag;
497+ __le16 len;
498+ __le32 addr;
499+ __le32 valid;
500+ u8 data[MT7996_EEPROM_BLOCK_SIZE];
501+} __packed;
502+
503 struct mt7996_mcu_phy_rx_info {
504 u8 category;
505 u8 rate;
506@@ -889,8 +899,31 @@ enum {
507 UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
508 };
509
510+struct tx_power_ctrl {
511+ u8 _rsv[4];
512+
513+ __le16 tag;
514+ __le16 len;
515+
516+ u8 power_ctrl_id;
517+ union {
518+ bool sku_enable;
519+ bool ate_mode_enable;
520+ bool percentage_ctrl_enable;
521+ bool bf_backoff_enable;
522+ u8 power_drop_level;
523+ };
524+ u8 band_idx;
525+ u8 rsv[1];
526+} __packed;
527+
528 enum {
529+ UNI_TXPOWER_SKU_POWER_LIMIT_CTRL = 0,
530+ UNI_TXPOWER_PERCENTAGE_CTRL = 1,
531+ UNI_TXPOWER_PERCENTAGE_DROP_CTRL = 2,
532+ UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
533 UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
534+ UNI_TXPOWER_ATE_MODE_CTRL = 6,
535 };
536
537 enum {
538diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer9237f442024-06-14 17:13:04 +0800539index 696e16f..0c6a4b9 100644
developer66e89bc2024-04-23 14:50:01 +0800540--- a/mt7996/mt7996.h
541+++ b/mt7996/mt7996.h
542@@ -32,25 +32,30 @@
543 #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
544 #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
545 #define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
546+#define MT7996_FIRMWARE_WM_TM "mediatek/mt7996/mt7996_wm_tm.bin"
547 #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
548
549 #define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin"
550 #define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin"
551 #define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin"
552+#define MT7992_FIRMWARE_WM_TM "mediatek/mt7996/mt7992_wm_tm.bin"
553 #define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
554
555 #define MT7992_FIRMWARE_WA_24 "mediatek/mt7996/mt7992_wa_24.bin"
556 #define MT7992_FIRMWARE_WM_24 "mediatek/mt7996/mt7992_wm_24.bin"
557 #define MT7992_FIRMWARE_DSP_24 "mediatek/mt7996/mt7992_dsp_24.bin"
558+#define MT7992_FIRMWARE_WM_TM_24 "mediatek/mt7996/mt7992_wm_tm_24.bin"
559 #define MT7992_ROM_PATCH_24 "mediatek/mt7996/mt7992_rom_patch_24.bin"
560
561 #define MT7992_FIRMWARE_WA_23 "mediatek/mt7996/mt7992_wa_23.bin"
562 #define MT7992_FIRMWARE_WM_23 "mediatek/mt7996/mt7992_wm_23.bin"
563 #define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
564+#define MT7992_FIRMWARE_WM_TM_23 "mediatek/mt7996/mt7992_wm_tm_23.bin"
565 #define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
566
567 #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
568 #define MT7996_EEPROM_DEFAULT_404 "mediatek/mt7996/mt7996_eeprom_dual_404.bin"
569+#define MT7996_EEPROM_DEFAULT_TM "mediatek/mt7996/mt7996_eeprom_tm.bin"
570 #define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom_2i5i.bin"
571 #define MT7992_EEPROM_DEFAULT_EXT "mediatek/mt7996/mt7992_eeprom_2e5e.bin"
572 #define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin"
573@@ -127,6 +132,7 @@ enum mt7992_sku_type {
574
575 enum mt7996_ram_type {
576 MT7996_RAM_TYPE_WM,
577+ MT7996_RAM_TYPE_WM_TM = MT7996_RAM_TYPE_WM,
578 MT7996_RAM_TYPE_WA,
579 MT7996_RAM_TYPE_DSP,
580 __MT7996_RAM_TYPE_MAX,
581@@ -277,6 +283,21 @@ struct mt7996_phy {
582
583 u8 pp_mode;
584 u16 punct_bitmap;
585+
586+#ifdef CONFIG_NL80211_TESTMODE
587+ struct {
588+ u32 *reg_backup;
589+
590+ s32 last_freq_offset;
591+ u8 last_rcpi[4];
592+ s8 last_rssi[4];
593+ s8 last_ib_rssi[4];
594+ s8 last_wb_rssi[4];
595+ u8 last_snr;
596+
597+ u8 spe_idx;
598+ } test;
599+#endif
600 };
601
602 struct mt7996_dev {
603@@ -357,6 +378,8 @@ struct mt7996_dev {
604 spinlock_t lock;
605 } wed_rro;
606
607+ bool testmode_enable;
608+
609 bool ibf;
610 u8 fw_debug_wm;
611 u8 fw_debug_wa;
612@@ -472,6 +495,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
613 extern const struct ieee80211_ops mt7996_ops;
614 extern struct pci_driver mt7996_pci_driver;
615 extern struct pci_driver mt7996_hif_driver;
616+extern const struct mt76_testmode_ops mt7996_testmode_ops;
617
618 struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
619 void __iomem *mem_base, u32 device_id);
620@@ -481,6 +505,7 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
621 int mt7996_register_device(struct mt7996_dev *dev);
622 void mt7996_unregister_device(struct mt7996_dev *dev);
623 int mt7996_eeprom_init(struct mt7996_dev *dev);
624+int mt7996_eeprom_check_fw_mode(struct mt7996_dev *dev);
625 int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
626 int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
627 struct ieee80211_channel *chan);
628@@ -533,7 +558,7 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
629 int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
630 struct ieee80211_sta *sta, void *data, u32 field);
631 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
632-int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset);
633+int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf);
634 int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
635 int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
636 int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
637@@ -568,6 +593,7 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
638 void mt7996_mcu_exit(struct mt7996_dev *dev);
639 int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
640 int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
641+int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
642
643 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
644 {
645diff --git a/mt7996/testmode.c b/mt7996/testmode.c
646new file mode 100644
developer9237f442024-06-14 17:13:04 +0800647index 0000000..98eebce
developer66e89bc2024-04-23 14:50:01 +0800648--- /dev/null
649+++ b/mt7996/testmode.c
650@@ -0,0 +1,740 @@
651+// SPDX-License-Identifier: ISC
652+/*
653+ * Copyright (C) 2022 MediaTek Inc.
654+ */
655+
656+#include "mt7996.h"
657+#include "mac.h"
658+#include "mcu.h"
659+#include "testmode.h"
660+
661+enum {
662+ TM_CHANGED_TXPOWER,
663+ TM_CHANGED_FREQ_OFFSET,
664+ TM_CHANGED_SKU_EN,
665+ TM_CHANGED_TX_LENGTH,
666+ TM_CHANGED_TX_TIME,
667+ TM_CHANGED_CFG,
668+
669+ /* must be last */
670+ NUM_TM_CHANGED
671+};
672+
673+static const u8 tm_change_map[] = {
674+ [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
675+ [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
676+ [TM_CHANGED_SKU_EN] = MT76_TM_ATTR_SKU_EN,
677+ [TM_CHANGED_TX_LENGTH] = MT76_TM_ATTR_TX_LENGTH,
678+ [TM_CHANGED_TX_TIME] = MT76_TM_ATTR_TX_TIME,
679+ [TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
680+};
681+
682+static u8 mt7996_tm_bw_mapping(enum nl80211_chan_width width, enum bw_mapping_method method)
683+{
684+ static const u8 width_to_bw[][NUM_BW_MAP] = {
685+ [NL80211_CHAN_WIDTH_40] = {FW_CDBW_40MHZ, TM_CBW_40MHZ},
686+ [NL80211_CHAN_WIDTH_80] = {FW_CDBW_80MHZ, TM_CBW_80MHZ},
687+ [NL80211_CHAN_WIDTH_80P80] = {FW_CDBW_8080MHZ, TM_CBW_8080MHZ},
688+ [NL80211_CHAN_WIDTH_160] = {FW_CDBW_160MHZ, TM_CBW_160MHZ},
689+ [NL80211_CHAN_WIDTH_5] = {FW_CDBW_5MHZ, TM_CBW_5MHZ},
690+ [NL80211_CHAN_WIDTH_10] = {FW_CDBW_10MHZ, TM_CBW_10MHZ},
691+ [NL80211_CHAN_WIDTH_20] = {FW_CDBW_20MHZ, TM_CBW_20MHZ},
692+ [NL80211_CHAN_WIDTH_20_NOHT] = {FW_CDBW_20MHZ, TM_CBW_20MHZ},
693+ [NL80211_CHAN_WIDTH_320] = {FW_CDBW_320MHZ, TM_CBW_320MHZ},
694+ };
695+
696+ if (width >= ARRAY_SIZE(width_to_bw))
697+ return 0;
698+
699+ return width_to_bw[width][method];
700+}
701+
702+static u8 mt7996_tm_rate_to_phy(u8 tx_rate_mode)
703+{
704+ static const u8 rate_to_phy[] = {
705+ [MT76_TM_TX_MODE_CCK] = MT_PHY_TYPE_CCK,
706+ [MT76_TM_TX_MODE_OFDM] = MT_PHY_TYPE_OFDM,
707+ [MT76_TM_TX_MODE_HT] = MT_PHY_TYPE_HT,
708+ [MT76_TM_TX_MODE_VHT] = MT_PHY_TYPE_VHT,
709+ [MT76_TM_TX_MODE_HE_SU] = MT_PHY_TYPE_HE_SU,
710+ [MT76_TM_TX_MODE_HE_EXT_SU] = MT_PHY_TYPE_HE_EXT_SU,
711+ [MT76_TM_TX_MODE_HE_TB] = MT_PHY_TYPE_HE_TB,
712+ [MT76_TM_TX_MODE_HE_MU] = MT_PHY_TYPE_HE_MU,
713+ [MT76_TM_TX_MODE_EHT_SU] = MT_PHY_TYPE_EHT_SU,
714+ [MT76_TM_TX_MODE_EHT_TRIG] = MT_PHY_TYPE_EHT_TRIG,
715+ [MT76_TM_TX_MODE_EHT_MU] = MT_PHY_TYPE_EHT_MU,
716+ };
717+
718+ if (tx_rate_mode > MT76_TM_TX_MODE_MAX)
719+ return -EINVAL;
720+
721+ return rate_to_phy[tx_rate_mode];
722+}
723+
724+static int
725+mt7996_tm_check_antenna(struct mt7996_phy *phy)
726+{
727+ struct mt76_testmode_data *td = &phy->mt76->test;
728+ struct mt7996_dev *dev = phy->dev;
729+ u8 band_idx = phy->mt76->band_idx;
730+ u32 chainmask = phy->mt76->chainmask;
731+ u32 aux_rx_mask;
732+
733+ chainmask = chainmask >> dev->chainshift[band_idx];
734+ aux_rx_mask = BIT(fls(chainmask)) * phy->has_aux_rx;
735+ if (td->tx_antenna_mask & ~(chainmask | aux_rx_mask)) {
736+ dev_err(dev->mt76.dev,
737+ "tx antenna mask 0x%x exceeds hw limit (chainmask 0x%x, has aux rx: %s)\n",
738+ td->tx_antenna_mask, chainmask, phy->has_aux_rx ? "yes" : "no");
739+ return -EINVAL;
740+ }
741+
742+ return 0;
743+}
744+
745+static int
746+mt7996_tm_set(struct mt7996_dev *dev, u32 func_idx, u32 data)
747+{
748+ struct mt7996_tm_req req = {
749+ .rf_test = {
750+ .tag = cpu_to_le16(UNI_RF_TEST_CTRL),
751+ .len = cpu_to_le16(sizeof(req.rf_test)),
752+ .action = RF_ACTION_SET,
753+ .op.rf.func_idx = func_idx,
754+ .op.rf.param.func_data = cpu_to_le32(data),
755+ },
756+ };
757+ bool wait = (data == RF_CMD(START_TX)) ? true : false;
758+
759+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), &req,
760+ sizeof(req), wait);
761+}
762+
763+static int
764+mt7996_tm_get(struct mt7996_dev *dev, u32 func_idx, u32 data, u32 *result)
765+{
766+ struct mt7996_tm_req req = {
767+ .rf_test = {
768+ .tag = cpu_to_le16(UNI_RF_TEST_CTRL),
769+ .len = cpu_to_le16(sizeof(req.rf_test)),
770+ .action = RF_ACTION_GET,
771+ .op.rf.func_idx = func_idx,
772+ .op.rf.param.func_data = cpu_to_le32(data),
773+ },
774+ };
775+ struct mt7996_tm_event *event;
776+ struct sk_buff *skb;
777+ int ret;
778+
779+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(TESTMODE_CTRL),
780+ &req, sizeof(req), true, &skb);
781+ if (ret)
782+ return ret;
783+
784+ event = (struct mt7996_tm_event *)skb->data;
785+ *result = event->result.payload_length;
786+
787+ dev_kfree_skb(skb);
788+
789+ return ret;
790+}
791+
792+static void
793+mt7996_tm_set_antenna(struct mt7996_phy *phy, u32 func_idx)
794+{
795+#define SPE_INDEX_MASK BIT(31)
796+#define TX_ANTENNA_MASK GENMASK(3, 0)
797+#define RX_ANTENNA_MASK GENMASK(20, 16) /* RX antenna mask at most 5 bit */
798+ struct mt7996_dev *dev = phy->dev;
799+ struct mt76_testmode_data *td = &phy->mt76->test;
800+ u32 antenna_mask;
801+
802+ if (!mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA))
803+ return;
804+
805+ if (func_idx == SET_ID(TX_PATH))
806+ antenna_mask = td->tx_spe_idx ? (SPE_INDEX_MASK | td->tx_spe_idx) :
807+ td->tx_antenna_mask & TX_ANTENNA_MASK;
808+ else if (func_idx == SET_ID(RX_PATH))
809+ antenna_mask = u32_encode_bits(td->tx_antenna_mask, RX_ANTENNA_MASK);
810+ else
811+ return;
812+
813+ mt7996_tm_set(dev, func_idx, antenna_mask);
814+}
815+
816+static void
817+mt7996_tm_set_mac_addr(struct mt7996_dev *dev, u8 *addr, u32 func_idx)
818+{
819+#define REMAIN_PART_TAG BIT(18)
820+ u32 own_mac_first = 0, own_mac_remain = 0;
821+ int len = sizeof(u32);
822+
823+ memcpy(&own_mac_first, addr, len);
824+ mt7996_tm_set(dev, func_idx, own_mac_first);
825+ /* Set the remain part of mac address */
826+ memcpy(&own_mac_remain, addr + len, ETH_ALEN - len);
827+ mt7996_tm_set(dev, func_idx | REMAIN_PART_TAG, own_mac_remain);
828+}
829+
830+static int
831+mt7996_tm_rf_switch_mode(struct mt7996_dev *dev, u32 op_mode)
832+{
833+ struct mt7996_tm_req req = {
834+ .rf_test = {
835+ .tag = cpu_to_le16(UNI_RF_TEST_CTRL),
836+ .len = cpu_to_le16(sizeof(req.rf_test)),
837+ .action = RF_ACTION_SWITCH_TO_RF_TEST,
838+ .op.op_mode = cpu_to_le32(op_mode),
839+ },
840+ };
841+
842+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_CTRL), &req,
843+ sizeof(req), false);
844+}
845+
846+static void
847+mt7996_tm_init(struct mt7996_phy *phy, bool en)
848+{
849+ struct mt7996_dev *dev = phy->dev;
850+ u8 rf_test_mode = en ? RF_OPER_RF_TEST : RF_OPER_NORMAL;
851+
852+ if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
853+ return;
854+
855+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(ATE_MODE), en);
856+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(SKU_POWER_LIMIT), !en);
857+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(BACKOFF_POWER_LIMIT), !en);
858+
859+ mt7996_tm_rf_switch_mode(dev, rf_test_mode);
860+
861+ mt7996_mcu_add_bss_info(phy, phy->monitor_vif, en);
862+ mt7996_mcu_add_sta(dev, phy->monitor_vif, NULL, en, false);
863+
864+ mt7996_tm_set(dev, SET_ID(BAND_IDX), phy->mt76->band_idx);
865+
866+ /* use firmware counter for RX stats */
867+ phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
868+}
869+
870+static void
871+mt7996_tm_update_channel(struct mt7996_phy *phy)
872+{
873+#define CHAN_FREQ_BW_80P80_TAG (SET_ID(CHAN_FREQ) | BIT(16))
874+ struct mt7996_dev *dev = phy->dev;
875+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
876+ struct ieee80211_channel *chan = chandef->chan;
877+ u8 width = chandef->width;
878+ static const u8 ch_band[] = {
879+ [NL80211_BAND_2GHZ] = 0,
880+ [NL80211_BAND_5GHZ] = 1,
881+ [NL80211_BAND_6GHZ] = 2,
882+ };
883+
884+ if (!chan || !chandef) {
885+ dev_info(dev->mt76.dev, "chandef not found, channel update failed!\n");
886+ return;
887+ }
888+
889+ /* system bw */
890+ mt7996_tm_set(dev, SET_ID(CBW), mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_FW));
891+
892+ if (width == NL80211_CHAN_WIDTH_80P80) {
893+ width = NL80211_CHAN_WIDTH_160;
894+ mt7996_tm_set(dev, CHAN_FREQ_BW_80P80_TAG, chandef->center_freq2 * 1000);
895+ }
896+
897+ /* TODO: define per-packet bw */
898+ /* per-packet bw */
899+ mt7996_tm_set(dev, SET_ID(DBW), mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_FW));
900+
901+ /* control channel selection index */
902+ mt7996_tm_set(dev, SET_ID(PRIMARY_CH), 0);
903+ mt7996_tm_set(dev, SET_ID(BAND), ch_band[chan->band]);
904+
905+ /* trigger switch channel calibration */
906+ mt7996_tm_set(dev, SET_ID(CHAN_FREQ), chandef->center_freq1 * 1000);
907+
908+ // TODO: update power limit table
909+}
910+
911+static void
912+mt7996_tm_tx_stop(struct mt76_phy *mphy)
913+{
914+ struct mt76_testmode_data *td = &mphy->test;
915+ struct mt7996_phy *phy = mphy->priv;
916+ struct mt7996_dev *dev = phy->dev;
917+
918+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(STOP_TEST));
919+ td->tx_pending = 0;
920+}
921+
922+static void
923+mt7996_tm_set_tx_frames(struct mt7996_phy *phy, bool en)
924+{
925+#define FRAME_CONTROL 0x88
926+ struct mt76_testmode_data *td = &phy->mt76->test;
927+ struct mt7996_dev *dev = phy->dev;
928+
929+ //TODO: RU operation, replace mcs, nss, and ldpc
930+ if (en) {
931+ mt7996_tm_set(dev, SET_ID(MAC_HEADER), FRAME_CONTROL);
932+ mt7996_tm_set(dev, SET_ID(SEQ_CTRL), 0);
933+ mt7996_tm_set(dev, SET_ID(TX_COUNT), td->tx_count);
934+ mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
935+ mt7996_tm_set(dev, SET_ID(TX_RATE), td->tx_rate_idx);
936+
937+ if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER))
938+ mt7996_tm_set(dev, SET_ID(POWER), td->tx_power[0]);
939+
940+ if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_TIME)) {
941+ mt7996_tm_set(dev, SET_ID(TX_LEN), 0);
942+ mt7996_tm_set(dev, SET_ID(TX_TIME), td->tx_time);
943+ } else {
944+ mt7996_tm_set(dev, SET_ID(TX_LEN), td->tx_mpdu_len);
945+ mt7996_tm_set(dev, SET_ID(TX_TIME), 0);
946+ }
947+
948+ mt7996_tm_set_antenna(phy, SET_ID(TX_PATH));
949+ mt7996_tm_set_antenna(phy, SET_ID(RX_PATH));
950+ mt7996_tm_set(dev, SET_ID(STBC), td->tx_rate_stbc);
951+ mt7996_tm_set(dev, SET_ID(ENCODE_MODE), td->tx_rate_ldpc);
952+ mt7996_tm_set(dev, SET_ID(IBF_ENABLE), td->ibf);
953+ mt7996_tm_set(dev, SET_ID(EBF_ENABLE), td->ebf);
954+ mt7996_tm_set(dev, SET_ID(IPG), td->tx_ipg);
955+ mt7996_tm_set(dev, SET_ID(GI), td->tx_rate_sgi);
956+ mt7996_tm_set(dev, SET_ID(NSS), td->tx_rate_nss);
957+ mt7996_tm_set(dev, SET_ID(AID_OFFSET), 0);
958+ mt7996_tm_set(dev, SET_ID(PUNCTURE), td->tx_preamble_puncture);
959+
960+ mt7996_tm_set(dev, SET_ID(MAX_PE), 2);
961+ mt7996_tm_set(dev, SET_ID(HW_TX_MODE), 0);
962+ mt7996_tm_update_channel(phy);
963+
964+ /* trigger firmware to start TX */
965+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(START_TX));
966+ } else {
967+ mt7996_tm_tx_stop(phy->mt76);
968+ }
969+}
970+
971+static int
972+mt7996_tm_rx_stats_user_ctrl(struct mt7996_phy *phy, u16 user_idx)
973+{
974+ struct mt7996_dev *dev = phy->dev;
975+ struct mt7996_tm_rx_req req = {
976+ .band = phy->mt76->band_idx,
977+ .user_ctrl = {
978+ .tag = cpu_to_le16(UNI_TM_RX_STAT_SET_USER_CTRL),
979+ .len = cpu_to_le16(sizeof(req.user_ctrl)),
980+ .band_idx = phy->mt76->band_idx,
981+ .user_idx = cpu_to_le16(user_idx),
982+ },
983+ };
984+
985+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(TESTMODE_RX_STAT), &req,
986+ sizeof(req), false);
987+}
988+
989+static void
990+mt7996_tm_set_rx_frames(struct mt7996_phy *phy, bool en)
991+{
992+#define RX_MU_DISABLE 0xf800
993+ struct mt76_testmode_data *td = &phy->mt76->test;
994+ struct mt7996_dev *dev = phy->dev;
995+ int ret;
996+
997+ if (en) {
998+ ret = mt7996_tm_rx_stats_user_ctrl(phy, td->aid);
999+ if (ret) {
1000+ dev_info(dev->mt76.dev, "Set RX stats user control failed!\n");
1001+ return;
1002+ }
1003+
1004+ mt7996_tm_update_channel(phy);
1005+
1006+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_HE_MU) {
1007+ if (td->aid)
1008+ ret = mt7996_tm_set(dev, SET_ID(RX_MU_AID), td->aid);
1009+ else
1010+ ret = mt7996_tm_set(dev, SET_ID(RX_MU_AID), RX_MU_DISABLE);
1011+ }
1012+ mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
1013+ mt7996_tm_set(dev, SET_ID(GI), td->tx_rate_sgi);
1014+ mt7996_tm_set_antenna(phy, SET_ID(RX_PATH));
1015+ mt7996_tm_set(dev, SET_ID(MAX_PE), 2);
1016+
1017+ mt7996_tm_set_mac_addr(dev, td->addr[1], SET_ID(SA));
1018+
1019+ /* trigger firmware to start RX */
1020+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(START_RX));
1021+ } else {
1022+ /* trigger firmware to stop RX */
1023+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(STOP_TEST));
1024+ }
1025+}
1026+
1027+static void
1028+mt7996_tm_set_tx_cont(struct mt7996_phy *phy, bool en)
1029+{
1030+#define CONT_WAVE_MODE_OFDM 3
1031+ struct mt76_testmode_data *td = &phy->mt76->test;
1032+ struct mt7996_dev *dev = phy->dev;
1033+
1034+ if (en) {
1035+ mt7996_tm_update_channel(phy);
1036+ mt7996_tm_set(dev, SET_ID(TX_MODE), mt7996_tm_rate_to_phy(td->tx_rate_mode));
1037+ mt7996_tm_set(dev, SET_ID(TX_RATE), td->tx_rate_idx);
1038+ /* fix payload is OFDM */
1039+ mt7996_tm_set(dev, SET_ID(CONT_WAVE_MODE), CONT_WAVE_MODE_OFDM);
1040+ mt7996_tm_set(dev, SET_ID(ANT_MASK), td->tx_antenna_mask);
1041+
1042+ /* trigger firmware to start CONT TX */
1043+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(CONT_WAVE));
1044+ } else {
1045+ /* trigger firmware to stop CONT TX */
1046+ mt7996_tm_set(dev, SET_ID(COMMAND), RF_CMD(STOP_TEST));
1047+ }
1048+}
1049+
1050+static void
1051+mt7996_tm_update_params(struct mt7996_phy *phy, u32 changed)
1052+{
1053+ struct mt76_testmode_data *td = &phy->mt76->test;
1054+ struct mt7996_dev *dev = phy->dev;
1055+
1056+ if (changed & BIT(TM_CHANGED_FREQ_OFFSET)) {
1057+ mt7996_tm_set(dev, SET_ID(FREQ_OFFSET), td->freq_offset);
1058+ mt7996_tm_set(dev, SET_ID(FREQ_OFFSET_C2), td->freq_offset);
1059+ }
1060+ if (changed & BIT(TM_CHANGED_TXPOWER))
1061+ mt7996_tm_set(dev, SET_ID(POWER), td->tx_power[0]);
1062+ if (changed & BIT(TM_CHANGED_SKU_EN)) {
1063+ mt7996_tm_update_channel(phy);
1064+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(SKU_POWER_LIMIT), td->sku_en);
1065+ mt7996_mcu_set_tx_power_ctrl(phy, POWER_CTRL(BACKOFF_POWER_LIMIT), td->sku_en);
1066+ mt7996_mcu_set_txpower_sku(phy);
1067+ }
1068+ if (changed & BIT(TM_CHANGED_TX_LENGTH)) {
1069+ mt7996_tm_set(dev, SET_ID(TX_LEN), td->tx_mpdu_len);
1070+ mt7996_tm_set(dev, SET_ID(TX_TIME), 0);
1071+ }
1072+ if (changed & BIT(TM_CHANGED_TX_TIME)) {
1073+ mt7996_tm_set(dev, SET_ID(TX_LEN), 0);
1074+ mt7996_tm_set(dev, SET_ID(TX_TIME), td->tx_time);
1075+ }
1076+ if (changed & BIT(TM_CHANGED_CFG)) {
1077+ u32 func_idx = td->cfg.enable ? SET_ID(CFG_ON) : SET_ID(CFG_OFF);
1078+
1079+ mt7996_tm_set(dev, func_idx, td->cfg.type);
1080+ }
1081+}
1082+
1083+static int
1084+mt7996_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
1085+{
1086+ struct mt76_testmode_data *td = &mphy->test;
1087+ struct mt7996_phy *phy = mphy->priv;
1088+ enum mt76_testmode_state prev_state = td->state;
1089+
1090+ mphy->test.state = state;
1091+
1092+ if (prev_state != MT76_TM_STATE_OFF)
1093+ mt7996_tm_set(phy->dev, SET_ID(BAND_IDX), mphy->band_idx);
1094+
1095+ if (prev_state == MT76_TM_STATE_TX_FRAMES ||
1096+ state == MT76_TM_STATE_TX_FRAMES)
1097+ mt7996_tm_set_tx_frames(phy, state == MT76_TM_STATE_TX_FRAMES);
1098+ else if (prev_state == MT76_TM_STATE_RX_FRAMES ||
1099+ state == MT76_TM_STATE_RX_FRAMES)
1100+ mt7996_tm_set_rx_frames(phy, state == MT76_TM_STATE_RX_FRAMES);
1101+ else if (prev_state == MT76_TM_STATE_TX_CONT ||
1102+ state == MT76_TM_STATE_TX_CONT)
1103+ mt7996_tm_set_tx_cont(phy, state == MT76_TM_STATE_TX_CONT);
1104+ else if (prev_state == MT76_TM_STATE_OFF ||
1105+ state == MT76_TM_STATE_OFF)
1106+ mt7996_tm_init(phy, !(state == MT76_TM_STATE_OFF));
1107+
1108+ if ((state == MT76_TM_STATE_IDLE &&
1109+ prev_state == MT76_TM_STATE_OFF) ||
1110+ (state == MT76_TM_STATE_OFF &&
1111+ prev_state == MT76_TM_STATE_IDLE)) {
1112+ u32 changed = 0;
1113+ int i, ret;
1114+
1115+ for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
1116+ u16 cur = tm_change_map[i];
1117+
1118+ if (mt76_testmode_param_present(td, cur))
1119+ changed |= BIT(i);
1120+ }
1121+
1122+ ret = mt7996_tm_check_antenna(phy);
1123+ if (ret)
1124+ return ret;
1125+
1126+ mt7996_tm_update_params(phy, changed);
1127+ }
1128+
1129+ return 0;
1130+}
1131+
1132+static int
1133+mt7996_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
1134+ enum mt76_testmode_state new_state)
1135+{
1136+ struct mt76_testmode_data *td = &mphy->test;
1137+ struct mt7996_phy *phy = mphy->priv;
1138+ struct mt7996_dev *dev = phy->dev;
1139+ u32 changed = 0;
1140+ int i, ret;
1141+
1142+ BUILD_BUG_ON(NUM_TM_CHANGED >= 32);
1143+
1144+ if (new_state == MT76_TM_STATE_OFF ||
1145+ td->state == MT76_TM_STATE_OFF)
1146+ return 0;
1147+
1148+ ret = mt7996_tm_check_antenna(phy);
1149+ if (ret)
1150+ return ret;
1151+
1152+ for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
1153+ if (tb[tm_change_map[i]])
1154+ changed |= BIT(i);
1155+ }
1156+
1157+ mt7996_tm_set(dev, SET_ID(BAND_IDX), mphy->band_idx);
1158+ mt7996_tm_update_params(phy, changed);
1159+
1160+ return 0;
1161+}
1162+
1163+static int
1164+mt7996_tm_get_rx_stats(struct mt7996_phy *phy)
1165+{
1166+ struct mt7996_dev *dev = phy->dev;
1167+ struct mt7996_tm_rx_req req = {
1168+ .band = phy->mt76->band_idx,
1169+ .rx_stat_all = {
1170+ .tag = cpu_to_le16(UNI_TM_RX_STAT_GET_ALL_V2),
1171+ .len = cpu_to_le16(sizeof(req.rx_stat_all)),
1172+ .band_idx = phy->mt76->band_idx,
1173+ },
1174+ };
1175+ struct mt76_testmode_data *td = &phy->mt76->test;
1176+ struct mt7996_tm_rx_event *rx_stats;
1177+ struct mt7996_tm_rx_event_stat_all *rx_stats_all;
1178+ struct sk_buff *skb;
1179+ enum mt76_rxq_id qid;
1180+ int i, ret = 0;
1181+ u32 mac_rx_mdrdy_cnt;
1182+ u16 mac_rx_len_mismatch, fcs_err_count;
1183+
1184+ if (td->state != MT76_TM_STATE_RX_FRAMES)
1185+ return 0;
1186+
1187+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(TESTMODE_RX_STAT),
1188+ &req, sizeof(req), true, &skb);
1189+
1190+ if (ret)
1191+ return ret;
1192+
1193+ rx_stats = (struct mt7996_tm_rx_event *)skb->data;
1194+ rx_stats_all = &rx_stats->rx_stat_all;
1195+
1196+ phy->test.last_freq_offset = le32_to_cpu(rx_stats_all->user_info[0].freq_offset);
1197+ phy->test.last_snr = le32_to_cpu(rx_stats_all->user_info[0].snr);
1198+ for (i = 0; i < ARRAY_SIZE(phy->test.last_rcpi); i++) {
1199+ phy->test.last_rcpi[i] = le16_to_cpu(rx_stats_all->rxv_info[i].rcpi);
1200+ phy->test.last_rssi[i] = le16_to_cpu(rx_stats_all->rxv_info[i].rssi);
1201+ phy->test.last_ib_rssi[i] = rx_stats_all->fagc[i].ib_rssi;
1202+ phy->test.last_wb_rssi[i] = rx_stats_all->fagc[i].wb_rssi;
1203+ }
1204+
1205+ if (phy->mt76->band_idx == 2)
1206+ qid = MT_RXQ_BAND2;
1207+ else if (phy->mt76->band_idx == 1)
1208+ qid = MT_RXQ_BAND1;
1209+ else
1210+ qid = MT_RXQ_MAIN;
1211+
1212+ fcs_err_count = le16_to_cpu(rx_stats_all->band_info.mac_rx_fcs_err_cnt);
1213+ mac_rx_len_mismatch = le16_to_cpu(rx_stats_all->band_info.mac_rx_len_mismatch);
1214+ mac_rx_mdrdy_cnt = le32_to_cpu(rx_stats_all->band_info.mac_rx_mdrdy_cnt);
1215+ td->rx_stats.packets[qid] += mac_rx_mdrdy_cnt;
1216+ td->rx_stats.packets[qid] += fcs_err_count;
1217+ td->rx_stats.fcs_error[qid] += fcs_err_count;
1218+ td->rx_stats.len_mismatch += mac_rx_len_mismatch;
1219+
1220+ dev_kfree_skb(skb);
1221+
1222+ return ret;
1223+}
1224+
1225+static void
1226+mt7996_tm_reset_trx_stats(struct mt76_phy *mphy)
1227+{
1228+ struct mt7996_phy *phy = mphy->priv;
1229+ struct mt7996_dev *dev = phy->dev;
1230+
1231+ memset(&mphy->test.rx_stats, 0, sizeof(mphy->test.rx_stats));
1232+ mt7996_tm_set(dev, SET_ID(TRX_COUNTER_RESET), 0);
1233+}
1234+
1235+static int
1236+mt7996_tm_get_tx_stats(struct mt7996_phy *phy)
1237+{
1238+ struct mt7996_dev *dev = phy->dev;
1239+ struct mt76_testmode_data *td = &phy->mt76->test;
1240+ int ret;
1241+
1242+ if (td->state != MT76_TM_STATE_TX_FRAMES)
1243+ return 0;
1244+
1245+ ret = mt7996_tm_get(dev, GET_ID(TXED_COUNT), 0, &td->tx_done);
1246+ if (ret)
1247+ return ret;
1248+
1249+ td->tx_pending = td->tx_count - td->tx_done;
1250+
1251+ return ret;
1252+}
1253+
1254+static int
1255+mt7996_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
1256+{
1257+ struct mt7996_phy *phy = mphy->priv;
1258+ void *rx, *rssi;
1259+ int i;
1260+
1261+ mt7996_tm_set(phy->dev, SET_ID(BAND_IDX), mphy->band_idx);
1262+ mt7996_tm_get_rx_stats(phy);
1263+ mt7996_tm_get_tx_stats(phy);
1264+
1265+ rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX);
1266+ if (!rx)
1267+ return -ENOMEM;
1268+
1269+ if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, phy->test.last_freq_offset))
1270+ return -ENOMEM;
1271+
1272+ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI);
1273+ if (!rssi)
1274+ return -ENOMEM;
1275+
1276+ for (i = 0; i < ARRAY_SIZE(phy->test.last_rcpi); i++)
1277+ if (nla_put_u8(msg, i, phy->test.last_rcpi[i]))
1278+ return -ENOMEM;
1279+
1280+ nla_nest_end(msg, rssi);
1281+
1282+ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RSSI);
1283+ if (!rssi)
1284+ return -ENOMEM;
1285+
1286+ for (i = 0; i < ARRAY_SIZE(phy->test.last_rssi); i++)
1287+ if (nla_put_s8(msg, i, phy->test.last_rssi[i]))
1288+ return -ENOMEM;
1289+
1290+ nla_nest_end(msg, rssi);
1291+
1292+ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI);
1293+ if (!rssi)
1294+ return -ENOMEM;
1295+
1296+ for (i = 0; i < ARRAY_SIZE(phy->test.last_ib_rssi); i++)
1297+ if (nla_put_s8(msg, i, phy->test.last_ib_rssi[i]))
1298+ return -ENOMEM;
1299+
1300+ nla_nest_end(msg, rssi);
1301+
1302+ rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI);
1303+ if (!rssi)
1304+ return -ENOMEM;
1305+
1306+ for (i = 0; i < ARRAY_SIZE(phy->test.last_wb_rssi); i++)
1307+ if (nla_put_s8(msg, i, phy->test.last_wb_rssi[i]))
1308+ return -ENOMEM;
1309+
1310+ nla_nest_end(msg, rssi);
1311+
1312+ if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, phy->test.last_snr))
1313+ return -ENOMEM;
1314+
1315+ nla_nest_end(msg, rx);
1316+
1317+ return 0;
1318+}
1319+
1320+static int
1321+mt7996_tm_write_back_to_efuse(struct mt7996_dev *dev)
1322+{
1323+ struct mt7996_mcu_eeprom_info req = {
1324+ .tag = cpu_to_le16(UNI_EFUSE_ACCESS),
1325+ .len = cpu_to_le16(sizeof(req) - 4),
1326+ };
1327+ u8 read_buf[MT76_TM_EEPROM_BLOCK_SIZE], *eeprom = dev->mt76.eeprom.data;
1328+ int i, ret = -EINVAL;
1329+
1330+ /* prevent from damaging chip id in efuse */
1331+ if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
1332+ goto out;
1333+
1334+ for (i = 0; i < MT7996_EEPROM_SIZE; i += MT76_TM_EEPROM_BLOCK_SIZE) {
1335+ req.addr = cpu_to_le32(i);
1336+ memcpy(req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
1337+
1338+ ret = mt7996_mcu_get_eeprom(dev, i, read_buf);
1339+ if (ret < 0)
1340+ return ret;
1341+
1342+ if (!memcmp(req.data, read_buf, MT76_TM_EEPROM_BLOCK_SIZE))
1343+ continue;
1344+
1345+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
1346+ &req, sizeof(req), true);
1347+ if (ret)
1348+ return ret;
1349+ }
1350+
1351+out:
1352+ return ret;
1353+}
1354+
1355+static int
1356+mt7996_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
1357+{
1358+ struct mt7996_phy *phy = mphy->priv;
1359+ struct mt7996_dev *dev = phy->dev;
1360+ u8 *eeprom = dev->mt76.eeprom.data;
1361+ int ret = 0;
1362+
1363+ if (offset >= MT7996_EEPROM_SIZE)
1364+ return -EINVAL;
1365+
1366+ switch (action) {
1367+ case MT76_TM_EEPROM_ACTION_UPDATE_DATA:
1368+ memcpy(eeprom + offset, val, MT76_TM_EEPROM_BLOCK_SIZE);
1369+ break;
1370+ case MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE:
1371+ ret = mt7996_mcu_set_eeprom(dev);
1372+ break;
1373+ case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
1374+ ret = mt7996_tm_write_back_to_efuse(dev);
1375+ break;
1376+ default:
1377+ break;
1378+ }
1379+
1380+ return ret;
1381+}
1382+
1383+const struct mt76_testmode_ops mt7996_testmode_ops = {
1384+ .set_state = mt7996_tm_set_state,
1385+ .set_params = mt7996_tm_set_params,
1386+ .dump_stats = mt7996_tm_dump_stats,
1387+ .reset_rx_stats = mt7996_tm_reset_trx_stats,
1388+ .tx_stop = mt7996_tm_tx_stop,
1389+ .set_eeprom = mt7996_tm_set_eeprom,
1390+};
1391diff --git a/mt7996/testmode.h b/mt7996/testmode.h
1392new file mode 100644
developer9237f442024-06-14 17:13:04 +08001393index 0000000..319ef25
developer66e89bc2024-04-23 14:50:01 +08001394--- /dev/null
1395+++ b/mt7996/testmode.h
1396@@ -0,0 +1,299 @@
1397+/* SPDX-License-Identifier: ISC */
1398+/* Copyright (C) 2020 MediaTek Inc. */
1399+
1400+#ifndef __MT7996_TESTMODE_H
1401+#define __MT7996_TESTMODE_H
1402+
1403+enum {
1404+ TM_CBW_20MHZ,
1405+ TM_CBW_40MHZ,
1406+ TM_CBW_80MHZ,
1407+ TM_CBW_10MHZ,
1408+ TM_CBW_5MHZ,
1409+ TM_CBW_160MHZ,
1410+ TM_CBW_8080MHZ,
1411+ TM_CBW_320MHZ = 12,
1412+};
1413+
1414+/* BW defined in FW hal_cal_flow_rom.h */
1415+enum {
1416+ FW_CDBW_20MHZ,
1417+ FW_CDBW_40MHZ,
1418+ FW_CDBW_80MHZ,
1419+ FW_CDBW_160MHZ,
1420+ FW_CDBW_320MHZ,
1421+ FW_CDBW_5MHZ,
1422+ FW_CDBW_10MHZ,
1423+ FW_CDBW_8080MHZ,
1424+};
1425+
1426+enum bw_mapping_method {
1427+ BW_MAP_NL_TO_FW,
1428+ BW_MAP_NL_TO_TM,
1429+
1430+ NUM_BW_MAP,
1431+};
1432+
1433+struct mt7996_tm_rf_test {
1434+ __le16 tag;
1435+ __le16 len;
1436+
1437+ u8 action;
1438+ u8 icap_len;
1439+ u8 _rsv[2];
1440+ union {
1441+ __le32 op_mode;
1442+ __le32 freq;
1443+
1444+ struct {
1445+ __le32 func_idx;
1446+ union {
1447+ __le32 func_data;
1448+ __le32 cal_dump;
1449+
1450+ u8 _pad[80];
1451+ } param;
1452+ } rf;
1453+ } op;
1454+} __packed;
1455+
1456+struct mt7996_tm_req {
1457+ u8 _rsv[4];
1458+
1459+ struct mt7996_tm_rf_test rf_test;
1460+} __packed;
1461+
1462+struct mt7996_tm_rf_test_result {
1463+ __le32 func_idx;
1464+ __le32 payload_length;
1465+ u8 event[0];
1466+};
1467+
1468+struct mt7996_tm_event {
1469+ u8 _rsv[4];
1470+
1471+ __le16 tag;
1472+ __le16 len;
1473+ struct mt7996_tm_rf_test_result result;
1474+} __packed;
1475+
1476+enum {
1477+ RF_ACTION_SWITCH_TO_RF_TEST,
1478+ RF_ACTION_IN_RF_TEST,
1479+ RF_ACTION_SET = 3,
1480+ RF_ACTION_GET,
1481+};
1482+
1483+enum {
1484+ RF_OPER_NORMAL,
1485+ RF_OPER_RF_TEST,
1486+ RF_OPER_ICAP,
1487+ RF_OPER_ICAP_OVERLAP,
1488+ RF_OPER_WIFI_SPECTRUM,
1489+};
1490+
1491+enum {
1492+ UNI_RF_TEST_CTRL,
1493+};
1494+
1495+#define RF_CMD(cmd) RF_TEST_CMD_##cmd
1496+
1497+enum {
1498+ RF_TEST_CMD_STOP_TEST = 0,
1499+ RF_TEST_CMD_START_TX = 1,
1500+ RF_TEST_CMD_START_RX = 2,
1501+ RF_TEST_CMD_CONT_WAVE = 10,
1502+ RF_TEST_CMD_TX_COMMIT = 18,
1503+ RF_TEST_CMD_RX_COMMIT = 19,
1504+};
1505+
1506+#define SET_ID(id) RF_TEST_ID_SET_##id
1507+#define GET_ID(id) RF_TEST_ID_GET_##id
1508+
1509+enum {
1510+ RF_TEST_ID_SET_COMMAND = 1,
1511+ RF_TEST_ID_SET_POWER = 2,
1512+ RF_TEST_ID_SET_TX_RATE = 3,
1513+ RF_TEST_ID_SET_TX_MODE = 4,
1514+ RF_TEST_ID_SET_TX_LEN = 6,
1515+ RF_TEST_ID_SET_TX_COUNT = 7,
1516+ RF_TEST_ID_SET_IPG = 8,
1517+ RF_TEST_ID_SET_GI = 16,
1518+ RF_TEST_ID_SET_STBC = 17,
1519+ RF_TEST_ID_SET_CHAN_FREQ = 18,
1520+ RF_TEST_ID_GET_TXED_COUNT = 32,
1521+ RF_TEST_ID_SET_CONT_WAVE_MODE = 65,
1522+ RF_TEST_ID_SET_DA = 68,
1523+ RF_TEST_ID_SET_SA = 69,
1524+ RF_TEST_ID_SET_CBW = 71,
1525+ RF_TEST_ID_SET_DBW = 72,
1526+ RF_TEST_ID_SET_PRIMARY_CH = 73,
1527+ RF_TEST_ID_SET_ENCODE_MODE = 74,
1528+ RF_TEST_ID_SET_BAND = 90,
1529+ RF_TEST_ID_SET_TRX_COUNTER_RESET = 91,
1530+ RF_TEST_ID_SET_MAC_HEADER = 101,
1531+ RF_TEST_ID_SET_SEQ_CTRL = 102,
1532+ RF_TEST_ID_SET_PAYLOAD = 103,
1533+ RF_TEST_ID_SET_BAND_IDX = 104,
1534+ RF_TEST_ID_SET_RX_PATH = 106,
1535+ RF_TEST_ID_SET_FREQ_OFFSET = 107,
1536+ RF_TEST_ID_GET_FREQ_OFFSET = 108,
1537+ RF_TEST_ID_SET_TX_PATH = 113,
1538+ RF_TEST_ID_SET_NSS = 114,
1539+ RF_TEST_ID_SET_ANT_MASK = 115,
1540+ RF_TEST_ID_SET_IBF_ENABLE = 126,
1541+ RF_TEST_ID_SET_EBF_ENABLE = 127,
1542+ RF_TEST_ID_GET_TX_POWER = 136,
1543+ RF_TEST_ID_SET_RX_MU_AID = 157,
1544+ RF_TEST_ID_SET_HW_TX_MODE = 167,
1545+ RF_TEST_ID_SET_PUNCTURE = 168,
1546+ RF_TEST_ID_SET_FREQ_OFFSET_C2 = 171,
1547+ RF_TEST_ID_GET_FREQ_OFFSET_C2 = 172,
1548+ RF_TEST_ID_SET_CFG_ON = 176,
1549+ RF_TEST_ID_SET_CFG_OFF = 177,
1550+ RF_TEST_ID_SET_BSSID = 189,
1551+ RF_TEST_ID_SET_TX_TIME = 190,
1552+ RF_TEST_ID_SET_MAX_PE = 191,
1553+ RF_TEST_ID_SET_AID_OFFSET = 204,
1554+};
1555+
1556+#define POWER_CTRL(type) UNI_TXPOWER_##type##_CTRL
1557+
1558+struct mt7996_tm_rx_stat_user_ctrl {
1559+ __le16 tag;
1560+ __le16 len;
1561+
1562+ u8 band_idx;
1563+ u8 rsv;
1564+ __le16 user_idx;
1565+} __packed;
1566+
1567+struct mt7996_tm_rx_stat_all {
1568+ __le16 tag;
1569+ __le16 len;
1570+
1571+ u8 band_idx;
1572+ u8 rsv[3];
1573+} __packed;
1574+
1575+struct mt7996_tm_rx_req {
1576+ u8 band;
1577+ u8 _rsv[3];
1578+
1579+ union {
1580+ struct mt7996_tm_rx_stat_user_ctrl user_ctrl;
1581+ struct mt7996_tm_rx_stat_all rx_stat_all;
1582+ };
1583+} __packed;
1584+
1585+enum {
1586+ UNI_TM_RX_STAT_SET_USER_CTRL = 7,
1587+ UNI_TM_RX_STAT_GET_ALL_V2 = 9,
1588+};
1589+
1590+struct rx_band_info {
1591+ /* mac part */
1592+ __le16 mac_rx_fcs_err_cnt;
1593+ __le16 mac_rx_len_mismatch;
1594+ __le16 mac_rx_fcs_ok_cnt;
1595+ u8 rsv1[2];
1596+ __le32 mac_rx_mdrdy_cnt;
1597+
1598+ /* phy part */
1599+ __le16 phy_rx_fcs_err_cnt_cck;
1600+ __le16 phy_rx_fcs_err_cnt_ofdm;
1601+ __le16 phy_rx_pd_cck;
1602+ __le16 phy_rx_pd_ofdm;
1603+ __le16 phy_rx_sig_err_cck;
1604+ __le16 phy_rx_sfd_err_cck;
1605+ __le16 phy_rx_sig_err_ofdm;
1606+ __le16 phy_rx_tag_err_ofdm;
1607+ __le16 phy_rx_mdrdy_cnt_cck;
1608+ __le16 phy_rx_mdrdy_cnt_ofdm;
1609+} __packed;
1610+
1611+struct rx_band_info_ext {
1612+ /* mac part */
1613+ __le32 mac_rx_mpdu_cnt;
1614+
1615+ /* phy part */
1616+ u8 rsv[4];
1617+} __packed;
1618+
1619+struct rx_common_info {
1620+ __le16 rx_fifo_full;
1621+ u8 rsv[2];
1622+ __le32 aci_hit_low;
1623+ __le32 aci_hit_high;
1624+} __packed;
1625+
1626+struct rx_common_info_ext {
1627+ __le32 driver_rx_count;
1628+ __le32 sinr;
1629+ __le32 mu_pkt_count;
1630+
1631+ /* mac part */
1632+ u8 _rsv[4];
1633+
1634+ /* phy part */
1635+ u8 sig_mcs;
1636+ u8 rsv[3];
1637+} __packed;
1638+
1639+struct rx_rxv_info {
1640+ __le16 rcpi;
1641+ s16 rssi;
1642+ s16 snr;
1643+ s16 adc_rssi;
1644+} __packed;
1645+
1646+struct rx_rssi_info {
1647+ s8 ib_rssi;
1648+ s8 wb_rssi;
1649+ u8 rsv[2];
1650+} __packed;
1651+
1652+struct rx_user_info {
1653+ s32 freq_offset;
1654+ s32 snr;
1655+ __le32 fcs_err_count;
1656+} __packed;
1657+
1658+struct rx_user_info_ext {
1659+ s8 ne_var_db_all_user;
1660+ u8 rsv[3];
1661+} __packed;
1662+
1663+#define MAX_ANTENNA_NUM 8
1664+#define MAX_USER_NUM 16
1665+
1666+struct mt7996_tm_rx_event_stat_all {
1667+ __le16 tag;
1668+ __le16 len;
1669+
1670+ struct rx_band_info band_info;
1671+ struct rx_band_info_ext band_info_ext;
1672+ struct rx_common_info common_info;
1673+ struct rx_common_info_ext common_info_ext;
1674+
1675+ /* RXV info */
1676+ struct rx_rxv_info rxv_info[MAX_ANTENNA_NUM];
1677+
1678+ /* RSSI info */
1679+ struct rx_rssi_info fagc[MAX_ANTENNA_NUM];
1680+ struct rx_rssi_info inst[MAX_ANTENNA_NUM];
1681+
1682+ /* User info */
1683+ struct rx_user_info user_info[MAX_USER_NUM];
1684+ struct rx_user_info_ext user_info_ext[MAX_USER_NUM];
1685+} __packed;
1686+
1687+struct mt7996_tm_rx_event {
1688+ u8 _rsv[4];
1689+
1690+ union {
1691+ struct mt7996_tm_rx_event_stat_all rx_stat_all;
1692+ };
1693+} __packed;
1694+
1695+#endif
1696diff --git a/testmode.c b/testmode.c
developer9237f442024-06-14 17:13:04 +08001697index ca4fecc..44f3a5b 100644
developer66e89bc2024-04-23 14:50:01 +08001698--- a/testmode.c
1699+++ b/testmode.c
1700@@ -2,11 +2,13 @@
1701 /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
1702
1703 #include <linux/random.h>
1704+#include "mt76_connac.h"
1705 #include "mt76.h"
1706
1707 const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
1708 [MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
1709 [MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
1710+ [MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
1711 [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
1712 [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
1713 [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
1714@@ -82,6 +84,11 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
1715 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991)
1716 return IEEE80211_MAX_MPDU_LEN_VHT_7991;
1717 return IEEE80211_MAX_MPDU_LEN_VHT_11454;
1718+ case MT76_TM_TX_MODE_EHT_SU:
1719+ case MT76_TM_TX_MODE_EHT_TRIG:
1720+ case MT76_TM_TX_MODE_EHT_MU:
1721+ /* TODO: check the limit */
1722+ return UINT_MAX;
1723 case MT76_TM_TX_MODE_CCK:
1724 case MT76_TM_TX_MODE_OFDM:
1725 default:
1726@@ -183,6 +190,9 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
1727 u8 max_nss = hweight8(phy->antenna_mask);
1728 int ret;
1729
1730+ if (is_mt7996(phy->dev))
1731+ return 0;
1732+
1733 ret = mt76_testmode_alloc_skb(phy, td->tx_mpdu_len);
1734 if (ret)
1735 return ret;
1736@@ -275,7 +285,9 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
1737 td->tx_queued = 0;
1738 td->tx_done = 0;
1739 td->tx_pending = td->tx_count;
1740- mt76_worker_schedule(&dev->tx_worker);
1741+
1742+ if (!is_mt7996(dev))
1743+ mt76_worker_schedule(&dev->tx_worker);
1744 }
1745
1746 static void
1747@@ -284,6 +296,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
1748 struct mt76_testmode_data *td = &phy->test;
1749 struct mt76_dev *dev = phy->dev;
1750
1751+ if (is_mt7996(dev) && dev->test_ops->tx_stop) {
1752+ dev->test_ops->tx_stop(phy);
1753+ return;
1754+ }
1755+
1756 mt76_worker_disable(&dev->tx_worker);
1757
1758 td->tx_pending = 0;
1759@@ -296,22 +313,11 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
1760 mt76_testmode_free_skb(phy);
1761 }
1762
1763-static inline void
1764-mt76_testmode_param_set(struct mt76_testmode_data *td, u16 idx)
1765-{
1766- td->param_set[idx / 32] |= BIT(idx % 32);
1767-}
1768-
1769-static inline bool
1770-mt76_testmode_param_present(struct mt76_testmode_data *td, u16 idx)
1771-{
1772- return td->param_set[idx / 32] & BIT(idx % 32);
1773-}
1774-
1775 static void
1776 mt76_testmode_init_defaults(struct mt76_phy *phy)
1777 {
1778 struct mt76_testmode_data *td = &phy->test;
1779+ u8 addr[ETH_ALEN] = {phy->band_idx, 0x11, 0x22, 0xaa, 0xbb, 0xcc};
1780
1781 if (td->tx_mpdu_len > 0)
1782 return;
1783@@ -319,11 +325,18 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
1784 td->tx_mpdu_len = 1024;
1785 td->tx_count = 1;
1786 td->tx_rate_mode = MT76_TM_TX_MODE_OFDM;
1787+ td->tx_rate_idx = 7;
1788 td->tx_rate_nss = 1;
1789+ /* 0xffff for OFDMA no puncture */
1790+ td->tx_preamble_puncture = ~(td->tx_preamble_puncture & 0);
1791+ td->tx_ipg = 50;
1792
1793- memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
1794- memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
1795- memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
1796+ /* rx stat user config */
1797+ td->aid = 1;
1798+
1799+ memcpy(td->addr[0], addr, ETH_ALEN);
1800+ memcpy(td->addr[1], addr, ETH_ALEN);
1801+ memcpy(td->addr[2], addr, ETH_ALEN);
1802 }
1803
1804 static int
1805@@ -353,7 +366,7 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
1806 if (state == MT76_TM_STATE_TX_FRAMES)
1807 mt76_testmode_tx_start(phy);
1808 else if (state == MT76_TM_STATE_RX_FRAMES) {
1809- memset(&phy->test.rx_stats, 0, sizeof(phy->test.rx_stats));
1810+ dev->test_ops->reset_rx_stats(phy);
1811 }
1812
1813 phy->test.state = state;
1814@@ -404,6 +417,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
1815 return 0;
1816 }
1817
1818+static int
1819+mt76_testmode_set_eeprom(struct mt76_phy *phy, struct nlattr **tb)
1820+{
1821+ struct mt76_dev *dev = phy->dev;
1822+ u8 action, val[MT76_TM_EEPROM_BLOCK_SIZE];
1823+ u32 offset = 0;
1824+ int err = -EINVAL;
1825+
1826+ if (!dev->test_ops->set_eeprom)
1827+ return -EOPNOTSUPP;
1828+
1829+ if (mt76_tm_get_u8(tb[MT76_TM_ATTR_EEPROM_ACTION], &action,
1830+ 0, MT76_TM_EEPROM_ACTION_MAX))
1831+ goto out;
1832+
1833+ if (tb[MT76_TM_ATTR_EEPROM_OFFSET]) {
1834+ struct nlattr *cur;
1835+ int rem, idx = 0;
1836+
1837+ offset = nla_get_u32(tb[MT76_TM_ATTR_EEPROM_OFFSET]);
1838+ if (!!(offset % MT76_TM_EEPROM_BLOCK_SIZE) ||
1839+ !tb[MT76_TM_ATTR_EEPROM_VAL])
1840+ goto out;
1841+
1842+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_EEPROM_VAL], rem) {
1843+ if (nla_len(cur) != 1 || idx >= ARRAY_SIZE(val))
1844+ goto out;
1845+
1846+ val[idx++] = nla_get_u8(cur);
1847+ }
1848+ }
1849+
1850+ err = dev->test_ops->set_eeprom(phy, offset, val, action);
1851+
1852+out:
1853+ return err;
1854+}
1855+
1856 int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1857 void *data, int len)
1858 {
1859@@ -427,6 +478,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1860
1861 mutex_lock(&dev->mutex);
1862
1863+ if (tb[MT76_TM_ATTR_EEPROM_ACTION]) {
1864+ err = mt76_testmode_set_eeprom(phy, tb);
1865+ goto out;
1866+ }
1867+
1868 if (tb[MT76_TM_ATTR_RESET]) {
1869 mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
1870 memset(td, 0, sizeof(*td));
1871@@ -434,6 +490,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1872
1873 mt76_testmode_init_defaults(phy);
1874
1875+ if (tb[MT76_TM_ATTR_SKU_EN])
1876+ td->sku_en = nla_get_u8(tb[MT76_TM_ATTR_SKU_EN]);
1877+
1878 if (tb[MT76_TM_ATTR_TX_COUNT])
1879 td->tx_count = nla_get_u32(tb[MT76_TM_ATTR_TX_COUNT]);
1880
1881@@ -454,7 +513,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1882 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
1883 &td->tx_duty_cycle, 0, 99) ||
1884 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
1885- &td->tx_power_control, 0, 1))
1886+ &td->tx_power_control, 0, 1) ||
1887+ mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16))
1888 goto out;
1889
1890 if (tb[MT76_TM_ATTR_TX_LENGTH]) {
1891@@ -494,7 +554,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1892 idx >= ARRAY_SIZE(td->tx_power))
1893 goto out;
1894
1895- td->tx_power[idx++] = nla_get_u8(cur);
1896+ err = mt76_tm_get_u8(cur, &td->tx_power[idx++], 0, 63);
1897+ if (err)
1898+ return err;
1899 }
1900 }
1901
1902@@ -512,6 +574,22 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1903 }
1904 }
1905
1906+ if (tb[MT76_TM_ATTR_CFG]) {
1907+ struct nlattr *cur;
1908+ int rem, idx = 0;
1909+
1910+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_CFG], rem) {
1911+ if (nla_len(cur) != 1 || idx >= 2)
1912+ goto out;
1913+
1914+ if (idx == 0)
1915+ td->cfg.type = nla_get_u8(cur);
1916+ else
1917+ td->cfg.enable = nla_get_u8(cur);
1918+ idx++;
1919+ }
1920+ }
1921+
1922 if (dev->test_ops->set_params) {
1923 err = dev->test_ops->set_params(phy, tb, state);
1924 if (err)
1925@@ -561,6 +639,9 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
1926 nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_PACKETS, rx_packets,
1927 MT76_TM_STATS_ATTR_PAD) ||
1928 nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_FCS_ERROR, rx_fcs_error,
1929+ MT76_TM_STATS_ATTR_PAD) ||
1930+ nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_LEN_MISMATCH,
1931+ td->rx_stats.len_mismatch,
1932 MT76_TM_STATS_ATTR_PAD))
1933 return -EMSGSIZE;
1934
1935@@ -613,7 +694,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
1936
1937 if (dev->test_mtd.name &&
1938 (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
1939- nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
1940+ nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
1941+ nla_put_u8(msg, MT76_TM_ATTR_BAND_IDX, phy->band_idx)))
1942 goto out;
1943
1944 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
1945@@ -624,6 +706,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
1946 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) ||
1947 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
1948 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
1949+ nla_put_u8(msg, MT76_TM_ATTR_SKU_EN, td->sku_en) ||
1950+ nla_put_u8(msg, MT76_TM_ATTR_AID, td->aid) ||
1951 (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
1952 nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
1953 (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
1954@@ -639,7 +723,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
1955 (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
1956 nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
1957 (mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&
1958- nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
1959+ nla_put_u32(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
1960 goto out;
1961
1962 if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
1963diff --git a/testmode.h b/testmode.h
developer9237f442024-06-14 17:13:04 +08001964index 5e2792d..96872e8 100644
developer66e89bc2024-04-23 14:50:01 +08001965--- a/testmode.h
1966+++ b/testmode.h
1967@@ -5,7 +5,8 @@
1968 #ifndef __MT76_TESTMODE_H
1969 #define __MT76_TESTMODE_H
1970
1971-#define MT76_TM_TIMEOUT 10
1972+#define MT76_TM_TIMEOUT 10
1973+#define MT76_TM_EEPROM_BLOCK_SIZE 16
1974
1975 /**
1976 * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
1977@@ -17,7 +18,9 @@
1978 *
1979 * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
1980 * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
1981+ * @MT76_TM_ATTR_BAND_IDX: band idx of the chip (u8)
1982 *
1983+ * @MT76_TM_ATTR_SKU_EN: config txpower sku is enabled or disabled in testmode (u8)
1984 * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
1985 * state to MT76_TM_STATE_TX_FRAMES (u32)
1986 * @MT76_TM_ATTR_TX_PENDING: pending frames during MT76_TM_STATE_TX_FRAMES (u32)
1987@@ -38,6 +41,11 @@
1988 *
1989 * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
1990 *
1991+ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
1992+ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
1993+ * eeprom cal indicator (u32),
1994+ * dpd_info = [dpd_per_chan_size, chan_num_2g,
1995+ * chan_num_5g, chan_num_6g]
1996 * @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
1997 *
1998 * @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
1999@@ -47,6 +55,29 @@
2000 * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
2001 *
2002 * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
2003+ *
2004+ * @MT76_TM_ATTR_EEPROM_ACTION: eeprom setting actions
2005+ * (u8, see &enum mt76_testmode_eeprom_action)
2006+ * @MT76_TM_ATTR_EEPROM_OFFSET: offset of eeprom data block for writing (u32)
2007+ * @MT76_TM_ATTR_EEPROM_VAL: values for writing into a 16-byte data block
2008+ * (nested, u8 attrs)
2009+ *
2010+ * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg)
2011+ * @MT76_TM_ATTR_TXBF_ACT: txbf setting actions (u8)
2012+ * @MT76_TM_ATTR_TXBF_PARAM: txbf parameters (nested)
2013+ *
2014+ * @MT76_TM_ATTR_OFF_CH_SCAN_CH: config the channel of background chain (ZWDFS) (u8)
2015+ * @MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH: config the center channel of background chain (ZWDFS) (u8)
2016+ * @MT76_TM_ATTR_OFF_CH_SCAN_BW: config the bandwidth of background chain (ZWDFS) (u8)
2017+ * @MT76_TM_ATTR_OFF_CH_SCAN_PATH: config the tx path of background chain (ZWDFS) (u8)
2018+ *
2019+ * @MT76_TM_ATTR_IPI_THRESHOLD: config the IPI index you want to read (u8)
2020+ * @MT76_TM_ATTR_IPI_PERIOD: config the time period for reading
2021+ * the histogram of specific IPI index (u8)
2022+ * @MT76_TM_ATTR_IPI_ANTENNA_INDEX: config the antenna index for reading
2023+ * the histogram of specific IPI index (u8)
2024+ * @MT76_TM_ATTR_IPI_RESET: Reset the IPI counter
2025+ *
2026 */
2027 enum mt76_testmode_attr {
2028 MT76_TM_ATTR_UNSPEC,
2029@@ -56,7 +87,9 @@ enum mt76_testmode_attr {
2030
2031 MT76_TM_ATTR_MTD_PART,
2032 MT76_TM_ATTR_MTD_OFFSET,
2033+ MT76_TM_ATTR_BAND_IDX,
2034
2035+ MT76_TM_ATTR_SKU_EN,
2036 MT76_TM_ATTR_TX_COUNT,
2037 MT76_TM_ATTR_TX_LENGTH,
2038 MT76_TM_ATTR_TX_RATE_MODE,
2039@@ -74,6 +107,8 @@ enum mt76_testmode_attr {
2040 MT76_TM_ATTR_FREQ_OFFSET,
2041
2042 MT76_TM_ATTR_STATS,
2043+ MT76_TM_ATTR_PRECAL,
2044+ MT76_TM_ATTR_PRECAL_INFO,
2045
2046 MT76_TM_ATTR_TX_SPE_IDX,
2047
2048@@ -84,6 +119,27 @@ enum mt76_testmode_attr {
2049 MT76_TM_ATTR_DRV_DATA,
2050
2051 MT76_TM_ATTR_MAC_ADDRS,
2052+ MT76_TM_ATTR_AID,
2053+ MT76_TM_ATTR_RU_ALLOC,
2054+ MT76_TM_ATTR_RU_IDX,
2055+
2056+ MT76_TM_ATTR_EEPROM_ACTION,
2057+ MT76_TM_ATTR_EEPROM_OFFSET,
2058+ MT76_TM_ATTR_EEPROM_VAL,
2059+
2060+ MT76_TM_ATTR_CFG,
2061+ MT76_TM_ATTR_TXBF_ACT,
2062+ MT76_TM_ATTR_TXBF_PARAM,
2063+
2064+ MT76_TM_ATTR_OFF_CH_SCAN_CH,
2065+ MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH,
2066+ MT76_TM_ATTR_OFF_CH_SCAN_BW,
2067+ MT76_TM_ATTR_OFF_CH_SCAN_PATH,
2068+
2069+ MT76_TM_ATTR_IPI_THRESHOLD,
2070+ MT76_TM_ATTR_IPI_PERIOD,
2071+ MT76_TM_ATTR_IPI_ANTENNA_INDEX,
2072+ MT76_TM_ATTR_IPI_RESET,
2073
2074 /* keep last */
2075 NUM_MT76_TM_ATTRS,
2076@@ -101,6 +157,8 @@ enum mt76_testmode_attr {
2077 * @MT76_TM_STATS_ATTR_RX_FCS_ERROR: number of rx packets with FCS error (u64)
2078 * @MT76_TM_STATS_ATTR_LAST_RX: information about the last received packet
2079 * see &enum mt76_testmode_rx_attr
2080+ * @MT76_TM_STATS_ATTR_RX_LEN_MISMATCH: number of rx packets with length
2081+ * mismatch error (u64)
2082 */
2083 enum mt76_testmode_stats_attr {
2084 MT76_TM_STATS_ATTR_UNSPEC,
2085@@ -113,6 +171,7 @@ enum mt76_testmode_stats_attr {
2086 MT76_TM_STATS_ATTR_RX_PACKETS,
2087 MT76_TM_STATS_ATTR_RX_FCS_ERROR,
2088 MT76_TM_STATS_ATTR_LAST_RX,
2089+ MT76_TM_STATS_ATTR_RX_LEN_MISMATCH,
2090
2091 /* keep last */
2092 NUM_MT76_TM_STATS_ATTRS,
2093@@ -125,6 +184,7 @@ enum mt76_testmode_stats_attr {
2094 *
2095 * @MT76_TM_RX_ATTR_FREQ_OFFSET: frequency offset (s32)
2096 * @MT76_TM_RX_ATTR_RCPI: received channel power indicator (array, u8)
2097+ * @MT76_TM_RX_ATTR_RSSI: received signal strength indicator (array, s8)
2098 * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (array, s8)
2099 * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (array, s8)
2100 * @MT76_TM_RX_ATTR_SNR: signal-to-noise ratio (u8)
2101@@ -134,6 +194,7 @@ enum mt76_testmode_rx_attr {
2102
2103 MT76_TM_RX_ATTR_FREQ_OFFSET,
2104 MT76_TM_RX_ATTR_RCPI,
2105+ MT76_TM_RX_ATTR_RSSI,
2106 MT76_TM_RX_ATTR_IB_RSSI,
2107 MT76_TM_RX_ATTR_WB_RSSI,
2108 MT76_TM_RX_ATTR_SNR,
2109@@ -177,6 +238,9 @@ enum mt76_testmode_state {
2110 * @MT76_TM_TX_MODE_HE_EXT_SU: 802.11ax extended-range SU
2111 * @MT76_TM_TX_MODE_HE_TB: 802.11ax trigger-based
2112 * @MT76_TM_TX_MODE_HE_MU: 802.11ax multi-user MIMO
2113+ * @MT76_TM_TX_MODE_EHT_SU: 802.11be single-user MIMO
2114+ * @MT76_TM_TX_MODE_EHT_TRIG: 802.11be trigger-based
2115+ * @MT76_TM_TX_MODE_EHT_MU: 802.11be multi-user MIMO
2116 */
2117 enum mt76_testmode_tx_mode {
2118 MT76_TM_TX_MODE_CCK,
2119@@ -187,12 +251,33 @@ enum mt76_testmode_tx_mode {
2120 MT76_TM_TX_MODE_HE_EXT_SU,
2121 MT76_TM_TX_MODE_HE_TB,
2122 MT76_TM_TX_MODE_HE_MU,
2123+ MT76_TM_TX_MODE_EHT_SU,
2124+ MT76_TM_TX_MODE_EHT_TRIG,
2125+ MT76_TM_TX_MODE_EHT_MU,
2126
2127 /* keep last */
2128 NUM_MT76_TM_TX_MODES,
2129 MT76_TM_TX_MODE_MAX = NUM_MT76_TM_TX_MODES - 1,
2130 };
2131
2132+/**
2133+ * enum mt76_testmode_eeprom_action - eeprom setting actions
2134+ *
2135+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
2136+ * eeprom data block
2137+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
2138+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
2139+ */
2140+enum mt76_testmode_eeprom_action {
2141+ MT76_TM_EEPROM_ACTION_UPDATE_DATA,
2142+ MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
2143+ MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
2144+
2145+ /* keep last */
2146+ NUM_MT76_TM_EEPROM_ACTION,
2147+ MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
2148+};
2149+
2150 extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
2151
2152 #endif
2153diff --git a/tools/fields.c b/tools/fields.c
developer9237f442024-06-14 17:13:04 +08002154index e3f6908..055f90f 100644
developer66e89bc2024-04-23 14:50:01 +08002155--- a/tools/fields.c
2156+++ b/tools/fields.c
2157@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
2158 [MT76_TM_STATE_IDLE] = "idle",
2159 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
2160 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
2161+ [MT76_TM_STATE_TX_CONT] = "tx_cont",
2162 };
2163
2164 static const char * const testmode_tx_mode[] = {
2165@@ -21,6 +22,9 @@ static const char * const testmode_tx_mode[] = {
2166 [MT76_TM_TX_MODE_HE_EXT_SU] = "he_ext_su",
2167 [MT76_TM_TX_MODE_HE_TB] = "he_tb",
2168 [MT76_TM_TX_MODE_HE_MU] = "he_mu",
2169+ [MT76_TM_TX_MODE_EHT_SU] = "eht_su",
2170+ [MT76_TM_TX_MODE_EHT_TRIG] = "eht_tb",
2171+ [MT76_TM_TX_MODE_EHT_MU] = "eht_mu",
2172 };
2173
2174 static void print_enum(const struct tm_field *field, struct nlattr *attr)
2175@@ -65,7 +69,7 @@ static bool parse_u8(const struct tm_field *field, int idx,
2176
2177 static void print_u8(const struct tm_field *field, struct nlattr *attr)
2178 {
2179- printf("%d", nla_get_u8(attr));
2180+ printf("%u", nla_get_u8(attr));
2181 }
2182
2183 static void print_s8(const struct tm_field *field, struct nlattr *attr)
2184@@ -86,12 +90,12 @@ static void print_s32(const struct tm_field *field, struct nlattr *attr)
2185
2186 static void print_u32(const struct tm_field *field, struct nlattr *attr)
2187 {
2188- printf("%d", nla_get_u32(attr));
2189+ printf("%u", nla_get_u32(attr));
2190 }
2191
2192 static void print_u64(const struct tm_field *field, struct nlattr *attr)
2193 {
2194- printf("%lld", (unsigned long long)nla_get_u64(attr));
2195+ printf("%llu", (unsigned long long)nla_get_u64(attr));
2196 }
2197
2198 static bool parse_flag(const struct tm_field *field, int idx,
2199@@ -201,6 +205,62 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2200 printf("%srx_per=%.02f%%\n", prefix, 100 * failed / total);
2201 }
2202
2203+static bool parse_mac(const struct tm_field *field, int idx,
2204+ struct nl_msg *msg, const char *val)
2205+{
2206+#define ETH_ALEN 6
2207+ bool ret = true;
2208+ char *str, *cur, *ap;
2209+ void *a;
2210+
2211+ str = strdup(val);
2212+ ap = str;
2213+
2214+ a = nla_nest_start(msg, idx);
2215+
2216+ idx = 0;
2217+ while ((cur = strsep(&ap, ",")) != NULL) {
2218+ unsigned char addr[ETH_ALEN];
2219+ char *val, *tmp = cur;
2220+ int i = 0;
2221+
2222+ while ((val = strsep(&tmp, ":")) != NULL) {
2223+ if (i >= ETH_ALEN)
2224+ break;
2225+
2226+ addr[i++] = strtoul(val, NULL, 16);
2227+ }
2228+
2229+ nla_put(msg, idx, ETH_ALEN, addr);
2230+
2231+ idx++;
2232+ }
2233+
2234+ nla_nest_end(msg, a);
2235+
2236+ free(str);
2237+
2238+ return ret;
2239+}
2240+
2241+static void print_mac(const struct tm_field *field, struct nlattr *attr)
2242+{
2243+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
2244+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
2245+ unsigned char addr[3][6];
2246+ struct nlattr *cur;
2247+ int idx = 0;
2248+ int rem;
2249+
2250+ nla_for_each_nested(cur, attr, rem) {
2251+ if (nla_len(cur) != 6)
2252+ continue;
2253+ memcpy(addr[idx++], nla_data(cur), 6);
2254+ }
2255+
2256+ printf("" MACSTR "," MACSTR "," MACSTR "",
2257+ MAC2STR(addr[0]), MAC2STR(addr[1]), MAC2STR(addr[2]));
2258+}
2259
2260 #define FIELD_GENERIC(_field, _name, ...) \
2261 [FIELD_NAME(_field)] = { \
2262@@ -250,10 +310,18 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2263 ##__VA_ARGS__ \
2264 )
2265
2266+#define FIELD_MAC(_field, _name) \
2267+ [FIELD_NAME(_field)] = { \
2268+ .name = _name, \
2269+ .parse = parse_mac, \
2270+ .print = print_mac \
2271+ }
2272+
2273 #define FIELD_NAME(_field) MT76_TM_RX_ATTR_##_field
2274 static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
2275 FIELD_RO(s32, FREQ_OFFSET, "freq_offset"),
2276 FIELD_ARRAY_RO(u8, RCPI, "rcpi"),
2277+ FIELD_ARRAY_RO(s8, RSSI, "rssi"),
2278 FIELD_ARRAY_RO(s8, IB_RSSI, "ib_rssi"),
2279 FIELD_ARRAY_RO(s8, WB_RSSI, "wb_rssi"),
2280 FIELD_RO(s8, SNR, "snr"),
2281@@ -261,6 +329,7 @@ static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
2282 static struct nla_policy rx_policy[NUM_MT76_TM_RX_ATTRS] = {
2283 [MT76_TM_RX_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
2284 [MT76_TM_RX_ATTR_RCPI] = { .type = NLA_NESTED },
2285+ [MT76_TM_RX_ATTR_RSSI] = { .type = NLA_NESTED },
2286 [MT76_TM_RX_ATTR_IB_RSSI] = { .type = NLA_NESTED },
2287 [MT76_TM_RX_ATTR_WB_RSSI] = { .type = NLA_NESTED },
2288 [MT76_TM_RX_ATTR_SNR] = { .type = NLA_U8 },
2289@@ -274,6 +343,7 @@ static const struct tm_field stats_fields[NUM_MT76_TM_STATS_ATTRS] = {
2290 FIELD_RO(u32, TX_DONE, "tx_done"),
2291 FIELD_RO(u64, RX_PACKETS, "rx_packets"),
2292 FIELD_RO(u64, RX_FCS_ERROR, "rx_fcs_error"),
2293+ FIELD_RO(u64, RX_LEN_MISMATCH, "rx_len_mismatch"),
2294 FIELD_NESTED_RO(LAST_RX, rx, "last_"),
2295 };
2296 static struct nla_policy stats_policy[NUM_MT76_TM_STATS_ATTRS] = {
2297@@ -282,6 +352,7 @@ static struct nla_policy stats_policy[NUM_MT76_TM_STATS_ATTRS] = {
2298 [MT76_TM_STATS_ATTR_TX_DONE] = { .type = NLA_U32 },
2299 [MT76_TM_STATS_ATTR_RX_PACKETS] = { .type = NLA_U64 },
2300 [MT76_TM_STATS_ATTR_RX_FCS_ERROR] = { .type = NLA_U64 },
2301+ [MT76_TM_STATS_ATTR_RX_LEN_MISMATCH] = { .type = NLA_U64 },
2302 };
2303 #undef FIELD_NAME
2304
2305@@ -291,6 +362,7 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
2306 FIELD_ENUM(STATE, "state", testmode_state),
2307 FIELD_RO(string, MTD_PART, "mtd_part"),
2308 FIELD_RO(u32, MTD_OFFSET, "mtd_offset"),
2309+ FIELD(u8, SKU_EN, "sku_en"),
2310 FIELD(u32, TX_COUNT, "tx_count"),
2311 FIELD(u32, TX_LENGTH, "tx_length"),
2312 FIELD_ENUM(TX_RATE_MODE, "tx_rate_mode", testmode_tx_mode),
2313@@ -300,12 +372,20 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
2314 FIELD(u8, TX_RATE_LDPC, "tx_rate_ldpc"),
2315 FIELD(u8, TX_RATE_STBC, "tx_rate_stbc"),
2316 FIELD(u8, TX_LTF, "tx_ltf"),
2317+ FIELD(u8, TX_DUTY_CYCLE, "tx_duty_cycle"),
2318+ FIELD(u32, TX_IPG, "tx_ipg"),
2319+ FIELD(u32, TX_TIME, "tx_time"),
2320 FIELD(u8, TX_POWER_CONTROL, "tx_power_control"),
2321 FIELD_ARRAY(u8, TX_POWER, "tx_power"),
2322 FIELD(u8, TX_ANTENNA, "tx_antenna"),
2323 FIELD(u32, FREQ_OFFSET, "freq_offset"),
2324+ FIELD(u8, AID, "aid"),
2325+ FIELD(u8, RU_ALLOC, "ru_alloc"),
2326+ FIELD(u8, RU_IDX, "ru_idx"),
2327+ FIELD_MAC(MAC_ADDRS, "mac_addrs"),
2328 FIELD_NESTED_RO(STATS, stats, "",
2329 .print_extra = print_extra_stats),
2330+
2331 };
2332 #undef FIELD_NAME
2333
2334@@ -313,6 +393,7 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
2335 [MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
2336 [MT76_TM_ATTR_MTD_PART] = { .type = NLA_STRING },
2337 [MT76_TM_ATTR_MTD_OFFSET] = { .type = NLA_U32 },
2338+ [MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
2339 [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
2340 [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
2341 [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
2342@@ -322,10 +403,25 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
2343 [MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 },
2344 [MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
2345 [MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
2346+ [MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 },
2347+ [MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 },
2348+ [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
2349 [MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },
2350 [MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },
2351+ [MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 },
2352 [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
2353+ [MT76_TM_ATTR_AID] = { .type = NLA_U8 },
2354+ [MT76_TM_ATTR_RU_ALLOC] = { .type = NLA_U8 },
2355+ [MT76_TM_ATTR_RU_IDX] = { .type = NLA_U8 },
2356 [MT76_TM_ATTR_STATS] = { .type = NLA_NESTED },
2357+ [MT76_TM_ATTR_TXBF_ACT] = { .type = NLA_U8 },
2358+ [MT76_TM_ATTR_OFF_CH_SCAN_CH] = { .type = NLA_U8 },
2359+ [MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH] = { .type = NLA_U8 },
2360+ [MT76_TM_ATTR_OFF_CH_SCAN_BW] = { .type = NLA_U8 },
2361+ [MT76_TM_ATTR_IPI_THRESHOLD] = { .type = NLA_U8 },
2362+ [MT76_TM_ATTR_IPI_PERIOD] = { .type = NLA_U32 },
2363+ [MT76_TM_ATTR_IPI_ANTENNA_INDEX] = { .type = NLA_U8 },
2364+ [MT76_TM_ATTR_IPI_RESET] = { .type = NLA_U8 },
2365 };
2366
2367 const struct tm_field msg_field = {
2368--
developer9237f442024-06-14 17:13:04 +080023692.18.0
developer66e89bc2024-04-23 14:50:01 +08002370