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