blob: fcea41b4344074bb135144f6e7d6e9cf97993482 [file] [log] [blame]
developerc6f56bb2022-06-14 18:36:30 +08001From 2e542afa1d9932b4ec588ad2c622c74a16fa1edd Mon Sep 17 00:00:00 2001
developer4c6b6002022-05-30 16:36:44 +08002From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Thu, 21 Apr 2022 15:43:19 +0800
developerc6f56bb2022-06-14 18:36:30 +08004Subject: [PATCH] mt76: testmode: additional supports
developer4c6b6002022-05-30 16:36:44 +08005
6Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
7---
developerc6f56bb2022-06-14 18:36:30 +08008 drivers/net/wireless/mediatek/mt76/dma.c | 3 +-
9 drivers/net/wireless/mediatek/mt76/mac80211.c | 12 +
10 drivers/net/wireless/mediatek/mt76/mt76.h | 111 +-
11 .../wireless/mediatek/mt76/mt76_connac_mcu.c | 4 +
12 .../wireless/mediatek/mt76/mt76_connac_mcu.h | 2 +
13 .../net/wireless/mediatek/mt76/mt7915/init.c | 2 +-
14 .../net/wireless/mediatek/mt76/mt7915/mac.c | 37 +-
15 .../net/wireless/mediatek/mt76/mt7915/main.c | 2 +-
16 .../net/wireless/mediatek/mt76/mt7915/mcu.c | 11 +-
17 .../net/wireless/mediatek/mt76/mt7915/mcu.h | 31 +-
18 .../net/wireless/mediatek/mt76/mt7915/mmio.c | 2 +
19 .../wireless/mediatek/mt76/mt7915/mt7915.h | 14 +-
20 .../net/wireless/mediatek/mt76/mt7915/regs.h | 3 +
21 .../wireless/mediatek/mt76/mt7915/testmode.c | 1171 +++++++++++++++--
22 .../wireless/mediatek/mt76/mt7915/testmode.h | 278 ++++
23 drivers/net/wireless/mediatek/mt76/testmode.c | 274 +++-
24 drivers/net/wireless/mediatek/mt76/testmode.h | 75 ++
25 .../net/wireless/mediatek/mt76/tools/fields.c | 80 ++
26 drivers/net/wireless/mediatek/mt76/tx.c | 3 +-
27 19 files changed, 1963 insertions(+), 152 deletions(-)
developer4c6b6002022-05-30 16:36:44 +080028
29diff --git a/dma.c b/dma.c
30index 30de8be4..f6f5f129 100644
31--- a/dma.c
32+++ b/dma.c
33@@ -426,8 +426,7 @@ free:
34 if (mt76_is_testmode_skb(dev, skb, &hw)) {
35 struct mt76_phy *phy = hw->priv;
36
37- if (tx_info.skb == phy->test.tx_skb)
38- phy->test.tx_done--;
39+ phy->test.tx_done--;
40 }
41 #endif
42
43diff --git a/mac80211.c b/mac80211.c
developerc6f56bb2022-06-14 18:36:30 +080044index 31602d7f..49b99f36 100644
developer4c6b6002022-05-30 16:36:44 +080045--- a/mac80211.c
46+++ b/mac80211.c
47@@ -55,6 +55,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
48 CHAN5G(60, 5300),
49 CHAN5G(64, 5320),
50
51+ CHAN5G(68, 5340),
52+ CHAN5G(80, 5400),
53+ CHAN5G(84, 5420),
54+ CHAN5G(88, 5440),
55+ CHAN5G(92, 5460),
56+ CHAN5G(96, 5480),
57+
58 CHAN5G(100, 5500),
59 CHAN5G(104, 5520),
60 CHAN5G(108, 5540),
61@@ -75,6 +82,11 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
62 CHAN5G(165, 5825),
63 CHAN5G(169, 5845),
64 CHAN5G(173, 5865),
65+
66+ CHAN5G(184, 4920),
67+ CHAN5G(188, 4940),
68+ CHAN5G(192, 4960),
69+ CHAN5G(196, 4980),
70 };
71
72 static const struct ieee80211_channel mt76_channels_6ghz[] = {
73diff --git a/mt76.h b/mt76.h
developerc6f56bb2022-06-14 18:36:30 +080074index 8f6279c5..3d1e893d 100644
developer4c6b6002022-05-30 16:36:44 +080075--- a/mt76.h
76+++ b/mt76.h
77@@ -602,6 +602,21 @@ struct mt76_testmode_ops {
78 int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
79 enum mt76_testmode_state new_state);
80 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
81+ int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
82+};
83+
84+struct mt76_testmode_entry_data {
85+ struct sk_buff *tx_skb;
86+
87+ u16 tx_mpdu_len;
88+ u8 tx_rate_idx;
89+ u8 tx_rate_nss;
90+ u8 tx_rate_ldpc;
91+
92+ u8 addr[3][ETH_ALEN];
93+ u8 aid;
94+ u8 ru_alloc;
95+ u8 ru_idx;
96 };
97
98 #define MT_TM_FW_RX_COUNT BIT(0)
99@@ -610,16 +625,11 @@ struct mt76_testmode_data {
100 enum mt76_testmode_state state;
101
102 u32 param_set[DIV_ROUND_UP(NUM_MT76_TM_ATTRS, 32)];
103- struct sk_buff *tx_skb;
104
105 u32 tx_count;
106- u16 tx_mpdu_len;
107
108 u8 tx_rate_mode;
109- u8 tx_rate_idx;
110- u8 tx_rate_nss;
111 u8 tx_rate_sgi;
112- u8 tx_rate_ldpc;
113 u8 tx_rate_stbc;
114 u8 tx_ltf;
115
116@@ -635,10 +645,37 @@ struct mt76_testmode_data {
117 u8 tx_power[4];
118 u8 tx_power_control;
119
120- u8 addr[3][ETH_ALEN];
121+ struct list_head tm_entry_list;
122+ struct mt76_wcid *cur_entry;
123+ u8 entry_num;
124+ union {
125+ struct mt76_testmode_entry_data ed;
126+ struct {
127+ /* must be the same as mt76_testmode_entry_data */
128+ struct sk_buff *tx_skb;
129+
130+ u16 tx_mpdu_len;
131+ u8 tx_rate_idx;
132+ u8 tx_rate_nss;
133+ u8 tx_rate_ldpc;
134+
135+ u8 addr[3][ETH_ALEN];
136+ u8 aid;
137+ u8 ru_alloc;
138+ u8 ru_idx;
139+ };
140+ };
141
142 u8 flag;
143
144+ struct {
145+ u8 type;
146+ u8 enable;
147+ } cfg;
148+
149+ u8 txbf_act;
150+ u16 txbf_param[8];
151+
152 u32 tx_pending;
153 u32 tx_queued;
154 u16 tx_queued_limit;
155@@ -1120,14 +1157,69 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
156 #endif
157 }
158
159+#ifdef CONFIG_NL80211_TESTMODE
160+static inline struct mt76_wcid *
161+mt76_testmode_first_entry(struct mt76_phy *phy)
162+{
163+ if (list_empty(&phy->test.tm_entry_list) && !phy->test.aid)
164+ return &phy->dev->global_wcid;
165+
166+ return list_first_entry(&phy->test.tm_entry_list,
167+ typeof(struct mt76_wcid),
168+ list);
169+}
170+
171+static inline struct mt76_testmode_entry_data *
172+mt76_testmode_entry_data(struct mt76_phy *phy, struct mt76_wcid *wcid)
173+{
174+ if (!wcid)
175+ return NULL;
176+ if (wcid == &phy->dev->global_wcid)
177+ return &phy->test.ed;
178+
179+ return (struct mt76_testmode_entry_data *)((u8 *)wcid +
180+ phy->hw->sta_data_size);
181+}
182+
183+#define mt76_tm_for_each_entry(phy, wcid, ed) \
184+ for (wcid = mt76_testmode_first_entry(phy), \
185+ ed = mt76_testmode_entry_data(phy, wcid); \
186+ ((phy->test.aid && \
187+ !list_entry_is_head(wcid, &phy->test.tm_entry_list, list)) || \
188+ (!phy->test.aid && wcid == &phy->dev->global_wcid)) && ed; \
189+ wcid = list_next_entry(wcid, list), \
190+ ed = mt76_testmode_entry_data(phy, wcid))
191+#endif
192+
193+static inline bool __mt76_is_testmode_skb(struct mt76_phy *phy,
194+ struct sk_buff *skb)
195+{
196+#ifdef CONFIG_NL80211_TESTMODE
197+ struct mt76_testmode_entry_data *ed = &phy->test.ed;
198+ struct mt76_wcid *wcid;
199+
200+ if (skb == ed->tx_skb)
201+ return true;
202+
203+ mt76_tm_for_each_entry(phy, wcid, ed)
204+ if (skb == ed->tx_skb)
205+ return true;
206+ return false;
207+#else
208+ return false;
209+#endif
210+}
211+
212 static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
213 struct sk_buff *skb,
214 struct ieee80211_hw **hw)
215 {
216 #ifdef CONFIG_NL80211_TESTMODE
217- if (skb == dev->phy.test.tx_skb)
218+ if (mt76_testmode_enabled(&dev->phy) &&
219+ __mt76_is_testmode_skb(&dev->phy, skb))
220 *hw = dev->phy.hw;
221- else if (dev->phy2 && skb == dev->phy2->test.tx_skb)
222+ else if (dev->phy2 && mt76_testmode_enabled(dev->phy2) &&
223+ __mt76_is_testmode_skb(dev->phy2, skb))
224 *hw = dev->phy2->hw;
225 else
226 return false;
227@@ -1227,7 +1319,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
228 int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
229 struct netlink_callback *cb, void *data, int len);
230 int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
231-int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len);
232+int mt76_testmode_init_skb(struct mt76_phy *phy, u32 len,
233+ struct sk_buff **tx_skb, u8 (*addr)[ETH_ALEN]);
234
235 static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
236 {
237diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
238index 4e495d4f..ebb78d33 100644
239--- a/mt76_connac_mcu.c
240+++ b/mt76_connac_mcu.c
241@@ -389,6 +389,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
242 switch (vif->type) {
243 case NL80211_IFTYPE_MESH_POINT:
244 case NL80211_IFTYPE_AP:
245+ case NL80211_IFTYPE_MONITOR:
246 if (vif->p2p)
247 conn_type = CONNECTION_P2P_GC;
248 else
249@@ -570,6 +571,9 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
250 rx->rca2 = 1;
251 rx->rv = 1;
252
253+ if (vif->type == NL80211_IFTYPE_MONITOR)
254+ rx->rca1 = 0;
255+
256 if (!is_connac_v1(dev))
257 return;
258
259diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
260index 82498039..a3bbf5ca 100644
261--- a/mt76_connac_mcu.h
262+++ b/mt76_connac_mcu.h
263@@ -816,6 +816,7 @@ enum {
264 MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
265 MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
266 MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
267+ MCU_EXT_EVENT_BF_STATUS_READ = 0x35,
268 MCU_EXT_EVENT_RDD_REPORT = 0x3a,
269 MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
270 MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
271@@ -993,6 +994,7 @@ enum {
272 MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
273 /* for vendor csi and air monitor */
274 MCU_EXT_CMD_SMESH_CTRL = 0xae,
275+ MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
276 MCU_EXT_CMD_CERT_CFG = 0xb7,
277 MCU_EXT_CMD_CSI_CTRL = 0xc2,
278 };
279diff --git a/mt7915/init.c b/mt7915/init.c
developerc6f56bb2022-06-14 18:36:30 +0800280index e4f6617f..25a9b5de 100644
developer4c6b6002022-05-30 16:36:44 +0800281--- a/mt7915/init.c
282+++ b/mt7915/init.c
developerc6f56bb2022-06-14 18:36:30 +0800283@@ -573,7 +573,7 @@ static void mt7915_init_work(struct work_struct *work)
developer4c6b6002022-05-30 16:36:44 +0800284 struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
285 init_work);
286
287- mt7915_mcu_set_eeprom(dev);
288+ mt7915_mcu_set_eeprom(dev, dev->flash_mode);
289 mt7915_mac_init(dev);
290 mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
291 mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
292diff --git a/mt7915/mac.c b/mt7915/mac.c
developerc6f56bb2022-06-14 18:36:30 +0800293index ffb0037b..12afb204 100644
developer4c6b6002022-05-30 16:36:44 +0800294--- a/mt7915/mac.c
295+++ b/mt7915/mac.c
296@@ -914,17 +914,39 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
297 {
298 #ifdef CONFIG_NL80211_TESTMODE
299 struct mt76_testmode_data *td = &phy->mt76->test;
300+ struct mt76_testmode_entry_data *ed;
301+ struct mt76_wcid *wcid;
302 const struct ieee80211_rate *r;
303- u8 bw, mode, nss = td->tx_rate_nss;
304- u8 rate_idx = td->tx_rate_idx;
305+ u8 bw, mode, nss, rate_idx, ldpc;
306 u16 rateval = 0;
307 u32 val;
308 bool cck = false;
309 int band;
310
311- if (skb != phy->mt76->test.tx_skb)
312+ txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID);
313+ txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
314+ phy->test.spe_idx));
315+
316+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU) {
317+ txwi[1] |= cpu_to_le32(BIT(18));
318+ txwi[2] = 0;
319+ txwi[3] &= ~cpu_to_le32(MT_TXD3_NO_ACK);
320+ le32p_replace_bits(&txwi[3], 0x1f, MT_TXD3_REM_TX_COUNT);
321+
322+ return;
323+ }
324+
325+ mt76_tm_for_each_entry(phy->mt76, wcid, ed)
326+ if (ed->tx_skb == skb)
327+ break;
328+
329+ if (!ed)
330 return;
331
332+ nss = ed->tx_rate_nss;
333+ rate_idx = ed->tx_rate_idx;
334+ ldpc = ed->tx_rate_ldpc;
335+
336 switch (td->tx_rate_mode) {
337 case MT76_TM_TX_MODE_HT:
338 nss = 1 + (rate_idx >> 3);
339@@ -1013,14 +1035,13 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
340 if (mode >= MT_PHY_TYPE_HE_SU)
341 val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf);
342
343- if (td->tx_rate_ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU))
344+ if (ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU))
345 val |= MT_TXD6_LDPC;
346
347- txwi[1] &= ~cpu_to_le32(MT_TXD1_VTA);
348- txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID);
349+ if (phy->test.bf_en)
350+ val |= MT_TXD6_TX_IBF | MT_TXD6_TX_EBF;
351+
352 txwi[6] |= cpu_to_le32(val);
353- txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
354- phy->test.spe_idx));
355 #endif
356 }
357
358diff --git a/mt7915/main.c b/mt7915/main.c
developerc6f56bb2022-06-14 18:36:30 +0800359index f2a6d9da..942b8a9a 100644
developer4c6b6002022-05-30 16:36:44 +0800360--- a/mt7915/main.c
361+++ b/mt7915/main.c
362@@ -221,7 +221,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
363 mvif->phy = phy;
364 mvif->mt76.band_idx = phy->band_idx;
365
366- mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
367+ mvif->mt76.wmm_idx = (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_MONITOR);
368 if (ext_phy)
369 mvif->mt76.wmm_idx += 2;
370
371diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developerc6f56bb2022-06-14 18:36:30 +0800372index 8a3bd33f..8ed8700d 100755
developer4c6b6002022-05-30 16:36:44 +0800373--- a/mt7915/mcu.c
374+++ b/mt7915/mcu.c
375@@ -360,7 +360,6 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
376 if (mcu_txd->ext_cid) {
377 mcu_txd->ext_cid_ack = 1;
378
379- /* do not use Q_SET for efuse */
380 if (cmd & __MCU_CMD_FIELD_QUERY)
381 mcu_txd->set_query = MCU_Q_QUERY;
382 else
383@@ -536,6 +535,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
384 case MCU_EXT_EVENT_BCC_NOTIFY:
385 mt7915_mcu_rx_bcc_notify(dev, skb);
386 break;
387+#ifdef CONFIG_NL80211_TESTMODE
388+ case MCU_EXT_EVENT_BF_STATUS_READ:
389+ mt7915_tm_txbf_status_read(dev, skb);
390+ break;
391+#endif
392 default:
393 break;
394 }
395@@ -565,6 +569,7 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
396 rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
397 rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
398 rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
399+ rxd->ext_eid == MCU_EXT_EVENT_BF_STATUS_READ ||
400 !rxd->seq)
401 mt7915_mcu_rx_unsolicited_event(dev, skb);
402 else
developerc6f56bb2022-06-14 18:36:30 +0800403@@ -3030,14 +3035,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
developer4c6b6002022-05-30 16:36:44 +0800404 return 0;
405 }
406
407-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
408+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
409 {
410 struct mt7915_mcu_eeprom req = {
411 .buffer_mode = EE_MODE_EFUSE,
412 .format = EE_FORMAT_WHOLE,
413 };
414
415- if (dev->flash_mode)
416+ if (flash_mode)
417 return mt7915_mcu_set_eeprom_flash(dev);
418
419 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
420diff --git a/mt7915/mcu.h b/mt7915/mcu.h
developerc6f56bb2022-06-14 18:36:30 +0800421index adf71f10..82c21168 100644
developer4c6b6002022-05-30 16:36:44 +0800422--- a/mt7915/mcu.h
423+++ b/mt7915/mcu.h
424@@ -27,10 +27,15 @@ struct mt7915_mcu_txd {
425
426 enum {
427 MCU_ATE_SET_TRX = 0x1,
428+ MCU_ATE_SET_TSSI = 0x5,
429+ MCU_ATE_SET_DPD = 0x6,
430+ MCU_ATE_SET_RATE_POWER_OFFSET = 0x7,
431+ MCU_ATE_SET_THERMAL_COMP = 0x8,
432 MCU_ATE_SET_FREQ_OFFSET = 0xa,
433 MCU_ATE_SET_PHY_COUNT = 0x11,
434 MCU_ATE_SET_SLOT_TIME = 0x13,
435 MCU_ATE_CLEAN_TXQUEUE = 0x1c,
436+ MCU_ATE_SET_MU_RX_AID = 0x1e,
437 };
438
439 struct mt7915_mcu_rxd {
developerc6f56bb2022-06-14 18:36:30 +0800440@@ -455,6 +460,12 @@ enum {
developer4c6b6002022-05-30 16:36:44 +0800441
442 enum {
443 MT_BF_SOUNDING_ON = 1,
444+ MT_BF_DATA_PACKET_APPLY = 2,
445+ MT_BF_PFMU_TAG_READ = 5,
446+ MT_BF_PFMU_TAG_WRITE = 6,
447+ MT_BF_PHASE_CAL = 14,
448+ MT_BF_IBF_PHASE_COMP = 15,
449+ MT_BF_PROFILE_WRITE_ALL = 17,
450 MT_BF_TYPE_UPDATE = 20,
451 MT_BF_MODULE_UPDATE = 25
452 };
developerc6f56bb2022-06-14 18:36:30 +0800453@@ -681,12 +692,20 @@ struct mt7915_muru {
developer4c6b6002022-05-30 16:36:44 +0800454 #define MURU_OFDMA_SCH_TYPE_DL BIT(0)
455 #define MURU_OFDMA_SCH_TYPE_UL BIT(1)
456
457-/* Common Config */
458-#define MURU_COMM_PPDU_FMT BIT(0)
459-#define MURU_COMM_SCH_TYPE BIT(1)
460-#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE)
461-
462-/* DL&UL User config*/
463+/* Common Config */
464+/* #define MURU_COMM_PPDU_FMT BIT(0) */
465+/* #define MURU_COMM_SCH_TYPE BIT(1) */
466+/* #define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE) */
467+#define MURU_COMM_PPDU_FMT BIT(0)
468+#define MURU_COMM_SCH_TYPE BIT(1)
469+#define MURU_COMM_BAND BIT(2)
470+#define MURU_COMM_WMM BIT(3)
471+#define MURU_COMM_SPE_IDX BIT(4)
472+#define MURU_COMM_PROC_TYPE BIT(5)
473+#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \
474+ MURU_COMM_WMM | MURU_COMM_SPE_IDX)
475+
476+/* DL&UL User config */
477 #define MURU_USER_CNT BIT(4)
478
479 enum {
480diff --git a/mt7915/mmio.c b/mt7915/mmio.c
developerc6f56bb2022-06-14 18:36:30 +0800481index b3de3a7a..bbf8b16c 100644
developer4c6b6002022-05-30 16:36:44 +0800482--- a/mt7915/mmio.c
483+++ b/mt7915/mmio.c
developerc6f56bb2022-06-14 18:36:30 +0800484@@ -73,6 +73,7 @@ static const u32 mt7915_offs[] = {
developer4c6b6002022-05-30 16:36:44 +0800485 [ARB_DRNGR0] = 0x194,
486 [ARB_SCR] = 0x080,
487 [RMAC_MIB_AIRTIME14] = 0x3b8,
488+ [AGG_AALCR0] = 0x048,
489 [AGG_AWSCR0] = 0x05c,
490 [AGG_PCR0] = 0x06c,
491 [AGG_ACR0] = 0x084,
developerc6f56bb2022-06-14 18:36:30 +0800492@@ -147,6 +148,7 @@ static const u32 mt7916_offs[] = {
developer4c6b6002022-05-30 16:36:44 +0800493 [ARB_DRNGR0] = 0x1e0,
494 [ARB_SCR] = 0x000,
495 [RMAC_MIB_AIRTIME14] = 0x0398,
496+ [AGG_AALCR0] = 0x028,
497 [AGG_AWSCR0] = 0x030,
498 [AGG_PCR0] = 0x040,
499 [AGG_ACR0] = 0x054,
500diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developerc6f56bb2022-06-14 18:36:30 +0800501index cf0630c8..4b375629 100644
developer4c6b6002022-05-30 16:36:44 +0800502--- a/mt7915/mt7915.h
503+++ b/mt7915/mt7915.h
developerc6f56bb2022-06-14 18:36:30 +0800504@@ -294,6 +294,9 @@ struct mt7915_phy {
developer4c6b6002022-05-30 16:36:44 +0800505 u8 last_snr;
506
507 u8 spe_idx;
508+
509+ bool bf_en;
510+ bool bf_ever_en;
511 } test;
512 #endif
513
developerc6f56bb2022-06-14 18:36:30 +0800514@@ -382,6 +385,14 @@ struct mt7915_dev {
developer4c6b6002022-05-30 16:36:44 +0800515 void __iomem *dcm;
516 void __iomem *sku;
517
518+#ifdef CONFIG_NL80211_TESTMODE
519+ struct {
520+ void *txbf_phase_cal;
521+ void *txbf_pfmu_data;
522+ void *txbf_pfmu_tag;
523+ } test;
524+#endif
525+
526 #ifdef MTK_DEBUG
527 u16 wlan_idx;
528 struct {
developerc6f56bb2022-06-14 18:36:30 +0800529@@ -572,7 +583,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
developer4c6b6002022-05-30 16:36:44 +0800530 struct ieee80211_vif *vif,
531 struct ieee80211_sta *sta,
532 void *data, u32 field);
533-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
534+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode);
535 int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
536 int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
537 int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
developerc6f56bb2022-06-14 18:36:30 +0800538@@ -605,6 +616,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
developer4c6b6002022-05-30 16:36:44 +0800539 int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
540 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
541 void mt7915_mcu_exit(struct mt7915_dev *dev);
542+int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
543
544 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
545 {
546diff --git a/mt7915/regs.h b/mt7915/regs.h
developerc6f56bb2022-06-14 18:36:30 +0800547index 99834310..6ba5e9fe 100644
developer4c6b6002022-05-30 16:36:44 +0800548--- a/mt7915/regs.h
549+++ b/mt7915/regs.h
developerc6f56bb2022-06-14 18:36:30 +0800550@@ -50,6 +50,7 @@ enum offs_rev {
developer4c6b6002022-05-30 16:36:44 +0800551 ARB_DRNGR0,
552 ARB_SCR,
553 RMAC_MIB_AIRTIME14,
554+ AGG_AALCR0,
555 AGG_AWSCR0,
556 AGG_PCR0,
557 AGG_ACR0,
developerc6f56bb2022-06-14 18:36:30 +0800558@@ -458,6 +459,8 @@ enum offs_rev {
developer4c6b6002022-05-30 16:36:44 +0800559 #define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000)
560 #define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
561
562+#define MT_AGG_AALCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_AALCR0) + \
563+ (_n) * 4))
564 #define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_AWSCR0) + \
565 (_n) * 4))
566 #define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \
567diff --git a/mt7915/testmode.c b/mt7915/testmode.c
developerc6f56bb2022-06-14 18:36:30 +0800568index e8bf616c..16c9e4ae 100644
developer4c6b6002022-05-30 16:36:44 +0800569--- a/mt7915/testmode.c
570+++ b/mt7915/testmode.c
571@@ -9,6 +9,9 @@
572 enum {
573 TM_CHANGED_TXPOWER,
574 TM_CHANGED_FREQ_OFFSET,
575+ TM_CHANGED_AID,
576+ TM_CHANGED_CFG,
577+ TM_CHANGED_TXBF_ACT,
578
579 /* must be last */
580 NUM_TM_CHANGED
581@@ -17,6 +20,9 @@ enum {
582 static const u8 tm_change_map[] = {
583 [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
584 [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
585+ [TM_CHANGED_AID] = MT76_TM_ATTR_AID,
586+ [TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
587+ [TM_CHANGED_TXBF_ACT] = MT76_TM_ATTR_TXBF_ACT,
588 };
589
590 struct reg_band {
developerc6f56bb2022-06-14 18:36:30 +0800591@@ -33,6 +39,38 @@ struct reg_band {
developer4c6b6002022-05-30 16:36:44 +0800592 #define TM_REG_MAX_ID 20
593 static struct reg_band reg_backup_list[TM_REG_MAX_ID];
594
developerc6f56bb2022-06-14 18:36:30 +0800595+static void mt7915_tm_update_entry(struct mt7915_phy *phy);
596+
developer4c6b6002022-05-30 16:36:44 +0800597+static u8 mt7915_tm_chan_bw(enum nl80211_chan_width width)
598+{
599+ static const u8 width_to_bw[] = {
600+ [NL80211_CHAN_WIDTH_40] = TM_CBW_40MHZ,
601+ [NL80211_CHAN_WIDTH_80] = TM_CBW_80MHZ,
602+ [NL80211_CHAN_WIDTH_80P80] = TM_CBW_8080MHZ,
603+ [NL80211_CHAN_WIDTH_160] = TM_CBW_160MHZ,
604+ [NL80211_CHAN_WIDTH_5] = TM_CBW_5MHZ,
605+ [NL80211_CHAN_WIDTH_10] = TM_CBW_10MHZ,
606+ [NL80211_CHAN_WIDTH_20] = TM_CBW_20MHZ,
607+ [NL80211_CHAN_WIDTH_20_NOHT] = TM_CBW_20MHZ,
608+ };
609+
610+ if (width >= ARRAY_SIZE(width_to_bw))
611+ return 0;
612+
613+ return width_to_bw[width];
614+}
615+
616+static void
617+mt7915_tm_update_channel(struct mt7915_phy *phy)
618+{
619+ mutex_unlock(&phy->dev->mt76.mutex);
620+ mt7915_set_channel(phy);
621+ mutex_lock(&phy->dev->mt76.mutex);
622+
623+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
developerc6f56bb2022-06-14 18:36:30 +0800624+
625+ mt7915_tm_update_entry(phy);
developer4c6b6002022-05-30 16:36:44 +0800626+}
627
628 static int
629 mt7915_tm_set_tx_power(struct mt7915_phy *phy)
developerc6f56bb2022-06-14 18:36:30 +0800630@@ -119,18 +157,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
developer4c6b6002022-05-30 16:36:44 +0800631 }
632
633 static int
634-mt7915_tm_clean_hwq(struct mt7915_phy *phy, u8 wcid)
635+mt7915_tm_clean_hwq(struct mt7915_phy *phy)
636 {
637+ struct mt76_testmode_entry_data *ed;
638+ struct mt76_wcid *wcid;
639 struct mt7915_dev *dev = phy->dev;
640 struct mt7915_tm_cmd req = {
641 .testmode_en = 1,
642 .param_idx = MCU_ATE_CLEAN_TXQUEUE,
643- .param.clean.wcid = wcid,
644 .param.clean.band = phy != &dev->phy,
645 };
646
647- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
648- sizeof(req), false);
649+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
650+ int ret;
651+
652+ req.param.clean.wcid = wcid->idx;
653+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL),
654+ &req, sizeof(req), false);
655+ if (ret)
656+ return ret;
657+ }
658+
659+ return 0;
660 }
661
662 static int
developerc6f56bb2022-06-14 18:36:30 +0800663@@ -182,11 +230,737 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
developer4c6b6002022-05-30 16:36:44 +0800664 return mt7915_mcu_set_muru_ctrl(dev, MURU_SET_ARB_OP_MODE, op_mode);
665 }
666
667+static int
668+mt7915_tm_set_cfg(struct mt7915_phy *phy)
669+{
670+ static const u8 cfg_cmd[] = {
671+ [MT76_TM_CFG_TSSI] = MCU_ATE_SET_TSSI,
672+ [MT76_TM_CFG_DPD] = MCU_ATE_SET_DPD,
673+ [MT76_TM_CFG_RATE_POWER_OFFSET] = MCU_ATE_SET_RATE_POWER_OFFSET,
674+ [MT76_TM_CFG_THERMAL_COMP] = MCU_ATE_SET_THERMAL_COMP,
675+ };
676+ struct mt76_testmode_data *td = &phy->mt76->test;
677+ struct mt7915_dev *dev = phy->dev;
678+ struct mt7915_tm_cmd req = {
679+ .testmode_en = !(phy->mt76->test.state == MT76_TM_STATE_OFF),
680+ .param_idx = cfg_cmd[td->cfg.type],
681+ .param.cfg.enable = td->cfg.enable,
682+ .param.cfg.band = phy->band_idx,
683+ };
684+
685+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
686+ sizeof(req), false);
687+}
688+
689+static int
690+mt7915_tm_add_txbf(struct mt7915_phy *phy, struct ieee80211_vif *vif,
691+ struct ieee80211_sta *sta, u8 pfmu_idx, u8 nr,
692+ u8 nc, bool ebf)
693+{
694+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
695+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
696+ struct mt7915_dev *dev = phy->dev;
697+ struct sk_buff *skb;
698+ struct sta_rec_bf *bf;
699+ struct tlv *tlv;
700+ u8 ndp_rate;
701+
702+ if (nr == 1)
703+ ndp_rate = 8;
704+ else if (nr == 2)
705+ ndp_rate = 16;
706+ else
707+ ndp_rate = 24;
708+
709+ skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
710+ &msta->wcid);
711+ if (IS_ERR(skb))
712+ return PTR_ERR(skb);
713+
714+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
715+ bf = (struct sta_rec_bf *)tlv;
716+
717+ bf->pfmu = cpu_to_le16(pfmu_idx);
718+ bf->sounding_phy = 1;
719+ bf->bf_cap = ebf;
720+ bf->ncol = nc;
721+ bf->nrow = nr;
722+ bf->ndp_rate = ndp_rate;
723+ bf->ibf_timeout = 0xff;
724+ bf->tx_mode = MT_PHY_TYPE_HT;
725+
726+ if (ebf) {
727+ bf->mem[0].row = 0;
728+ bf->mem[1].row = 1;
729+ bf->mem[2].row = 2;
730+ bf->mem[3].row = 3;
731+ } else {
732+ bf->mem[0].row = 4;
733+ bf->mem[1].row = 5;
734+ bf->mem[2].row = 6;
735+ bf->mem[3].row = 7;
736+ }
737+
738+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
739+ MCU_EXT_CMD(STA_REC_UPDATE), true);
740+}
741+
742+static int
743+mt7915_tm_entry_add(struct mt7915_phy *phy, u8 aid)
744+{
745+ struct mt76_testmode_data *td = &phy->mt76->test;
746+ struct mt76_testmode_entry_data *ed;
747+ struct ieee80211_sband_iftype_data *sdata;
748+ struct ieee80211_supported_band *sband;
749+ struct ieee80211_sta *sta;
750+ struct mt7915_sta *msta;
751+ int tid, ret;
752+
753+ if (td->entry_num >= MT76_TM_MAX_ENTRY_NUM)
754+ return -EINVAL;
755+
756+ sta = kzalloc(sizeof(*sta) + phy->mt76->hw->sta_data_size +
757+ sizeof(*ed), GFP_KERNEL);
758+ if (!sta)
759+ return -ENOMEM;
760+
761+ msta = (struct mt7915_sta *)sta->drv_priv;
762+ ed = mt76_testmode_entry_data(phy->mt76, &msta->wcid);
763+ memcpy(ed, &td->ed, sizeof(*ed));
764+
765+ if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) {
766+ sband = &phy->mt76->sband_5g.sband;
767+ sdata = phy->iftype[NL80211_BAND_5GHZ];
768+ } else if (phy->mt76->chandef.chan->band == NL80211_BAND_6GHZ) {
769+ sband = &phy->mt76->sband_6g.sband;
770+ sdata = phy->iftype[NL80211_BAND_6GHZ];
771+ } else {
772+ sband = &phy->mt76->sband_2g.sband;
773+ sdata = phy->iftype[NL80211_BAND_2GHZ];
774+ }
775+
776+ memcpy(sta->addr, ed->addr[0], ETH_ALEN);
777+ if (phy->test.bf_en) {
778+ u8 addr[ETH_ALEN] = {0x00, 0x11, 0x11, 0x11, 0x11, 0x11};
779+
780+ memcpy(sta->addr, addr, ETH_ALEN);
781+ }
782+
783+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_HT)
784+ memcpy(&sta->ht_cap, &sband->ht_cap, sizeof(sta->ht_cap));
785+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_VHT)
786+ memcpy(&sta->vht_cap, &sband->vht_cap, sizeof(sta->vht_cap));
787+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_HE_SU)
788+ memcpy(&sta->he_cap, &sdata[NL80211_IFTYPE_STATION].he_cap,
789+ sizeof(sta->he_cap));
790+ sta->aid = aid;
791+ sta->wme = 1;
792+
793+ ret = mt7915_mac_sta_add(&phy->dev->mt76, phy->monitor_vif, sta);
794+ if (ret) {
795+ kfree(sta);
796+ return ret;
797+ }
798+
799+ /* prevent from starting tx ba session */
800+ for (tid = 0; tid < 8; tid++)
801+ set_bit(tid, &msta->ampdu_state);
802+
803+ list_add_tail(&msta->wcid.list, &td->tm_entry_list);
804+ td->entry_num++;
805+
806+ return 0;
807+}
808+
809+static void
810+mt7915_tm_entry_remove(struct mt7915_phy *phy, u8 aid)
811+{
812+ struct mt76_testmode_data *td = &phy->mt76->test;
813+ struct mt76_wcid *wcid, *tmp;
814+
815+ if (list_empty(&td->tm_entry_list))
816+ return;
817+
818+ list_for_each_entry_safe(wcid, tmp, &td->tm_entry_list, list) {
developerc6f56bb2022-06-14 18:36:30 +0800819+ struct mt76_testmode_entry_data *ed;
developer4c6b6002022-05-30 16:36:44 +0800820+ struct mt7915_dev *dev = phy->dev;
developerc6f56bb2022-06-14 18:36:30 +0800821+ struct ieee80211_sta *sta;
developer4c6b6002022-05-30 16:36:44 +0800822+
developerc6f56bb2022-06-14 18:36:30 +0800823+ ed = mt76_testmode_entry_data(phy->mt76, wcid);
824+ if (aid && ed->aid != aid)
825+ continue;
826+
827+ sta = wcid_to_sta(wcid);
developer4c6b6002022-05-30 16:36:44 +0800828+ mt7915_mac_sta_remove(&dev->mt76, phy->monitor_vif, sta);
829+ mt76_wcid_mask_clear(dev->mt76.wcid_mask, wcid->idx);
830+
831+ list_del_init(&wcid->list);
832+ kfree(sta);
833+ phy->mt76->test.entry_num--;
834+ }
835+}
836+
837+static int
838+mt7915_tm_set_entry(struct mt7915_phy *phy)
839+{
840+ struct mt76_testmode_data *td = &phy->mt76->test;
841+ struct mt76_testmode_entry_data *ed;
842+ struct mt76_wcid *wcid;
843+
844+ if (!td->aid) {
845+ if (td->state > MT76_TM_STATE_IDLE)
846+ mt76_testmode_set_state(phy->mt76, MT76_TM_STATE_IDLE);
847+ mt7915_tm_entry_remove(phy, td->aid);
848+ return 0;
849+ }
850+
851+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
852+ if (ed->aid == td->aid) {
853+ struct sk_buff *skb;
854+
855+ local_bh_disable();
856+ skb = ed->tx_skb;
857+ memcpy(ed, &td->ed, sizeof(*ed));
858+ ed->tx_skb = skb;
859+ local_bh_enable();
860+
861+ return 0;
862+ }
863+ }
864+
865+ return mt7915_tm_entry_add(phy, td->aid);
866+}
867+
developerc6f56bb2022-06-14 18:36:30 +0800868+static void
869+mt7915_tm_update_entry(struct mt7915_phy *phy)
870+{
871+ struct mt76_testmode_data *td = &phy->mt76->test;
872+ struct mt76_testmode_entry_data *ed, tmp;
873+ struct mt76_wcid *wcid, *last;
874+
875+ if (!td->aid || phy->test.bf_en)
876+ return;
877+
878+ memcpy(&tmp, &td->ed, sizeof(tmp));
879+ last = list_last_entry(&td->tm_entry_list,
880+ struct mt76_wcid, list);
881+
882+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
883+ memcpy(&td->ed, ed, sizeof(td->ed));
884+ mt7915_tm_entry_remove(phy, td->aid);
885+ mt7915_tm_entry_add(phy, td->aid);
886+ if (wcid == last)
887+ break;
888+ }
889+
890+ memcpy(&td->ed, &tmp, sizeof(td->ed));
891+}
892+
developer4c6b6002022-05-30 16:36:44 +0800893+static int
894+mt7915_tm_txbf_init(struct mt7915_phy *phy, u16 *val)
895+{
896+ struct mt76_testmode_data *td = &phy->mt76->test;
897+ struct mt7915_dev *dev = phy->dev;
898+ bool enable = val[0];
899+ void *phase_cal, *pfmu_data, *pfmu_tag;
900+ u8 addr[ETH_ALEN] = {0x00, 0x22, 0x22, 0x22, 0x22, 0x22};
901+
902+ if (!enable) {
903+ phy->test.bf_en = 0;
904+ return 0;
905+ }
906+
907+ if (!dev->test.txbf_phase_cal) {
908+ phase_cal = devm_kzalloc(dev->mt76.dev,
909+ sizeof(struct mt7915_tm_txbf_phase) *
910+ MAX_PHASE_GROUP_NUM,
911+ GFP_KERNEL);
912+ if (!phase_cal)
913+ return -ENOMEM;
914+
915+ dev->test.txbf_phase_cal = phase_cal;
916+ }
917+
918+ if (!dev->test.txbf_pfmu_data) {
919+ pfmu_data = devm_kzalloc(dev->mt76.dev, 512, GFP_KERNEL);
920+ if (!pfmu_data)
921+ return -ENOMEM;
922+
923+ dev->test.txbf_pfmu_data = pfmu_data;
924+ }
925+
926+ if (!dev->test.txbf_pfmu_tag) {
927+ pfmu_tag = devm_kzalloc(dev->mt76.dev,
928+ sizeof(struct mt7915_tm_pfmu_tag), GFP_KERNEL);
929+ if (!pfmu_tag)
930+ return -ENOMEM;
931+
932+ dev->test.txbf_pfmu_tag = pfmu_tag;
933+ }
934+
935+ memcpy(phy->monitor_vif->addr, addr, ETH_ALEN);
936+ mt7915_mcu_add_dev_info(phy, phy->monitor_vif, true);
937+
938+ td->tx_rate_mode = MT76_TM_TX_MODE_HT;
939+ td->tx_mpdu_len = 1024;
940+ td->tx_rate_sgi = 0;
941+ td->tx_ipg = 100;
942+ phy->test.bf_en = 1;
943+
944+ return mt7915_tm_set_trx(phy, TM_MAC_TX, true);
945+}
946+
947+static int
948+mt7915_tm_txbf_phase_comp(struct mt7915_phy *phy, u16 *val)
949+{
950+ struct mt7915_dev *dev = phy->dev;
951+ struct {
952+ u8 category;
953+ u8 wlan_idx_lo;
954+ u8 bw;
955+ u8 jp_band;
956+ u8 dbdc_idx;
957+ bool read_from_e2p;
958+ bool disable;
959+ u8 wlan_idx_hi;
960+ u8 buf[40];
961+ } __packed req = {
962+ .category = MT_BF_IBF_PHASE_COMP,
963+ .bw = val[0],
964+ .jp_band = (val[2] == 1) ? 1 : 0,
965+ .dbdc_idx = phy->band_idx,
966+ .read_from_e2p = val[3],
967+ .disable = val[4],
968+ };
969+ struct mt7915_tm_txbf_phase *phase =
970+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
971+
972+ wait_event_timeout(dev->mt76.tx_wait, phase[val[2]].status != 0, HZ);
973+ memcpy(req.buf, &phase[val[2]].phase, sizeof(req.buf));
974+
975+ pr_info("ibf cal process: phase comp info\n");
976+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
977+ &req, sizeof(req), 0);
978+
979+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
980+ sizeof(req), true);
981+}
982+
983+static int
984+mt7915_tm_txbf_profile_tag_read(struct mt7915_phy *phy, u8 pfmu_idx)
985+{
986+ struct mt7915_dev *dev = phy->dev;
987+ struct {
988+ u8 format_id;
989+ u8 pfmu_idx;
990+ bool bfer;
991+ u8 dbdc_idx;
992+ } __packed req = {
993+ .format_id = MT_BF_PFMU_TAG_READ,
994+ .pfmu_idx = pfmu_idx,
995+ .bfer = 1,
996+ .dbdc_idx = phy != &dev->phy,
997+ };
998+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
999+
1000+ tag->t1.pfmu_idx = 0;
1001+
1002+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1003+ sizeof(req), true);
1004+}
1005+
1006+static int
1007+mt7915_tm_txbf_profile_tag_write(struct mt7915_phy *phy, u8 pfmu_idx,
1008+ struct mt7915_tm_pfmu_tag *tag)
1009+{
1010+ struct mt7915_dev *dev = phy->dev;
1011+ struct {
1012+ u8 format_id;
1013+ u8 pfmu_idx;
1014+ bool bfer;
1015+ u8 dbdc_idx;
1016+ u8 buf[64];
1017+ } __packed req = {
1018+ .format_id = MT_BF_PFMU_TAG_WRITE,
1019+ .pfmu_idx = pfmu_idx,
1020+ .bfer = 1,
1021+ .dbdc_idx = phy != &dev->phy,
1022+ };
1023+
1024+ memcpy(req.buf, tag, sizeof(*tag));
1025+ wait_event_timeout(dev->mt76.tx_wait, tag->t1.pfmu_idx != 0, HZ);
1026+
1027+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1028+ sizeof(req), false);
1029+}
1030+
1031+static int
1032+mt7915_tm_txbf_apply_tx(struct mt7915_phy *phy, u16 wlan_idx, bool ebf,
1033+ bool ibf, bool phase_cal)
1034+{
1035+#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
1036+#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
1037+ struct mt7915_dev *dev = phy->dev;
1038+ struct {
1039+ u8 category;
1040+ u8 wlan_idx_lo;
1041+ bool ebf;
1042+ bool ibf;
1043+ bool mu_txbf;
1044+ bool phase_cal;
1045+ u8 wlan_idx_hi;
1046+ u8 _rsv;
1047+ } __packed req = {
1048+ .category = MT_BF_DATA_PACKET_APPLY,
1049+ .wlan_idx_lo = to_wcid_lo(wlan_idx),
1050+ .ebf = ebf,
1051+ .ibf = ibf,
1052+ .phase_cal = phase_cal,
1053+ .wlan_idx_hi = to_wcid_hi(wlan_idx),
1054+ };
1055+
1056+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1057+ sizeof(req), false);
1058+}
1059+
1060+static int mt7915_tm_txbf_set_rate(struct mt7915_phy *phy,
1061+ struct mt76_wcid *wcid)
1062+{
1063+ struct mt7915_dev *dev = phy->dev;
1064+ struct mt76_testmode_entry_data *ed = mt76_testmode_entry_data(phy->mt76, wcid);
1065+ struct ieee80211_sta *sta = wcid_to_sta(wcid);
1066+ struct sta_phy rate = {};
1067+
1068+ if (!sta)
1069+ return 0;
1070+
1071+ rate.type = MT_PHY_TYPE_HT;
1072+ rate.bw = mt7915_tm_chan_bw(phy->mt76->chandef.width);
1073+ rate.nss = ed->tx_rate_nss;
1074+ rate.mcs = ed->tx_rate_idx;
1075+ rate.ldpc = (rate.bw || ed->tx_rate_ldpc) * GENMASK(2, 0);
1076+
1077+ return mt7915_mcu_set_fixed_rate_ctrl(dev, phy->monitor_vif, sta,
1078+ &rate, RATE_PARAM_FIXED);
1079+}
1080+
1081+static int
1082+mt7915_tm_txbf_set_tx(struct mt7915_phy *phy, u16 *val)
1083+{
1084+ bool bf_on = val[0], update = val[3];
1085+ /* u16 wlan_idx = val[2]; */
1086+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
1087+ struct mt76_testmode_data *td = &phy->mt76->test;
1088+ struct mt76_wcid *wcid;
1089+
1090+ if (bf_on) {
1091+ mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1092+ mt7915_tm_txbf_profile_tag_read(phy, 2);
1093+ tag->t1.invalid_prof = false;
1094+ mt7915_tm_txbf_profile_tag_write(phy, 2, tag);
1095+
1096+ phy->test.bf_ever_en = true;
1097+
1098+ if (update)
1099+ mt7915_tm_txbf_apply_tx(phy, 1, 0, 1, 1);
1100+ } else {
1101+ if (!phy->test.bf_ever_en) {
1102+ if (update)
1103+ mt7915_tm_txbf_apply_tx(phy, 1, 0, 0, 0);
1104+ } else {
1105+ phy->test.bf_ever_en = false;
1106+
1107+ mt7915_tm_txbf_profile_tag_read(phy, 2);
1108+ tag->t1.invalid_prof = true;
1109+ mt7915_tm_txbf_profile_tag_write(phy, 2, tag);
1110+ }
1111+ }
1112+
1113+ wcid = list_first_entry(&td->tm_entry_list, struct mt76_wcid, list);
1114+ mt7915_tm_txbf_set_rate(phy, wcid);
1115+
1116+ return 0;
1117+}
1118+
1119+static int
1120+mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
1121+{
1122+ static const u8 mode_to_lm[] = {
1123+ [MT76_TM_TX_MODE_CCK] = 0,
1124+ [MT76_TM_TX_MODE_OFDM] = 0,
1125+ [MT76_TM_TX_MODE_HT] = 1,
1126+ [MT76_TM_TX_MODE_VHT] = 2,
1127+ [MT76_TM_TX_MODE_HE_SU] = 3,
1128+ [MT76_TM_TX_MODE_HE_EXT_SU] = 3,
1129+ [MT76_TM_TX_MODE_HE_TB] = 3,
1130+ [MT76_TM_TX_MODE_HE_MU] = 3,
1131+ };
1132+ struct mt76_testmode_data *td = &phy->mt76->test;
1133+ struct mt76_wcid *wcid;
1134+ struct ieee80211_vif *vif = phy->monitor_vif;
1135+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
1136+ u8 pfmu_idx = val[0], nc = val[2], nr;
1137+ int ret;
1138+
1139+ if (td->tx_antenna_mask == 3)
1140+ nr = 1;
1141+ else if (td->tx_antenna_mask == 7)
1142+ nr = 2;
1143+ else
1144+ nr = 3;
1145+
1146+ memset(tag, 0, sizeof(*tag));
1147+ tag->t1.pfmu_idx = pfmu_idx;
1148+ tag->t1.ebf = ebf;
1149+ tag->t1.nr = nr;
1150+ tag->t1.nc = nc;
1151+ tag->t1.invalid_prof = true;
1152+
1153+ tag->t1.snr_sts4 = 0xc0;
1154+ tag->t1.snr_sts5 = 0xff;
1155+ tag->t1.snr_sts6 = 0xff;
1156+ tag->t1.snr_sts7 = 0xff;
1157+
1158+ if (ebf) {
1159+ tag->t1.row_id1 = 0;
1160+ tag->t1.row_id2 = 1;
1161+ tag->t1.row_id3 = 2;
1162+ tag->t1.row_id4 = 3;
1163+ tag->t1.lm = mode_to_lm[MT76_TM_TX_MODE_HT];
1164+ } else {
1165+ tag->t1.row_id1 = 4;
1166+ tag->t1.row_id2 = 5;
1167+ tag->t1.row_id3 = 6;
1168+ tag->t1.row_id4 = 7;
1169+ tag->t1.lm = mode_to_lm[MT76_TM_TX_MODE_OFDM];
1170+
1171+ tag->t2.ibf_timeout = 0xff;
1172+ tag->t2.ibf_nr = nr;
1173+ }
1174+
1175+ ret = mt7915_tm_txbf_profile_tag_write(phy, pfmu_idx, tag);
1176+ if (ret)
1177+ return ret;
1178+
1179+ wcid = list_first_entry(&td->tm_entry_list, struct mt76_wcid, list);
1180+ ret = mt7915_tm_add_txbf(phy, vif, wcid_to_sta(wcid), pfmu_idx, nr, nc, ebf);
1181+ if (ret)
1182+ return ret;
1183+
1184+ if (!ebf)
1185+ return mt7915_tm_txbf_apply_tx(phy, 1, false, true, true);
1186+
1187+ return 0;
1188+}
1189+
1190+static int
1191+mt7915_tm_txbf_phase_cal(struct mt7915_phy *phy, u16 *val)
1192+{
1193+#define GROUP_L 0
1194+#define GROUP_M 1
1195+#define GROUP_H 2
1196+ struct mt7915_dev *dev = phy->dev;
1197+ struct {
1198+ u8 category;
1199+ u8 group_l_m_n;
1200+ u8 group;
1201+ bool sx2;
1202+ u8 cal_type;
1203+ u8 lna_gain_level;
1204+ u8 _rsv[2];
1205+ } __packed req = {
1206+ .category = MT_BF_PHASE_CAL,
1207+ .group = val[0],
1208+ .group_l_m_n = val[1],
1209+ .sx2 = val[2],
1210+ .cal_type = val[3],
1211+ .lna_gain_level = 0, /* for test purpose */
1212+ };
1213+ struct mt7915_tm_txbf_phase *phase =
1214+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1215+
1216+ phase[req.group].status = 0;
1217+
1218+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1219+ sizeof(req), true);
1220+}
1221+
1222+int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb)
1223+{
1224+#define BF_PFMU_TAG 16
1225+#define BF_CAL_PHASE 21
1226+ u8 format_id;
1227+
1228+ skb_pull(skb, sizeof(struct mt7915_mcu_rxd));
1229+ format_id = *(u8 *)skb->data;
1230+
1231+ if (format_id == BF_PFMU_TAG) {
1232+ struct mt7915_tm_pfmu_tag *tag = dev->test.txbf_pfmu_tag;
1233+
1234+ skb_pull(skb, 8);
1235+ memcpy(tag, skb->data, sizeof(struct mt7915_tm_pfmu_tag));
1236+ } else if (format_id == BF_CAL_PHASE) {
1237+ struct mt7915_tm_ibf_cal_info *cal;
1238+ struct mt7915_tm_txbf_phase *phase =
1239+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1240+
1241+ cal = (struct mt7915_tm_ibf_cal_info *)skb->data;
1242+ switch (cal->cal_type) {
1243+ case IBF_PHASE_CAL_NORMAL:
1244+ case IBF_PHASE_CAL_NORMAL_INSTRUMENT:
1245+ if (cal->group_l_m_n != GROUP_M)
1246+ break;
1247+ phase = &phase[cal->group];
1248+ memcpy(&phase->phase, cal->buf + 16, sizeof(phase->phase));
1249+ phase->status = cal->status;
1250+ break;
1251+ case IBF_PHASE_CAL_VERIFY:
1252+ case IBF_PHASE_CAL_VERIFY_INSTRUMENT:
1253+ break;
1254+ default:
1255+ break;
1256+ }
1257+ }
1258+
1259+ wake_up(&dev->mt76.tx_wait);
1260+
1261+ return 0;
1262+}
1263+
1264+static int
1265+mt7915_tm_txbf_profile_update_all(struct mt7915_phy *phy, u16 *val)
1266+{
1267+ struct mt76_testmode_data *td = &phy->mt76->test;
1268+ u16 pfmu_idx = val[0];
1269+ u16 subc_id = val[1];
1270+ u16 angle11 = val[2];
1271+ u16 angle21 = val[3];
1272+ u16 angle31 = val[4];
1273+ u16 angle41 = val[5];
1274+ s16 phi11 = 0, phi21 = 0, phi31 = 0;
1275+ struct mt7915_tm_pfmu_data *pfmu_data;
1276+
1277+ if (subc_id > 63)
1278+ return -EINVAL;
1279+
1280+ if (td->tx_antenna_mask == 2) {
1281+ phi11 = (s16)(angle21 - angle11);
1282+ } else if (td->tx_antenna_mask == 3) {
1283+ phi11 = (s16)(angle31 - angle11);
1284+ phi21 = (s16)(angle31 - angle21);
1285+ } else {
1286+ phi11 = (s16)(angle41 - angle11);
1287+ phi21 = (s16)(angle41 - angle21);
1288+ phi31 = (s16)(angle41 - angle31);
1289+ }
1290+
1291+ pfmu_data = (struct mt7915_tm_pfmu_data *)phy->dev->test.txbf_pfmu_data;
1292+ pfmu_data = &pfmu_data[subc_id];
1293+
1294+ if (subc_id < 32)
1295+ pfmu_data->subc_idx = cpu_to_le16(subc_id + 224);
1296+ else
1297+ pfmu_data->subc_idx = cpu_to_le16(subc_id - 32);
1298+ pfmu_data->phi11 = cpu_to_le16(phi11);
1299+ pfmu_data->phi21 = cpu_to_le16(phi21);
1300+ pfmu_data->phi31 = cpu_to_le16(phi31);
1301+
1302+ if (subc_id == 63) {
1303+ struct mt7915_dev *dev = phy->dev;
1304+ struct {
1305+ u8 format_id;
1306+ u8 pfmu_idx;
1307+ u8 dbdc_idx;
1308+ u8 _rsv;
1309+ u8 buf[512];
1310+ } __packed req = {
1311+ .format_id = MT_BF_PROFILE_WRITE_ALL,
1312+ .pfmu_idx = pfmu_idx,
1313+ .dbdc_idx = phy != &dev->phy,
1314+ };
1315+
1316+ memcpy(req.buf, dev->test.txbf_pfmu_data, 512);
1317+
1318+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION),
1319+ &req, sizeof(req), true);
1320+ }
1321+
1322+ return 0;
1323+}
1324+
1325+static int
1326+mt7915_tm_txbf_e2p_update(struct mt7915_phy *phy)
1327+{
1328+ struct mt7915_tm_txbf_phase *phase, *p;
1329+ struct mt7915_dev *dev = phy->dev;
1330+ u8 *eeprom = dev->mt76.eeprom.data;
1331+ u16 offset;
1332+ bool is_7976;
1333+ int i;
1334+
1335+ is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
1336+ offset = is_7976 ? 0x60a : 0x651;
1337+
1338+ phase = (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1339+ for (i = 0; i < MAX_PHASE_GROUP_NUM; i++) {
1340+ p = &phase[i];
1341+
1342+ if (!p->status)
1343+ continue;
1344+
1345+ /* copy phase cal data to eeprom */
1346+ memcpy(eeprom + offset + i * sizeof(p->phase), &p->phase,
1347+ sizeof(p->phase));
1348+ }
1349+
1350+ return 0;
1351+}
1352+
1353+static int
1354+mt7915_tm_set_txbf(struct mt7915_phy *phy)
1355+{
1356+ struct mt76_testmode_data *td = &phy->mt76->test;
1357+ u16 *val = td->txbf_param;
1358+
1359+ pr_info("ibf cal process: act = %u, val = %u, %u, %u, %u, %u\n",
1360+ td->txbf_act, val[0], val[1], val[2], val[3], val[4]);
1361+
1362+ switch (td->txbf_act) {
1363+ case MT76_TM_TXBF_ACT_INIT:
1364+ return mt7915_tm_txbf_init(phy, val);
1365+ case MT76_TM_TXBF_ACT_UPDATE_CH:
1366+ mt7915_tm_update_channel(phy);
1367+ break;
1368+ case MT76_TM_TXBF_ACT_PHASE_COMP:
1369+ return mt7915_tm_txbf_phase_comp(phy, val);
1370+ case MT76_TM_TXBF_ACT_TX_PREP:
1371+ return mt7915_tm_txbf_set_tx(phy, val);
1372+ case MT76_TM_TXBF_ACT_IBF_PROF_UPDATE:
1373+ return mt7915_tm_txbf_profile_update(phy, val, false);
1374+ case MT76_TM_TXBF_ACT_EBF_PROF_UPDATE:
1375+ return mt7915_tm_txbf_profile_update(phy, val, true);
1376+ case MT76_TM_TXBF_ACT_PHASE_CAL:
1377+ return mt7915_tm_txbf_phase_cal(phy, val);
1378+ case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL:
1379+ return mt7915_tm_txbf_profile_update_all(phy, val);
1380+ case MT76_TM_TXBF_ACT_E2P_UPDATE:
1381+ return mt7915_tm_txbf_e2p_update(phy);
1382+ default:
1383+ break;
1384+ };
1385+
1386+ return 0;
1387+}
1388+
1389 static int
1390 mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
1391- u16 cw_max, u16 txop)
1392+ u16 cw_max, u16 txop, u8 tx_cmd)
1393 {
1394- struct mt7915_mcu_tx req = { .total = 1 };
1395+ struct mt7915_mcu_tx req = {
1396+ .valid = true,
1397+ .mode = tx_cmd,
1398+ .total = 1,
1399+ };
1400 struct edca *e = &req.edca[0];
1401
1402 e->queue = qid;
developerc6f56bb2022-06-14 18:36:30 +08001403@@ -261,7 +1035,8 @@ done:
developer4c6b6002022-05-30 16:36:44 +08001404
1405 return mt7915_tm_set_wmm_qid(dev,
1406 mt76_connac_lmac_mapping(IEEE80211_AC_BE),
1407- aifsn, cw, cw, 0);
1408+ aifsn, cw, cw, 0,
1409+ mode == MT76_TM_TX_MODE_HE_MU);
1410 }
1411
1412 static int
developerc6f56bb2022-06-14 18:36:30 +08001413@@ -337,7 +1112,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
developer4c6b6002022-05-30 16:36:44 +08001414 bitrate = cfg80211_calculate_bitrate(&rate);
1415 tx_len = bitrate * tx_time / 10 / 8;
1416
1417- ret = mt76_testmode_alloc_skb(phy->mt76, tx_len);
1418+ ret = mt76_testmode_init_skb(phy->mt76, tx_len, &td->tx_skb, td->addr);
1419 if (ret)
1420 return ret;
1421
developerc6f56bb2022-06-14 18:36:30 +08001422@@ -455,18 +1230,180 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001423
1424 phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
1425
1426- if (!en)
1427+ if (!en) {
1428 mt7915_tm_set_tam_arb(phy, en, 0);
1429+
1430+ phy->mt76->test.aid = 0;
1431+ phy->mt76->test.tx_mpdu_len = 0;
1432+ phy->test.bf_en = 0;
1433+ mt7915_tm_set_entry(phy);
1434+ }
1435+}
1436+
1437+static bool
1438+mt7915_tm_check_skb(struct mt7915_phy *phy)
1439+{
1440+ struct mt76_testmode_entry_data *ed;
1441+ struct mt76_wcid *wcid;
1442+
1443+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
1444+ struct ieee80211_tx_info *info;
1445+
1446+ if (!ed->tx_skb)
1447+ return false;
1448+
1449+ info = IEEE80211_SKB_CB(ed->tx_skb);
1450+ info->control.vif = phy->monitor_vif;
1451+ }
1452+
1453+ return true;
1454+}
1455+
1456+static int
1457+mt7915_tm_set_ba(struct mt7915_phy *phy)
1458+{
1459+ struct mt7915_dev *dev = phy->dev;
1460+ struct mt76_testmode_data *td = &phy->mt76->test;
1461+ struct mt76_wcid *wcid;
1462+ struct ieee80211_vif *vif = phy->monitor_vif;
1463+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1464+ struct ieee80211_ampdu_params params = { .buf_size = 256 };
1465+
1466+ list_for_each_entry(wcid, &td->tm_entry_list, list) {
1467+ int tid, ret;
1468+
1469+ params.sta = wcid_to_sta(wcid);
1470+ for (tid = 0; tid < 8; tid++) {
1471+ params.tid = tid;
1472+ ret = mt7915_mcu_add_tx_ba(phy->dev, &params, true);
1473+ if (ret)
1474+ return ret;
1475+ }
1476+ }
1477+
1478+ mt76_wr(dev, MT_AGG_AALCR0(mvif->mt76.band_idx, mvif->mt76.wmm_idx),
1479+ 0x01010101);
1480+
1481+ return 0;
1482+}
1483+
1484+static int
1485+mt7915_tm_set_muru_cfg(struct mt7915_phy *phy, struct mt7915_tm_muru *muru)
1486+{
1487+/* #define MURU_SET_MANUAL_CFG 100 */
1488+ struct mt7915_dev *dev = phy->dev;
1489+ struct {
1490+ __le32 cmd;
1491+ struct mt7915_tm_muru muru;
1492+ } __packed req = {
1493+ .cmd = cpu_to_le32(MURU_SET_MANUAL_CFG),
1494+ };
1495+
1496+ memcpy(&req.muru, muru, sizeof(struct mt7915_tm_muru));
1497+
1498+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1499+ sizeof(req), false);
1500+}
1501+
1502+static int
1503+mt7915_tm_set_muru_dl(struct mt7915_phy *phy)
1504+{
1505+ struct mt76_testmode_data *td = &phy->mt76->test;
1506+ struct mt76_testmode_entry_data *ed;
1507+ struct mt76_wcid *wcid;
1508+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
1509+ struct ieee80211_vif *vif = phy->monitor_vif;
1510+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1511+ struct mt7915_tm_muru muru = {};
1512+ struct mt7915_tm_muru_comm *comm = &muru.comm;
1513+ struct mt7915_tm_muru_dl *dl = &muru.dl;
1514+ int i;
1515+
1516+ comm->ppdu_format = MURU_PPDU_HE_MU;
1517+ comm->band = mvif->mt76.band_idx;
1518+ comm->wmm_idx = mvif->mt76.wmm_idx;
1519+ comm->spe_idx = phy->test.spe_idx;
1520+
1521+ dl->bw = mt7915_tm_chan_bw(chandef->width);
1522+ dl->gi = td->tx_rate_sgi;;
1523+ dl->ltf = td->tx_ltf;
1524+ dl->tx_mode = MT_PHY_TYPE_HE_MU;
1525+
1526+ for (i = 0; i < sizeof(dl->ru); i++)
1527+ dl->ru[i] = 0x71;
1528+
1529+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
1530+ struct mt7915_tm_muru_dl_usr *dl_usr = &dl->usr[dl->user_num];
1531+
1532+ dl_usr->wlan_idx = cpu_to_le16(wcid->idx);
1533+ dl_usr->ru_alloc_seg = ed->aid < 8 ? 0 : 1;
1534+ dl_usr->ru_idx = ed->ru_idx;
1535+ dl_usr->mcs = ed->tx_rate_idx;
1536+ dl_usr->nss = ed->tx_rate_nss - 1;
1537+ dl_usr->ldpc = ed->tx_rate_ldpc;
1538+ dl->ru[dl->user_num] = ed->ru_alloc;
1539+
1540+ dl->user_num++;
1541+ }
1542+
1543+ muru.cfg_comm = cpu_to_le32(MURU_COMM_SET);
1544+ muru.cfg_dl = cpu_to_le32(MURU_DL_SET);
1545+
1546+ return mt7915_tm_set_muru_cfg(phy, &muru);
1547+}
1548+
1549+static int
1550+mt7915_tm_set_muru_pkt_cnt(struct mt7915_phy *phy, bool enable, u32 tx_count)
1551+{
1552+#define MURU_SET_TX_PKT_CNT 105
1553+#define MURU_SET_TX_EN 106
1554+ struct mt7915_dev *dev = phy->dev;
1555+ struct {
1556+ __le32 cmd;
1557+ u8 band;
1558+ u8 enable;
1559+ u8 _rsv[2];
1560+ __le32 tx_count;
1561+ } __packed req = {
1562+ .band = phy != &dev->phy,
1563+ .enable = enable,
1564+ .tx_count = enable ? cpu_to_le32(tx_count) : 0,
1565+ };
1566+ int ret;
1567+
1568+ req.cmd = enable ? cpu_to_le32(MURU_SET_TX_PKT_CNT) :
1569+ cpu_to_le32(MURU_SET_TX_EN);
1570+
1571+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1572+ sizeof(req), false);
1573+ if (ret)
1574+ return ret;
1575+
1576+ req.cmd = enable ? cpu_to_le32(MURU_SET_TX_EN) :
1577+ cpu_to_le32(MURU_SET_TX_PKT_CNT);
1578+
1579+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1580+ sizeof(req), false);
1581 }
1582
1583 static void
1584-mt7915_tm_update_channel(struct mt7915_phy *phy)
1585+mt7915_tm_tx_frames_mu(struct mt7915_phy *phy, bool enable)
1586 {
1587- mutex_unlock(&phy->dev->mt76.mutex);
1588- mt7915_set_channel(phy);
1589- mutex_lock(&phy->dev->mt76.mutex);
1590+ struct mt76_testmode_data *td = &phy->mt76->test;
1591
1592- mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
1593+ if (enable) {
1594+ struct mt7915_dev *dev = phy->dev;
1595+
1596+ mt7915_tm_set_ba(phy);
1597+ mt7915_tm_set_muru_dl(phy);
1598+ mt76_rr(dev, MT_MIB_DR8(phy != &dev->phy));
1599+ } else {
1600+ /* set to zero for counting real tx free num */
1601+ td->tx_done = 0;
1602+ }
1603+
1604+ mt7915_tm_set_muru_pkt_cnt(phy, enable, td->tx_count);
1605+ usleep_range(100000, 200000);
1606 }
1607
1608 static void
developerc6f56bb2022-06-14 18:36:30 +08001609@@ -475,47 +1412,48 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001610 static const u8 spe_idx_map[] = {0, 0, 1, 0, 3, 2, 4, 0,
1611 9, 8, 6, 10, 16, 12, 18, 0};
1612 struct mt76_testmode_data *td = &phy->mt76->test;
1613- struct mt7915_dev *dev = phy->dev;
1614- struct ieee80211_tx_info *info;
1615- u8 duty_cycle = td->tx_duty_cycle;
1616- u32 tx_time = td->tx_time;
1617- u32 ipg = td->tx_ipg;
1618
1619 mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1620- mt7915_tm_clean_hwq(phy, dev->mt76.global_wcid.idx);
1621+ mt7915_tm_set_trx(phy, TM_MAC_TX, false);
1622
1623 if (en) {
1624- mt7915_tm_update_channel(phy);
1625+ u32 tx_time = td->tx_time, ipg = td->tx_ipg;
1626+ u8 duty_cycle = td->tx_duty_cycle;
1627+
1628+ if (!phy->test.bf_en)
1629+ mt7915_tm_update_channel(phy);
1630
1631 if (td->tx_spe_idx) {
1632 phy->test.spe_idx = td->tx_spe_idx;
1633 } else {
1634 phy->test.spe_idx = spe_idx_map[td->tx_antenna_mask];
1635 }
1636- }
1637
1638- mt7915_tm_set_tam_arb(phy, en,
1639- td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU);
1640+ /* if all three params are set, duty_cycle will be ignored */
1641+ if (duty_cycle && tx_time && !ipg) {
1642+ ipg = tx_time * 100 / duty_cycle - tx_time;
1643+ } else if (duty_cycle && !tx_time && ipg) {
1644+ if (duty_cycle < 100)
1645+ tx_time = duty_cycle * ipg / (100 - duty_cycle);
1646+ }
1647
1648- /* if all three params are set, duty_cycle will be ignored */
1649- if (duty_cycle && tx_time && !ipg) {
1650- ipg = tx_time * 100 / duty_cycle - tx_time;
1651- } else if (duty_cycle && !tx_time && ipg) {
1652- if (duty_cycle < 100)
1653- tx_time = duty_cycle * ipg / (100 - duty_cycle);
1654- }
1655+ mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
1656+ mt7915_tm_set_tx_len(phy, tx_time);
1657
1658- mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
1659- mt7915_tm_set_tx_len(phy, tx_time);
1660+ if (ipg)
1661+ td->tx_queued_limit = MT76_TM_TIMEOUT * 1000000 / ipg / 2;
1662
1663- if (ipg)
1664- td->tx_queued_limit = MT76_TM_TIMEOUT * 1000000 / ipg / 2;
1665+ if (!mt7915_tm_check_skb(phy))
1666+ return;
1667+ } else {
1668+ mt7915_tm_clean_hwq(phy);
1669+ }
1670
1671- if (!en || !td->tx_skb)
1672- return;
1673+ mt7915_tm_set_tam_arb(phy, en,
1674+ td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU);
1675
1676- info = IEEE80211_SKB_CB(td->tx_skb);
1677- info->control.vif = phy->monitor_vif;
1678+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1679+ mt7915_tm_tx_frames_mu(phy, en);
1680
1681 mt7915_tm_set_trx(phy, TM_MAC_TX, en);
1682 }
developerc6f56bb2022-06-14 18:36:30 +08001683@@ -544,10 +1482,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
developer4c6b6002022-05-30 16:36:44 +08001684 return ret;
1685
1686 rs_band = (struct mt7915_tm_rx_stat_band *)skb->data;
1687- /* pr_info("mdrdy_cnt = %d\n", le32_to_cpu(rs_band->mdrdy_cnt)); */
1688- /* pr_info("fcs_err = %d\n", le16_to_cpu(rs_band->fcs_err)); */
1689- /* pr_info("len_mismatch = %d\n", le16_to_cpu(rs_band->len_mismatch)); */
1690- /* pr_info("fcs_ok = %d\n", le16_to_cpu(rs_band->fcs_succ)); */
1691
1692 if (!clear) {
1693 enum mt76_rxq_id q = req.band ? MT_RXQ_EXT : MT_RXQ_MAIN;
developerc6f56bb2022-06-14 18:36:30 +08001694@@ -562,13 +1496,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
developer4c6b6002022-05-30 16:36:44 +08001695 return 0;
1696 }
1697
1698+static int
1699+mt7915_tm_set_rx_user_idx(struct mt7915_phy *phy, u8 aid)
1700+{
1701+ struct mt7915_dev *dev = phy->dev;
1702+ struct mt76_wcid *wcid = NULL;
1703+ struct mt76_testmode_entry_data *ed;
1704+ struct {
1705+ u8 band;
1706+ u8 _rsv;
1707+ __le16 wlan_idx;
1708+ } __packed req = {
1709+ .band = phy->band_idx,
1710+ };
1711+
1712+ mt76_tm_for_each_entry(phy->mt76, wcid, ed)
1713+ if (ed->aid == aid)
1714+ break;
1715+
1716+ if (!wcid)
1717+ return -EINVAL;
1718+
1719+ req.wlan_idx = cpu_to_le16(wcid->idx);
1720+
1721+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_STAT_USER_CTRL),
1722+ &req, sizeof(req), false);
1723+}
1724+
1725+static int
1726+mt7915_tm_set_muru_aid(struct mt7915_phy *phy, u16 aid)
1727+{
1728+ struct mt7915_dev *dev = phy->dev;
1729+ struct mt7915_tm_cmd req = {
1730+ .testmode_en = 1,
1731+ .param_idx = MCU_ATE_SET_MU_RX_AID,
1732+ .param.rx_aid.band = cpu_to_le32(phy->band_idx),
1733+ .param.rx_aid.aid = cpu_to_le16(aid),
1734+ };
1735+
1736+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
1737+ sizeof(req), false);
1738+}
1739+
1740 static void
1741 mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
1742 {
1743+ struct mt76_testmode_data *td = &phy->mt76->test;
1744+
1745+ mt7915_tm_set_trx(phy, TM_MAC_TX, false);
1746 mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1747
1748 if (en) {
1749- mt7915_tm_update_channel(phy);
1750+ if (!phy->test.bf_en)
1751+ mt7915_tm_update_channel(phy);
1752+ if (td->aid)
1753+ mt7915_tm_set_rx_user_idx(phy, td->aid);
1754
1755 /* read-clear */
1756 mt7915_tm_get_rx_stats(phy, true);
developerc6f56bb2022-06-14 18:36:30 +08001757@@ -576,9 +1558,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001758 /* clear fw count */
1759 mt7915_tm_set_phy_count(phy, 0);
1760 mt7915_tm_set_phy_count(phy, 1);
1761-
1762- mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
1763 }
1764+
1765+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1766+ mt7915_tm_set_muru_aid(phy, en ? td->aid : 0xf800);
1767+
1768+ mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
1769 }
1770
1771 static int
developerc6f56bb2022-06-14 18:36:30 +08001772@@ -615,35 +1600,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001773 tx_cont->center_ch = freq1;
1774 tx_cont->tx_ant = td->tx_antenna_mask;
1775 tx_cont->band = phy != &dev->phy;
1776-
1777- switch (chandef->width) {
1778- case NL80211_CHAN_WIDTH_40:
1779- tx_cont->bw = CMD_CBW_40MHZ;
1780- break;
1781- case NL80211_CHAN_WIDTH_80:
1782- tx_cont->bw = CMD_CBW_80MHZ;
1783- break;
1784- case NL80211_CHAN_WIDTH_80P80:
1785- tx_cont->bw = CMD_CBW_8080MHZ;
1786- break;
1787- case NL80211_CHAN_WIDTH_160:
1788- tx_cont->bw = CMD_CBW_160MHZ;
1789- break;
1790- case NL80211_CHAN_WIDTH_5:
1791- tx_cont->bw = CMD_CBW_5MHZ;
1792- break;
1793- case NL80211_CHAN_WIDTH_10:
1794- tx_cont->bw = CMD_CBW_10MHZ;
1795- break;
1796- case NL80211_CHAN_WIDTH_20:
1797- tx_cont->bw = CMD_CBW_20MHZ;
1798- break;
1799- case NL80211_CHAN_WIDTH_20_NOHT:
1800- tx_cont->bw = CMD_CBW_20MHZ;
1801- break;
1802- default:
1803- return -EINVAL;
1804- }
1805+ tx_cont->bw = mt7915_tm_chan_bw(chandef->width);
1806
1807 if (!en) {
1808 req.op.rf.param.func_data = cpu_to_le32(phy != &dev->phy);
developerc6f56bb2022-06-14 18:36:30 +08001809@@ -727,6 +1684,12 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
developer4c6b6002022-05-30 16:36:44 +08001810 mt7915_tm_set_freq_offset(phy, en, en ? td->freq_offset : 0);
1811 if (changed & BIT(TM_CHANGED_TXPOWER))
1812 mt7915_tm_set_tx_power(phy);
1813+ if (changed & BIT(TM_CHANGED_AID))
1814+ mt7915_tm_set_entry(phy);
1815+ if (changed & BIT(TM_CHANGED_CFG))
1816+ mt7915_tm_set_cfg(phy);
1817+ if (changed & BIT(TM_CHANGED_TXBF_ACT))
1818+ mt7915_tm_set_txbf(phy);
1819 }
1820
1821 static int
developerc6f56bb2022-06-14 18:36:30 +08001822@@ -800,6 +1763,7 @@ static int
developer4c6b6002022-05-30 16:36:44 +08001823 mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
1824 {
1825 struct mt7915_phy *phy = mphy->priv;
1826+ struct mt7915_dev *dev = phy->dev;
1827 void *rx, *rssi;
1828 int i;
1829
developerc6f56bb2022-06-14 18:36:30 +08001830@@ -845,11 +1809,68 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
developer4c6b6002022-05-30 16:36:44 +08001831
1832 nla_nest_end(msg, rx);
1833
1834+ if (mphy->test.tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1835+ mphy->test.tx_done += mt76_rr(dev, MT_MIB_DR8(phy != &dev->phy));
1836+
1837 return mt7915_tm_get_rx_stats(phy, false);
1838 }
1839
1840+static int
1841+mt7915_tm_write_back_to_efuse(struct mt7915_dev *dev)
1842+{
1843+ struct mt7915_mcu_eeprom_info req = {};
1844+ u8 *eeprom = dev->mt76.eeprom.data;
1845+ int i, ret = -EINVAL;
1846+
1847+ /* prevent from damaging chip id in efuse */
1848+ if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
1849+ goto out;
1850+
1851+ for (i = 0; i < mt7915_eeprom_size(dev); i += MT76_TM_EEPROM_BLOCK_SIZE) {
1852+ req.addr = cpu_to_le32(i);
1853+ memcpy(&req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
1854+
1855+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_ACCESS),
1856+ &req, sizeof(req), true);
1857+ if (ret)
1858+ return ret;
1859+ }
1860+
1861+out:
1862+ return ret;
1863+}
1864+
1865+static int
1866+mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
1867+{
1868+ struct mt7915_phy *phy = mphy->priv;
1869+ struct mt7915_dev *dev = phy->dev;
1870+ u8 *eeprom = dev->mt76.eeprom.data;
1871+ int ret = 0;
1872+
1873+ if (offset >= mt7915_eeprom_size(dev))
1874+ return -EINVAL;
1875+
1876+ switch (action) {
1877+ case MT76_TM_EEPROM_ACTION_UPDATE_DATA:
1878+ memcpy(eeprom + offset, val, MT76_TM_EEPROM_BLOCK_SIZE);
1879+ break;
1880+ case MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE:
1881+ ret = mt7915_mcu_set_eeprom(dev, true);
1882+ break;
1883+ case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
1884+ ret = mt7915_tm_write_back_to_efuse(dev);
1885+ break;
1886+ default:
1887+ break;
1888+ }
1889+
1890+ return ret;
1891+}
1892+
1893 const struct mt76_testmode_ops mt7915_testmode_ops = {
1894 .set_state = mt7915_tm_set_state,
1895 .set_params = mt7915_tm_set_params,
1896 .dump_stats = mt7915_tm_dump_stats,
1897+ .set_eeprom = mt7915_tm_set_eeprom,
1898 };
1899diff --git a/mt7915/testmode.h b/mt7915/testmode.h
1900index a1c54c89..01b08e9e 100644
1901--- a/mt7915/testmode.h
1902+++ b/mt7915/testmode.h
1903@@ -4,6 +4,8 @@
1904 #ifndef __MT7915_TESTMODE_H
1905 #define __MT7915_TESTMODE_H
1906
1907+#include "mcu.h"
1908+
1909 struct mt7915_tm_trx {
1910 u8 type;
1911 u8 enable;
1912@@ -39,6 +41,11 @@ struct mt7915_tm_cfg {
1913 u8 _rsv[2];
1914 };
1915
1916+struct mt7915_tm_mu_rx_aid {
1917+ __le32 band;
1918+ __le16 aid;
1919+};
1920+
1921 struct mt7915_tm_cmd {
1922 u8 testmode_en;
1923 u8 param_idx;
1924@@ -50,6 +57,7 @@ struct mt7915_tm_cmd {
1925 struct mt7915_tm_slot_time slot;
1926 struct mt7915_tm_clean_txq clean;
1927 struct mt7915_tm_cfg cfg;
1928+ struct mt7915_tm_mu_rx_aid rx_aid;
1929 u8 test[72];
1930 } param;
1931 } __packed;
1932@@ -109,6 +117,16 @@ enum {
1933 TAM_ARB_OP_MODE_FORCE_SU = 5,
1934 };
1935
1936+enum {
1937+ TM_CBW_20MHZ,
1938+ TM_CBW_40MHZ,
1939+ TM_CBW_80MHZ,
1940+ TM_CBW_10MHZ,
1941+ TM_CBW_5MHZ,
1942+ TM_CBW_160MHZ,
1943+ TM_CBW_8080MHZ,
1944+};
1945+
1946 struct mt7915_tm_rx_stat_band {
1947 u8 category;
1948
1949@@ -130,4 +148,264 @@ struct mt7915_tm_rx_stat_band {
1950 __le16 mdrdy_cnt_ofdm;
1951 };
1952
1953+struct mt7915_tm_muru_comm {
1954+ u8 ppdu_format;
1955+ u8 sch_type;
1956+ u8 band;
1957+ u8 wmm_idx;
1958+ u8 spe_idx;
1959+ u8 proc_type;
1960+};
1961+
1962+struct mt7915_tm_muru_dl_usr {
1963+ __le16 wlan_idx;
1964+ u8 ru_alloc_seg;
1965+ u8 ru_idx;
1966+ u8 ldpc;
1967+ u8 nss;
1968+ u8 mcs;
1969+ u8 mu_group_idx;
1970+ u8 vht_groud_id;
1971+ u8 vht_up;
1972+ u8 he_start_stream;
1973+ u8 he_mu_spatial;
1974+ u8 ack_policy;
1975+ __le16 tx_power_alpha;
1976+};
1977+
1978+struct mt7915_tm_muru_dl {
1979+ u8 user_num;
1980+ u8 tx_mode;
1981+ u8 bw;
1982+ u8 gi;
1983+ u8 ltf;
1984+ /* sigB */
1985+ u8 mcs;
1986+ u8 dcm;
1987+ u8 cmprs;
1988+
1989+ u8 tx_power;
1990+ u8 ru[8];
1991+ u8 c26[2];
1992+ u8 ack_policy;
1993+
1994+ struct mt7915_tm_muru_dl_usr usr[16];
1995+};
1996+
1997+struct mt7915_tm_muru_ul_usr {
1998+ __le16 wlan_idx;
1999+ u8 ru_alloc;
2000+ u8 ru_idx;
2001+ u8 ldpc;
2002+ u8 nss;
2003+ u8 mcs;
2004+ u8 target_rssi;
2005+ __le32 trig_pkt_size;
2006+};
2007+
2008+struct mt7915_tm_muru_ul {
2009+ u8 user_num;
2010+
2011+ /* UL TX */
2012+ u8 trig_type;
2013+ __le16 trig_cnt;
2014+ __le16 trig_intv;
2015+ u8 bw;
2016+ u8 gi_ltf;
2017+ __le16 ul_len;
2018+ u8 pad;
2019+ u8 trig_ta[ETH_ALEN];
2020+ u8 ru[8];
2021+ u8 c26[2];
2022+
2023+ struct mt7915_tm_muru_ul_usr usr[16];
2024+ /* HE TB RX Debug */
2025+ __le32 rx_hetb_nonsf_en_bitmap;
2026+ __le32 rx_hetb_cfg[2];
2027+
2028+ /* DL TX */
2029+ u8 ba_type;
2030+};
2031+
2032+struct mt7915_tm_muru {
2033+ __le32 cfg_comm;
2034+ __le32 cfg_dl;
2035+ __le32 cfg_ul;
2036+
2037+ struct mt7915_tm_muru_comm comm;
2038+ struct mt7915_tm_muru_dl dl;
2039+ struct mt7915_tm_muru_ul ul;
2040+};
2041+
2042+#define MURU_PPDU_HE_MU BIT(3)
2043+
2044+/* Common Config */
2045+/* #define MURU_COMM_PPDU_FMT BIT(0) */
2046+/* #define MURU_COMM_SCH_TYPE BIT(1) */
2047+/* #define MURU_COMM_BAND BIT(2) */
2048+/* #define MURU_COMM_WMM BIT(3) */
2049+/* #define MURU_COMM_SPE_IDX BIT(4) */
2050+/* #define MURU_COMM_PROC_TYPE BIT(5) */
2051+/* #define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \ */
2052+/* MURU_COMM_WMM | MURU_COMM_SPE_IDX) */
2053+/* DL Config */
2054+#define MURU_DL_BW BIT(0)
2055+#define MURU_DL_GI BIT(1)
2056+#define MURU_DL_TX_MODE BIT(2)
2057+#define MURU_DL_TONE_PLAN BIT(3)
2058+#define MURU_DL_USER_CNT BIT(4)
2059+#define MURU_DL_LTF BIT(5)
2060+#define MURU_DL_SIGB_MCS BIT(6)
2061+#define MURU_DL_SIGB_DCM BIT(7)
2062+#define MURU_DL_SIGB_CMPRS BIT(8)
2063+#define MURU_DL_ACK_POLICY BIT(9)
2064+#define MURU_DL_TXPOWER BIT(10)
2065+/* DL Per User Config */
2066+#define MURU_DL_USER_WLAN_ID BIT(16)
2067+#define MURU_DL_USER_COD BIT(17)
2068+#define MURU_DL_USER_MCS BIT(18)
2069+#define MURU_DL_USER_NSS BIT(19)
2070+#define MURU_DL_USER_RU_ALLOC BIT(20)
2071+#define MURU_DL_USER_MUMIMO_GRP BIT(21)
2072+#define MURU_DL_USER_MUMIMO_VHT BIT(22)
2073+#define MURU_DL_USER_ACK_POLICY BIT(23)
2074+#define MURU_DL_USER_MUMIMO_HE BIT(24)
2075+#define MURU_DL_USER_PWR_ALPHA BIT(25)
2076+#define MURU_DL_SET (GENMASK(7, 0) | GENMASK(20, 16) | BIT(25))
2077+
2078+#define MAX_PHASE_GROUP_NUM 9
2079+
2080+struct mt7915_tm_txbf_phase {
2081+ u8 status;
2082+ struct {
2083+ u8 r0_uh;
2084+ u8 r0_h;
2085+ u8 r0_m;
2086+ u8 r0_l;
2087+ u8 r0_ul;
2088+ u8 r1_uh;
2089+ u8 r1_h;
2090+ u8 r1_m;
2091+ u8 r1_l;
2092+ u8 r1_ul;
2093+ u8 r2_uh;
2094+ u8 r2_h;
2095+ u8 r2_m;
2096+ u8 r2_l;
2097+ u8 r2_ul;
2098+ u8 r3_uh;
2099+ u8 r3_h;
2100+ u8 r3_m;
2101+ u8 r3_l;
2102+ u8 r3_ul;
2103+ u8 r2_uh_sx2;
2104+ u8 r2_h_sx2;
2105+ u8 r2_m_sx2;
2106+ u8 r2_l_sx2;
2107+ u8 r2_ul_sx2;
2108+ u8 r3_uh_sx2;
2109+ u8 r3_h_sx2;
2110+ u8 r3_m_sx2;
2111+ u8 r3_l_sx2;
2112+ u8 r3_ul_sx2;
2113+ u8 m_t0_h;
2114+ u8 m_t1_h;
2115+ u8 m_t2_h;
2116+ u8 m_t2_h_sx2;
2117+ u8 r0_reserved;
2118+ u8 r1_reserved;
2119+ u8 r2_reserved;
2120+ u8 r3_reserved;
2121+ u8 r2_sx2_reserved;
2122+ u8 r3_sx2_reserved;
2123+ } phase;
2124+};
2125+
2126+struct mt7915_tm_pfmu_tag1 {
2127+ __le32 pfmu_idx:10;
2128+ __le32 ebf:1;
2129+ __le32 data_bw:2;
2130+ __le32 lm:2;
2131+ __le32 is_mu:1;
2132+ __le32 nr:3, nc:3;
2133+ __le32 codebook:2;
2134+ __le32 ngroup:2;
2135+ __le32 _rsv:2;
2136+ __le32 invalid_prof:1;
2137+ __le32 rmsd:3;
2138+
2139+ __le32 col_id1:6, row_id1:10;
2140+ __le32 col_id2:6, row_id2:10;
2141+ __le32 col_id3:6, row_id3:10;
2142+ __le32 col_id4:6, row_id4:10;
2143+
2144+ __le32 ru_start_id:7;
2145+ __le32 _rsv1:1;
2146+ __le32 ru_end_id:7;
2147+ __le32 _rsv2:1;
2148+ __le32 mob_cal_en:1;
2149+ __le32 _rsv3:15;
2150+
2151+ __le32 snr_sts0:8, snr_sts1:8, snr_sts2:8, snr_sts3:8;
2152+ __le32 snr_sts4:8, snr_sts5:8, snr_sts6:8, snr_sts7:8;
2153+
2154+ __le32 _rsv4;
2155+} __packed;
2156+
2157+struct mt7915_tm_pfmu_tag2 {
2158+ __le32 smart_ant:24;
2159+ __le32 se_idx:5;
2160+ __le32 _rsv:3;
2161+
2162+ __le32 _rsv1:8;
2163+ __le32 rmsd_thres:3;
2164+ __le32 _rsv2:5;
2165+ __le32 ibf_timeout:8;
2166+ __le32 _rsv3:8;
2167+
2168+ __le32 _rsv4:16;
2169+ __le32 ibf_data_bw:2;
2170+ __le32 ibf_nc:3;
2171+ __le32 ibf_nr:3;
2172+ __le32 ibf_ru:8;
2173+
2174+ __le32 mob_delta_t:8;
2175+ __le32 mob_lq_result:7;
2176+ __le32 _rsv5:1;
2177+ __le32 _rsv6:16;
2178+
2179+ __le32 _rsv7;
2180+} __packed;
2181+
2182+struct mt7915_tm_pfmu_tag {
2183+ struct mt7915_tm_pfmu_tag1 t1;
2184+ struct mt7915_tm_pfmu_tag2 t2;
2185+};
2186+
2187+struct mt7915_tm_pfmu_data {
2188+ __le16 subc_idx;
2189+ __le16 phi11;
2190+ __le16 phi21;
2191+ __le16 phi31;
2192+};
2193+
2194+struct mt7915_tm_ibf_cal_info {
2195+ u8 format_id;
2196+ u8 group_l_m_n;
2197+ u8 group;
2198+ bool sx2;
2199+ u8 status;
2200+ u8 cal_type;
2201+ u8 _rsv[2];
2202+ u8 buf[1000];
2203+} __packed;
2204+
2205+enum {
2206+ IBF_PHASE_CAL_UNSPEC,
2207+ IBF_PHASE_CAL_NORMAL,
2208+ IBF_PHASE_CAL_VERIFY,
2209+ IBF_PHASE_CAL_NORMAL_INSTRUMENT,
2210+ IBF_PHASE_CAL_VERIFY_INSTRUMENT,
2211+};
2212+
2213 #endif
2214diff --git a/testmode.c b/testmode.c
2215index e6d1f702..2c699ac8 100644
2216--- a/testmode.c
2217+++ b/testmode.c
2218@@ -25,28 +25,15 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
2219 };
2220 EXPORT_SYMBOL_GPL(mt76_tm_policy);
2221
2222-void mt76_testmode_tx_pending(struct mt76_phy *phy)
2223+static void
2224+mt76_testmode_queue_tx(struct mt76_phy *phy, struct mt76_wcid *wcid,
2225+ struct sk_buff *skb, struct mt76_queue *q, u16 limit)
2226 {
2227 struct mt76_testmode_data *td = &phy->test;
2228 struct mt76_dev *dev = phy->dev;
2229- struct mt76_wcid *wcid = &dev->global_wcid;
2230- struct sk_buff *skb = td->tx_skb;
2231- struct mt76_queue *q;
2232- u16 tx_queued_limit;
2233- int qid;
2234-
2235- if (!skb || !td->tx_pending)
2236- return;
2237+ u16 count = limit;
2238
2239- qid = skb_get_queue_mapping(skb);
2240- q = phy->q_tx[qid];
2241-
2242- tx_queued_limit = td->tx_queued_limit ? td->tx_queued_limit : 1000;
2243-
2244- spin_lock_bh(&q->lock);
2245-
2246- while (td->tx_pending > 0 &&
2247- td->tx_queued - td->tx_done < tx_queued_limit &&
2248+ while (td->tx_pending > 0 && count &&
2249 q->queued < q->ndesc / 2) {
2250 int ret;
2251
2252@@ -55,13 +42,65 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
2253 if (ret < 0)
2254 break;
2255
2256+ count--;
2257 td->tx_pending--;
2258 td->tx_queued++;
2259+
2260+ if (td->tx_rate_mode != MT76_TM_TX_MODE_HE_MU)
2261+ if (td->tx_queued - td->tx_done >= limit)
2262+ break;
2263 }
2264
2265 dev->queue_ops->kick(dev, q);
2266+}
2267+
2268+void mt76_testmode_tx_pending(struct mt76_phy *phy)
2269+{
2270+ struct mt76_testmode_data *td = &phy->test;
2271+ struct mt76_testmode_entry_data *ed;
2272+ struct mt76_queue *q;
2273+ int qid;
2274+ u16 tx_queued_limit;
2275+ u32 remain;
2276+ bool is_mu;
2277+
2278+ if (!td->tx_pending)
2279+ return;
2280+
2281+ /* tx_queued_limit = td->tx_queued_limit ?: 100; */
2282+ tx_queued_limit = 100;
2283+
2284+ if (!td->aid) {
2285+ qid = skb_get_queue_mapping(td->tx_skb);
2286+ q = phy->q_tx[qid];
2287+ spin_lock_bh(&q->lock);
2288+ mt76_testmode_queue_tx(phy, &phy->dev->global_wcid,
2289+ td->tx_skb, q, tx_queued_limit);
2290+ spin_unlock_bh(&q->lock);
2291+
2292+ return;
2293+ }
2294+
2295+ is_mu = td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU;
2296+ ed = mt76_testmode_entry_data(phy, td->cur_entry);
2297+ qid = skb_get_queue_mapping(ed->tx_skb);
2298+ q = phy->q_tx[qid];
2299+
2300+ spin_lock_bh(&q->lock);
2301+
2302+ remain = is_mu ? 1 : (td->tx_pending % td->tx_count) ?: td->tx_count;
2303+ if (remain < tx_queued_limit)
2304+ tx_queued_limit = remain;
2305+
2306+ mt76_testmode_queue_tx(phy, td->cur_entry, ed->tx_skb, q, tx_queued_limit);
2307+
2308+ if (td->tx_pending % td->tx_count == 0 || is_mu)
2309+ td->cur_entry = list_next_entry(td->cur_entry, list);
2310
2311 spin_unlock_bh(&q->lock);
2312+
2313+ if (is_mu && td->tx_pending)
2314+ mt76_worker_schedule(&phy->dev->tx_worker);
2315 }
2316
2317 static u32
2318@@ -87,15 +126,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
2319 }
2320
2321 static void
2322-mt76_testmode_free_skb(struct mt76_phy *phy)
2323+mt76_testmode_free_skb(struct sk_buff **tx_skb)
2324+{
2325+ if (!(*tx_skb))
2326+ return;
2327+
2328+ dev_kfree_skb(*tx_skb);
2329+ *tx_skb = NULL;
2330+}
2331+
2332+static void
2333+mt76_testmode_free_skb_all(struct mt76_phy *phy)
2334 {
2335 struct mt76_testmode_data *td = &phy->test;
2336+ struct mt76_testmode_entry_data *ed = &td->ed;
2337+ struct mt76_wcid *wcid;
2338+
2339+ mt76_testmode_free_skb(&ed->tx_skb);
2340
2341- dev_kfree_skb(td->tx_skb);
2342- td->tx_skb = NULL;
2343+ mt76_tm_for_each_entry(phy, wcid, ed)
2344+ mt76_testmode_free_skb(&ed->tx_skb);
2345 }
2346
2347-int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2348+static int
2349+mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len,
2350+ struct sk_buff **tx_skb, u8 (*addr)[ETH_ALEN])
2351 {
2352 #define MT_TXP_MAX_LEN 4095
2353 u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
2354@@ -117,7 +172,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2355 nfrags = len / MT_TXP_MAX_LEN;
2356 head_len = nfrags ? MT_TXP_MAX_LEN : len;
2357
2358- if (len > IEEE80211_MAX_FRAME_LEN)
2359+ if (len > IEEE80211_MAX_FRAME_LEN ||
2360+ td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2361 fc |= IEEE80211_STYPE_QOS_DATA;
2362
2363 head = alloc_skb(head_len, GFP_KERNEL);
2364@@ -126,9 +182,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2365
2366 hdr = __skb_put_zero(head, head_len);
2367 hdr->frame_control = cpu_to_le16(fc);
2368- memcpy(hdr->addr1, td->addr[0], ETH_ALEN);
2369- memcpy(hdr->addr2, td->addr[1], ETH_ALEN);
2370- memcpy(hdr->addr3, td->addr[2], ETH_ALEN);
2371+ memcpy(hdr->addr1, addr[0], ETH_ALEN);
2372+ memcpy(hdr->addr2, addr[1], ETH_ALEN);
2373+ memcpy(hdr->addr3, addr[2], ETH_ALEN);
2374 skb_set_queue_mapping(head, IEEE80211_AC_BE);
2375
2376 info = IEEE80211_SKB_CB(head);
2377@@ -152,7 +208,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2378
2379 frag = alloc_skb(frag_len, GFP_KERNEL);
2380 if (!frag) {
2381- mt76_testmode_free_skb(phy);
2382+ mt76_testmode_free_skb(tx_skb);
2383 dev_kfree_skb(head);
2384 return -ENOMEM;
2385 }
2386@@ -165,15 +221,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2387 frag_tail = &(*frag_tail)->next;
2388 }
2389
2390- mt76_testmode_free_skb(phy);
2391- td->tx_skb = head;
2392+ mt76_testmode_free_skb(tx_skb);
2393+ *tx_skb = head;
2394
2395 return 0;
2396 }
2397-EXPORT_SYMBOL(mt76_testmode_alloc_skb);
2398
2399-static int
2400-mt76_testmode_tx_init(struct mt76_phy *phy)
2401+int mt76_testmode_init_skb(struct mt76_phy *phy, u32 len,
2402+ struct sk_buff **tx_skb, u8 (*addr)[ETH_ALEN])
2403 {
2404 struct mt76_testmode_data *td = &phy->test;
2405 struct ieee80211_tx_info *info;
2406@@ -181,7 +236,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
2407 u8 max_nss = hweight8(phy->antenna_mask);
2408 int ret;
2409
2410- ret = mt76_testmode_alloc_skb(phy, td->tx_mpdu_len);
2411+ ret = mt76_testmode_alloc_skb(phy, len, tx_skb, addr);
2412 if (ret)
2413 return ret;
2414
2415@@ -191,7 +246,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
2416 if (td->tx_antenna_mask)
2417 max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
2418
2419- info = IEEE80211_SKB_CB(td->tx_skb);
2420+ info = IEEE80211_SKB_CB(*tx_skb);
2421 rate = &info->control.rates[0];
2422 rate->count = 1;
2423 rate->idx = td->tx_rate_idx;
2424@@ -263,6 +318,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
2425 out:
2426 return 0;
2427 }
2428+EXPORT_SYMBOL(mt76_testmode_init_skb);
2429+
2430+static int
2431+mt76_testmode_tx_init(struct mt76_phy *phy)
2432+{
2433+ struct mt76_testmode_entry_data *ed;
2434+ struct mt76_wcid *wcid;
2435+
2436+ mt76_tm_for_each_entry(phy, wcid, ed) {
2437+ int ret;
2438+
2439+ ret = mt76_testmode_init_skb(phy, ed->tx_mpdu_len,
2440+ &ed->tx_skb, ed->addr);
2441+ if (ret)
2442+ return ret;
2443+ }
2444+
2445+ return 0;
2446+}
2447
2448 static void
2449 mt76_testmode_tx_start(struct mt76_phy *phy)
2450@@ -273,6 +347,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
2451 td->tx_queued = 0;
2452 td->tx_done = 0;
2453 td->tx_pending = td->tx_count;
2454+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2455+ td->tx_pending = 1;
2456+ if (td->entry_num) {
2457+ td->tx_pending *= td->entry_num;
2458+ td->cur_entry = list_first_entry(&td->tm_entry_list,
2459+ struct mt76_wcid, list);
2460+ }
2461+
2462 mt76_worker_schedule(&dev->tx_worker);
2463 }
2464
2465@@ -291,7 +373,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
2466 wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
2467 MT76_TM_TIMEOUT * HZ);
2468
2469- mt76_testmode_free_skb(phy);
2470+ mt76_testmode_free_skb_all(phy);
2471 }
2472
2473 static inline void
2474@@ -322,6 +404,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
2475 memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
2476 memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
2477 memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
2478+
2479+ INIT_LIST_HEAD(&phy->test.tm_entry_list);
2480 }
2481
2482 static int
2483@@ -331,8 +415,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
2484 struct mt76_dev *dev = phy->dev;
2485 int err;
2486
2487- if (prev_state == MT76_TM_STATE_TX_FRAMES)
2488+ if (prev_state == MT76_TM_STATE_TX_FRAMES) {
2489+ /* MU needs to clean hwq for free done event */
2490+ if (phy->test.tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2491+ dev->test_ops->set_state(phy, MT76_TM_STATE_IDLE);
2492 mt76_testmode_tx_stop(phy);
2493+ }
2494
2495 if (state == MT76_TM_STATE_TX_FRAMES) {
2496 err = mt76_testmode_tx_init(phy);
2497@@ -402,6 +490,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
2498 return 0;
2499 }
2500
2501+static int
2502+mt76_testmode_set_eeprom(struct mt76_phy *phy, struct nlattr **tb)
2503+{
2504+ struct mt76_dev *dev = phy->dev;
2505+ u8 action, val[MT76_TM_EEPROM_BLOCK_SIZE];
2506+ u32 offset = 0;
2507+ int err = -EINVAL;
2508+
2509+ if (!dev->test_ops->set_eeprom)
2510+ return -EOPNOTSUPP;
2511+
2512+ if (mt76_tm_get_u8(tb[MT76_TM_ATTR_EEPROM_ACTION], &action,
2513+ 0, MT76_TM_EEPROM_ACTION_MAX))
2514+ goto out;
2515+
2516+ if (tb[MT76_TM_ATTR_EEPROM_OFFSET]) {
2517+ struct nlattr *cur;
2518+ int rem, idx = 0;
2519+
2520+ offset = nla_get_u32(tb[MT76_TM_ATTR_EEPROM_OFFSET]);
2521+ if (!!(offset % MT76_TM_EEPROM_BLOCK_SIZE) ||
2522+ !tb[MT76_TM_ATTR_EEPROM_VAL])
2523+ goto out;
2524+
2525+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_EEPROM_VAL], rem) {
2526+ if (nla_len(cur) != 1 || idx >= ARRAY_SIZE(val))
2527+ goto out;
2528+
2529+ val[idx++] = nla_get_u8(cur);
2530+ }
2531+ }
2532+
2533+ err = dev->test_ops->set_eeprom(phy, offset, val, action);
2534+
2535+out:
2536+ return err;
2537+}
2538+
2539 int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2540 void *data, int len)
2541 {
2542@@ -425,6 +551,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2543
2544 mutex_lock(&dev->mutex);
2545
2546+ if (tb[MT76_TM_ATTR_EEPROM_ACTION]) {
2547+ err = mt76_testmode_set_eeprom(phy, tb);
2548+ goto out;
2549+ }
2550+
2551 if (tb[MT76_TM_ATTR_RESET]) {
2552 mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
2553 memset(td, 0, sizeof(*td));
2554@@ -452,7 +583,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2555 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
2556 &td->tx_duty_cycle, 0, 99) ||
2557 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
2558- &td->tx_power_control, 0, 1))
2559+ &td->tx_power_control, 0, 1) ||
2560+ mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16) ||
2561+ mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_ALLOC], &td->ru_alloc, 0, 0xff) ||
2562+ mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_IDX], &td->ru_idx, 0, 68))
2563 goto out;
2564
2565 if (tb[MT76_TM_ATTR_TX_LENGTH]) {
2566@@ -484,8 +618,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2567
2568 if (tb[MT76_TM_ATTR_TX_POWER]) {
2569 struct nlattr *cur;
2570- int idx = 0;
2571- int rem;
2572+ int rem, idx = 0;
2573
2574 nla_for_each_nested(cur, tb[MT76_TM_ATTR_TX_POWER], rem) {
2575 if (nla_len(cur) != 1 ||
2576@@ -505,11 +638,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2577 if (nla_len(cur) != ETH_ALEN || idx >= 3)
2578 goto out;
2579
2580- memcpy(td->addr[idx], nla_data(cur), ETH_ALEN);
2581+ memcpy(td->addr[idx++], nla_data(cur), ETH_ALEN);
2582+ }
2583+ }
2584+
2585+ if (tb[MT76_TM_ATTR_CFG]) {
2586+ struct nlattr *cur;
2587+ int rem, idx = 0;
2588+
2589+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_CFG], rem) {
2590+ if (nla_len(cur) != 1 || idx >= 2)
2591+ goto out;
2592+
2593+ if (idx == 0)
2594+ td->cfg.type = nla_get_u8(cur);
2595+ else
2596+ td->cfg.enable = nla_get_u8(cur);
2597 idx++;
2598 }
2599 }
2600
2601+ if (tb[MT76_TM_ATTR_TXBF_ACT]) {
2602+ struct nlattr *cur;
2603+ int rem, idx = 0;
2604+
2605+ if (!tb[MT76_TM_ATTR_TXBF_PARAM] ||
2606+ mt76_tm_get_u8(tb[MT76_TM_ATTR_TXBF_ACT], &td->txbf_act,
2607+ 0, MT76_TM_TXBF_ACT_MAX))
2608+ goto out;
2609+
2610+ memset(td->txbf_param, 0, sizeof(td->txbf_param));
2611+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
2612+ if (nla_len(cur) != 2 ||
2613+ idx >= ARRAY_SIZE(td->txbf_param))
2614+ goto out;
2615+
2616+ td->txbf_param[idx++] = nla_get_u16(cur);
2617+ }
2618+ }
2619+
2620 if (dev->test_ops->set_params) {
2621 err = dev->test_ops->set_params(phy, tb, state);
2622 if (err)
2623@@ -574,6 +741,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
2624 struct mt76_phy *phy = hw->priv;
2625 struct mt76_dev *dev = phy->dev;
2626 struct mt76_testmode_data *td = &phy->test;
2627+ struct mt76_testmode_entry_data *ed = &td->ed;
2628 struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
2629 int err = 0;
2630 void *a;
2631@@ -606,6 +774,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
2632 goto out;
2633 }
2634
2635+ if (tb[MT76_TM_ATTR_AID]) {
2636+ struct mt76_wcid *wcid;
2637+ u8 aid;
2638+
2639+ err = mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &aid, 1, 16);
2640+ if (err)
2641+ goto out;
2642+
2643+ mt76_tm_for_each_entry(phy, wcid, ed)
2644+ if (ed->aid == aid)
2645+ ed = mt76_testmode_entry_data(phy, wcid);
2646+ }
2647+
2648 mt76_testmode_init_defaults(phy);
2649
2650 err = -EMSGSIZE;
2651@@ -618,12 +799,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
2652 goto out;
2653
2654 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
2655- nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, td->tx_mpdu_len) ||
2656 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, td->tx_rate_mode) ||
2657- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, td->tx_rate_nss) ||
2658- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, td->tx_rate_idx) ||
2659 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) ||
2660- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
2661 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
2662 (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
2663 nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
2664@@ -643,6 +820,15 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
2665 nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
2666 goto out;
2667
2668+ if (nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, ed->tx_mpdu_len) ||
2669+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, ed->tx_rate_nss) ||
2670+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, ed->tx_rate_idx) ||
2671+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, ed->tx_rate_ldpc) ||
2672+ nla_put_u8(msg, MT76_TM_ATTR_AID, ed->aid) ||
2673+ nla_put_u8(msg, MT76_TM_ATTR_RU_ALLOC, ed->ru_alloc) ||
2674+ nla_put_u8(msg, MT76_TM_ATTR_RU_IDX, ed->ru_idx))
2675+ goto out;
2676+
2677 if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
2678 a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
2679 if (!a)
2680diff --git a/testmode.h b/testmode.h
2681index 89613266..57949f2b 100644
2682--- a/testmode.h
2683+++ b/testmode.h
2684@@ -6,6 +6,8 @@
2685 #define __MT76_TESTMODE_H
2686
2687 #define MT76_TM_TIMEOUT 10
2688+#define MT76_TM_MAX_ENTRY_NUM 16
2689+#define MT76_TM_EEPROM_BLOCK_SIZE 16
2690
2691 /**
2692 * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
2693@@ -47,6 +49,15 @@
2694 * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
2695 *
2696 * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
2697+ *
2698+ * @MT76_TM_ATTR_EEPROM_ACTION: eeprom setting actions
2699+ * (u8, see &enum mt76_testmode_eeprom_action)
2700+ * @MT76_TM_ATTR_EEPROM_OFFSET: offset of eeprom data block for writing (u32)
2701+ * @MT76_TM_ATTR_EEPROM_VAL: values for writing into a 16-byte data block
2702+ * (nested, u8 attrs)
2703+ *
2704+ * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg)
2705+ *
2706 */
2707 enum mt76_testmode_attr {
2708 MT76_TM_ATTR_UNSPEC,
2709@@ -84,6 +95,17 @@ enum mt76_testmode_attr {
2710 MT76_TM_ATTR_DRV_DATA,
2711
2712 MT76_TM_ATTR_MAC_ADDRS,
2713+ MT76_TM_ATTR_AID,
2714+ MT76_TM_ATTR_RU_ALLOC,
2715+ MT76_TM_ATTR_RU_IDX,
2716+
2717+ MT76_TM_ATTR_EEPROM_ACTION,
2718+ MT76_TM_ATTR_EEPROM_OFFSET,
2719+ MT76_TM_ATTR_EEPROM_VAL,
2720+
2721+ MT76_TM_ATTR_CFG,
2722+ MT76_TM_ATTR_TXBF_ACT,
2723+ MT76_TM_ATTR_TXBF_PARAM,
2724
2725 /* keep last */
2726 NUM_MT76_TM_ATTRS,
2727@@ -198,4 +220,57 @@ enum mt76_testmode_tx_mode {
2728
2729 extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
2730
2731+/**
2732+ * enum mt76_testmode_eeprom_action - eeprom setting actions
2733+ *
2734+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
2735+ * eeprom data block
2736+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
2737+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
2738+ */
2739+enum mt76_testmode_eeprom_action {
2740+ MT76_TM_EEPROM_ACTION_UPDATE_DATA,
2741+ MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
2742+ MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
2743+
2744+ /* keep last */
2745+ NUM_MT76_TM_EEPROM_ACTION,
2746+ MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
2747+};
2748+
2749+/**
2750+ * enum mt76_testmode_cfg - packet tx phy mode
2751+ *
2752+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
2753+ * eeprom data block
2754+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
2755+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
2756+ */
2757+enum mt76_testmode_cfg {
2758+ MT76_TM_CFG_TSSI,
2759+ MT76_TM_CFG_DPD,
2760+ MT76_TM_CFG_RATE_POWER_OFFSET,
2761+ MT76_TM_CFG_THERMAL_COMP,
2762+
2763+ /* keep last */
2764+ NUM_MT76_TM_CFG,
2765+ MT76_TM_CFG_MAX = NUM_MT76_TM_CFG - 1,
2766+};
2767+
2768+enum mt76_testmode_txbf_act {
2769+ MT76_TM_TXBF_ACT_INIT,
2770+ MT76_TM_TXBF_ACT_UPDATE_CH,
2771+ MT76_TM_TXBF_ACT_PHASE_COMP,
2772+ MT76_TM_TXBF_ACT_TX_PREP,
2773+ MT76_TM_TXBF_ACT_IBF_PROF_UPDATE,
2774+ MT76_TM_TXBF_ACT_EBF_PROF_UPDATE,
2775+ MT76_TM_TXBF_ACT_PHASE_CAL,
2776+ MT76_TM_TXBF_ACT_PROF_UPDATE_ALL,
2777+ MT76_TM_TXBF_ACT_E2P_UPDATE,
2778+
2779+ /* keep last */
2780+ NUM_MT76_TM_TXBF_ACT,
2781+ MT76_TM_TXBF_ACT_MAX = NUM_MT76_TM_TXBF_ACT - 1,
2782+};
2783+
2784 #endif
2785diff --git a/tools/fields.c b/tools/fields.c
2786index e3f69089..6e36ab27 100644
2787--- a/tools/fields.c
2788+++ b/tools/fields.c
2789@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
2790 [MT76_TM_STATE_IDLE] = "idle",
2791 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
2792 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
2793+ [MT76_TM_STATE_TX_CONT] = "tx_cont",
2794 };
2795
2796 static const char * const testmode_tx_mode[] = {
2797@@ -201,6 +202,63 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2798 printf("%srx_per=%.02f%%\n", prefix, 100 * failed / total);
2799 }
2800
2801+static bool parse_mac(const struct tm_field *field, int idx,
2802+ struct nl_msg *msg, const char *val)
2803+{
2804+#define ETH_ALEN 6
2805+ bool ret = true;
2806+ char *str, *cur, *ap;
2807+ void *a;
2808+
2809+ ap = str = strdup(val);
2810+
2811+ a = nla_nest_start(msg, idx);
2812+
2813+ idx = 0;
2814+ while ((cur = strsep(&ap, ",")) != NULL) {
2815+ unsigned char addr[ETH_ALEN];
2816+ char *val, *tmp = cur;
2817+ int i = 0;
2818+
2819+ while ((val = strsep(&tmp, ":")) != NULL) {
2820+ if (i >= ETH_ALEN)
2821+ break;
2822+
2823+ addr[i++] = strtoul(val, NULL, 16);
2824+ }
2825+
2826+ nla_put(msg, idx, ETH_ALEN, addr);
2827+
2828+ idx++;
2829+ }
2830+
2831+ nla_nest_end(msg, a);
2832+
2833+ free(str);
2834+
2835+ return ret;
2836+}
2837+
2838+static void print_mac(const struct tm_field *field, struct nlattr *attr)
2839+{
2840+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
2841+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
2842+ unsigned char addr[3][6];
2843+ struct nlattr *cur;
2844+ int idx = 0;
2845+ int rem;
2846+
2847+ nla_for_each_nested(cur, attr, rem) {
2848+ if (nla_len(cur) != 6)
2849+ continue;
2850+ memcpy(addr[idx++], nla_data(cur), 6);
2851+ }
2852+
2853+ printf("" MACSTR "," MACSTR "," MACSTR "",
2854+ MAC2STR(addr[0]), MAC2STR(addr[1]), MAC2STR(addr[2]));
2855+
2856+ return;
2857+}
2858
2859 #define FIELD_GENERIC(_field, _name, ...) \
2860 [FIELD_NAME(_field)] = { \
2861@@ -250,6 +308,13 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2862 ##__VA_ARGS__ \
2863 )
2864
2865+#define FIELD_MAC(_field, _name) \
2866+ [FIELD_NAME(_field)] = { \
2867+ .name = _name, \
2868+ .parse = parse_mac, \
2869+ .print = print_mac \
2870+ }
2871+
2872 #define FIELD_NAME(_field) MT76_TM_RX_ATTR_##_field
2873 static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
2874 FIELD_RO(s32, FREQ_OFFSET, "freq_offset"),
2875@@ -300,10 +365,18 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
2876 FIELD(u8, TX_RATE_LDPC, "tx_rate_ldpc"),
2877 FIELD(u8, TX_RATE_STBC, "tx_rate_stbc"),
2878 FIELD(u8, TX_LTF, "tx_ltf"),
2879+ FIELD(u8, TX_DUTY_CYCLE, "tx_duty_cycle"),
2880+ FIELD(u32, TX_IPG, "tx_ipg"),
2881+ FIELD(u32, TX_TIME, "tx_time"),
2882 FIELD(u8, TX_POWER_CONTROL, "tx_power_control"),
2883 FIELD_ARRAY(u8, TX_POWER, "tx_power"),
2884 FIELD(u8, TX_ANTENNA, "tx_antenna"),
2885+ FIELD(u8, TX_SPE_IDX, "tx_spe_idx"),
2886 FIELD(u32, FREQ_OFFSET, "freq_offset"),
2887+ FIELD(u8, AID, "aid"),
2888+ FIELD(u8, RU_ALLOC, "ru_alloc"),
2889+ FIELD(u8, RU_IDX, "ru_idx"),
2890+ FIELD_MAC(MAC_ADDRS, "mac_addrs"),
2891 FIELD_NESTED_RO(STATS, stats, "",
2892 .print_extra = print_extra_stats),
2893 };
2894@@ -322,9 +395,16 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
2895 [MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 },
2896 [MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
2897 [MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
2898+ [MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 },
2899+ [MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 },
2900+ [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
2901 [MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },
2902 [MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },
2903+ [MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 },
2904 [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
2905+ [MT76_TM_ATTR_AID] = { .type = NLA_U8 },
2906+ [MT76_TM_ATTR_RU_ALLOC] = { .type = NLA_U8 },
2907+ [MT76_TM_ATTR_RU_IDX] = { .type = NLA_U8 },
2908 [MT76_TM_ATTR_STATS] = { .type = NLA_NESTED },
2909 };
2910
2911diff --git a/tx.c b/tx.c
2912index 02067edc..0457c3eb 100644
2913--- a/tx.c
2914+++ b/tx.c
2915@@ -245,8 +245,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
2916 if (mt76_is_testmode_skb(dev, skb, &hw)) {
2917 struct mt76_phy *phy = hw->priv;
2918
2919- if (skb == phy->test.tx_skb)
2920- phy->test.tx_done++;
2921+ phy->test.tx_done++;
2922 if (phy->test.tx_queued == phy->test.tx_done)
2923 wake_up(&dev->tx_wait);
2924
2925--
developerc6f56bb2022-06-14 18:36:30 +080029262.25.1
developer4c6b6002022-05-30 16:36:44 +08002927