blob: e2dcba6399062125ab0b0bcaa4dd7aab4d92f0b2 [file] [log] [blame]
developerc1997a82023-03-30 15:28:14 +08001From 219040e9aa5a584809fce08c86d6a6279cf7fe8a 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
developerc1997a82023-03-30 15:28:14 +08004Subject: [PATCH 1112/1133] mt76: testmode: additional supports
developer4c6b6002022-05-30 16:36:44 +08005
6Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
developer287ee9f2023-03-02 20:13:34 +08007Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer4c6b6002022-05-30 16:36:44 +08008---
developerf40484f2022-08-25 15:33:33 +08009 dma.c | 3 +-
10 mac80211.c | 12 +
developer1d9fede2022-08-29 15:24:07 +080011 mt76.h | 108 ++++-
developerf40484f2022-08-25 15:33:33 +080012 mt76_connac_mcu.c | 4 +
13 mt76_connac_mcu.h | 2 +
developerc1997a82023-03-30 15:28:14 +080014 mt7915/eeprom.c | 2 +-
developerf40484f2022-08-25 15:33:33 +080015 mt7915/init.c | 2 +-
developer4feb1012023-01-30 17:29:07 +080016 mt7915/mac.c | 39 +-
developerf40484f2022-08-25 15:33:33 +080017 mt7915/main.c | 2 +-
developerc1997a82023-03-30 15:28:14 +080018 mt7915/mcu.c | 19 +-
developerf40484f2022-08-25 15:33:33 +080019 mt7915/mcu.h | 28 +-
20 mt7915/mmio.c | 2 +
developerc1997a82023-03-30 15:28:14 +080021 mt7915/mt7915.h | 16 +-
developerf40484f2022-08-25 15:33:33 +080022 mt7915/regs.h | 3 +
developerc1997a82023-03-30 15:28:14 +080023 mt7915/testmode.c | 1184 ++++++++++++++++++++++++++++++++++++++++++---
developerf40484f2022-08-25 15:33:33 +080024 mt7915/testmode.h | 278 +++++++++++
developer62713c82023-03-20 10:46:08 +080025 testmode.c | 280 +++++++++--
developerf40484f2022-08-25 15:33:33 +080026 testmode.h | 75 +++
developer62713c82023-03-20 10:46:08 +080027 tools/fields.c | 84 +++-
developerf40484f2022-08-25 15:33:33 +080028 tx.c | 3 +-
developerc1997a82023-03-30 15:28:14 +080029 20 files changed, 1990 insertions(+), 156 deletions(-)
developer4c6b6002022-05-30 16:36:44 +080030
31diff --git a/dma.c b/dma.c
developer62713c82023-03-20 10:46:08 +080032index df2ca73..fe65e0f 100644
developer4c6b6002022-05-30 16:36:44 +080033--- a/dma.c
34+++ b/dma.c
developer62713c82023-03-20 10:46:08 +080035@@ -568,8 +568,7 @@ free:
developer4c6b6002022-05-30 16:36:44 +080036 if (mt76_is_testmode_skb(dev, skb, &hw)) {
37 struct mt76_phy *phy = hw->priv;
38
39- if (tx_info.skb == phy->test.tx_skb)
40- phy->test.tx_done--;
41+ phy->test.tx_done--;
42 }
43 #endif
44
45diff --git a/mac80211.c b/mac80211.c
developer62713c82023-03-20 10:46:08 +080046index ad5d6f8..9107c0c 100644
developer4c6b6002022-05-30 16:36:44 +080047--- a/mac80211.c
48+++ b/mac80211.c
developerc04f5402023-02-03 09:22:26 +080049@@ -56,6 +56,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
developer4c6b6002022-05-30 16:36:44 +080050 CHAN5G(60, 5300),
51 CHAN5G(64, 5320),
52
53+ CHAN5G(68, 5340),
54+ CHAN5G(80, 5400),
55+ CHAN5G(84, 5420),
56+ CHAN5G(88, 5440),
57+ CHAN5G(92, 5460),
58+ CHAN5G(96, 5480),
59+
60 CHAN5G(100, 5500),
61 CHAN5G(104, 5520),
62 CHAN5G(108, 5540),
developerc04f5402023-02-03 09:22:26 +080063@@ -76,6 +83,11 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
developer4c6b6002022-05-30 16:36:44 +080064 CHAN5G(165, 5825),
65 CHAN5G(169, 5845),
66 CHAN5G(173, 5865),
67+
68+ CHAN5G(184, 4920),
69+ CHAN5G(188, 4940),
70+ CHAN5G(192, 4960),
71+ CHAN5G(196, 4980),
72 };
73
74 static const struct ieee80211_channel mt76_channels_6ghz[] = {
75diff --git a/mt76.h b/mt76.h
developer62713c82023-03-20 10:46:08 +080076index ca66448..898726e 100644
developer4c6b6002022-05-30 16:36:44 +080077--- a/mt76.h
78+++ b/mt76.h
developer62713c82023-03-20 10:46:08 +080079@@ -642,6 +642,21 @@ struct mt76_testmode_ops {
developer4c6b6002022-05-30 16:36:44 +080080 int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
81 enum mt76_testmode_state new_state);
82 int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
83+ int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
84+};
85+
86+struct mt76_testmode_entry_data {
87+ struct sk_buff *tx_skb;
88+
89+ u16 tx_mpdu_len;
90+ u8 tx_rate_idx;
91+ u8 tx_rate_nss;
92+ u8 tx_rate_ldpc;
93+
94+ u8 addr[3][ETH_ALEN];
95+ u8 aid;
96+ u8 ru_alloc;
97+ u8 ru_idx;
98 };
99
100 #define MT_TM_FW_RX_COUNT BIT(0)
developer62713c82023-03-20 10:46:08 +0800101@@ -650,16 +665,11 @@ struct mt76_testmode_data {
developer4c6b6002022-05-30 16:36:44 +0800102 enum mt76_testmode_state state;
103
104 u32 param_set[DIV_ROUND_UP(NUM_MT76_TM_ATTRS, 32)];
105- struct sk_buff *tx_skb;
106
107 u32 tx_count;
108- u16 tx_mpdu_len;
109
110 u8 tx_rate_mode;
111- u8 tx_rate_idx;
112- u8 tx_rate_nss;
113 u8 tx_rate_sgi;
114- u8 tx_rate_ldpc;
115 u8 tx_rate_stbc;
116 u8 tx_ltf;
117
developer62713c82023-03-20 10:46:08 +0800118@@ -675,10 +685,37 @@ struct mt76_testmode_data {
developer4c6b6002022-05-30 16:36:44 +0800119 u8 tx_power[4];
120 u8 tx_power_control;
121
122- u8 addr[3][ETH_ALEN];
123+ struct list_head tm_entry_list;
124+ struct mt76_wcid *cur_entry;
125+ u8 entry_num;
126+ union {
127+ struct mt76_testmode_entry_data ed;
128+ struct {
129+ /* must be the same as mt76_testmode_entry_data */
130+ struct sk_buff *tx_skb;
131+
132+ u16 tx_mpdu_len;
133+ u8 tx_rate_idx;
134+ u8 tx_rate_nss;
135+ u8 tx_rate_ldpc;
136+
137+ u8 addr[3][ETH_ALEN];
138+ u8 aid;
139+ u8 ru_alloc;
140+ u8 ru_idx;
141+ };
142+ };
143
144 u8 flag;
145
146+ struct {
147+ u8 type;
148+ u8 enable;
149+ } cfg;
150+
151+ u8 txbf_act;
152+ u16 txbf_param[8];
153+
154 u32 tx_pending;
155 u32 tx_queued;
156 u16 tx_queued_limit;
developer62713c82023-03-20 10:46:08 +0800157@@ -1142,6 +1179,59 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +0800158 #endif
159 }
160
161+#ifdef CONFIG_NL80211_TESTMODE
162+static inline struct mt76_wcid *
163+mt76_testmode_first_entry(struct mt76_phy *phy)
164+{
165+ if (list_empty(&phy->test.tm_entry_list) && !phy->test.aid)
166+ return &phy->dev->global_wcid;
167+
168+ return list_first_entry(&phy->test.tm_entry_list,
169+ typeof(struct mt76_wcid),
170+ list);
171+}
172+
173+static inline struct mt76_testmode_entry_data *
174+mt76_testmode_entry_data(struct mt76_phy *phy, struct mt76_wcid *wcid)
175+{
176+ if (!wcid)
177+ return NULL;
178+ if (wcid == &phy->dev->global_wcid)
179+ return &phy->test.ed;
180+
181+ return (struct mt76_testmode_entry_data *)((u8 *)wcid +
182+ phy->hw->sta_data_size);
183+}
184+
185+#define mt76_tm_for_each_entry(phy, wcid, ed) \
186+ for (wcid = mt76_testmode_first_entry(phy), \
187+ ed = mt76_testmode_entry_data(phy, wcid); \
188+ ((phy->test.aid && \
189+ !list_entry_is_head(wcid, &phy->test.tm_entry_list, list)) || \
190+ (!phy->test.aid && wcid == &phy->dev->global_wcid)) && ed; \
191+ wcid = list_next_entry(wcid, list), \
192+ ed = mt76_testmode_entry_data(phy, wcid))
193+#endif
194+
195+static inline bool __mt76_is_testmode_skb(struct mt76_phy *phy,
196+ struct sk_buff *skb)
197+{
198+#ifdef CONFIG_NL80211_TESTMODE
199+ struct mt76_testmode_entry_data *ed = &phy->test.ed;
200+ struct mt76_wcid *wcid;
201+
202+ if (skb == ed->tx_skb)
203+ return true;
204+
205+ mt76_tm_for_each_entry(phy, wcid, ed)
206+ if (skb == ed->tx_skb)
207+ return true;
208+ return false;
209+#else
210+ return false;
211+#endif
212+}
213+
214 static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
215 struct sk_buff *skb,
216 struct ieee80211_hw **hw)
developer62713c82023-03-20 10:46:08 +0800217@@ -1152,7 +1242,8 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
developer1d9fede2022-08-29 15:24:07 +0800218 for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
219 struct mt76_phy *phy = dev->phys[i];
220
221- if (phy && skb == phy->test.tx_skb) {
222+ if (phy && mt76_testmode_enabled(phy) &&
223+ __mt76_is_testmode_skb(phy, skb)) {
224 *hw = dev->phys[i]->hw;
225 return true;
226 }
developer62713c82023-03-20 10:46:08 +0800227@@ -1254,7 +1345,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer4c6b6002022-05-30 16:36:44 +0800228 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
developer287ee9f2023-03-02 20:13:34 +0800238index 2fefac6..b6c2ccf 100644
developer4c6b6002022-05-30 16:36:44 +0800239--- a/mt76_connac_mcu.c
240+++ b/mt76_connac_mcu.c
developer144824b2022-11-25 21:27:43 +0800241@@ -394,6 +394,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
developer144824b2022-11-25 21:27:43 +0800249@@ -575,6 +576,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
developer62713c82023-03-20 10:46:08 +0800260index 8ba8ebf..4a63a24 100644
developer4c6b6002022-05-30 16:36:44 +0800261--- a/mt76_connac_mcu.h
262+++ b/mt76_connac_mcu.h
developer62713c82023-03-20 10:46:08 +0800263@@ -996,6 +996,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,
developer62713c82023-03-20 10:46:08 +0800271@@ -1197,6 +1198,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 };
developerc1997a82023-03-30 15:28:14 +0800279diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c
280index a796289..f1b1471 100644
281--- a/mt7915/eeprom.c
282+++ b/mt7915/eeprom.c
283@@ -126,7 +126,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
284 /* read eeprom data from efuse */
285 block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);
286 for (i = 0; i < block_num; i++) {
287- ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size);
288+ ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
289 if (ret < 0)
290 return ret;
291 }
developer4c6b6002022-05-30 16:36:44 +0800292diff --git a/mt7915/init.c b/mt7915/init.c
developer62713c82023-03-20 10:46:08 +0800293index 1177e4e..f40d09c 100644
developer4c6b6002022-05-30 16:36:44 +0800294--- a/mt7915/init.c
295+++ b/mt7915/init.c
developer62713c82023-03-20 10:46:08 +0800296@@ -695,7 +695,7 @@ static void mt7915_init_work(struct work_struct *work)
developer4c6b6002022-05-30 16:36:44 +0800297 struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
298 init_work);
299
300- mt7915_mcu_set_eeprom(dev);
301+ mt7915_mcu_set_eeprom(dev, dev->flash_mode);
302 mt7915_mac_init(dev);
303 mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
304 mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
305diff --git a/mt7915/mac.c b/mt7915/mac.c
developer287ee9f2023-03-02 20:13:34 +0800306index de2bdba..1460a32 100644
developer4c6b6002022-05-30 16:36:44 +0800307--- a/mt7915/mac.c
308+++ b/mt7915/mac.c
developerc04f5402023-02-03 09:22:26 +0800309@@ -627,16 +627,38 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
developer4c6b6002022-05-30 16:36:44 +0800310 {
311 #ifdef CONFIG_NL80211_TESTMODE
312 struct mt76_testmode_data *td = &phy->mt76->test;
313+ struct mt76_testmode_entry_data *ed;
314+ struct mt76_wcid *wcid;
315 const struct ieee80211_rate *r;
316- u8 bw, mode, nss = td->tx_rate_nss;
317- u8 rate_idx = td->tx_rate_idx;
318+ u8 bw, mode, nss, rate_idx, ldpc;
319 u16 rateval = 0;
320 u32 val;
321 bool cck = false;
322 int band;
323
324- if (skb != phy->mt76->test.tx_skb)
325+ txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID);
326+ txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
327+ phy->test.spe_idx));
328+
329+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU) {
330+ txwi[1] |= cpu_to_le32(BIT(18));
331+ txwi[2] = 0;
332+ txwi[3] &= ~cpu_to_le32(MT_TXD3_NO_ACK);
333+ le32p_replace_bits(&txwi[3], 0x1f, MT_TXD3_REM_TX_COUNT);
334+
developerf40484f2022-08-25 15:33:33 +0800335 return;
developer4c6b6002022-05-30 16:36:44 +0800336+ }
337+
338+ mt76_tm_for_each_entry(phy->mt76, wcid, ed)
339+ if (ed->tx_skb == skb)
340+ break;
341+
342+ if (!ed)
developerf40484f2022-08-25 15:33:33 +0800343+ return;
344+
developer4c6b6002022-05-30 16:36:44 +0800345+ nss = ed->tx_rate_nss;
346+ rate_idx = ed->tx_rate_idx;
347+ ldpc = ed->tx_rate_ldpc;
developerf40484f2022-08-25 15:33:33 +0800348
developer4c6b6002022-05-30 16:36:44 +0800349 switch (td->tx_rate_mode) {
350 case MT76_TM_TX_MODE_HT:
developerc04f5402023-02-03 09:22:26 +0800351@@ -667,7 +689,7 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
developer4feb1012023-01-30 17:29:07 +0800352 rate_idx += 4;
353
354 r = &phy->mt76->hw->wiphy->bands[band]->bitrates[rate_idx];
355- val = cck ? r->hw_value_short : r->hw_value;
356+ val = r->hw_value;
357
358 mode = val >> 8;
359 rate_idx = val & 0xff;
developerc04f5402023-02-03 09:22:26 +0800360@@ -726,13 +748,14 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
developer4c6b6002022-05-30 16:36:44 +0800361 if (mode >= MT_PHY_TYPE_HE_SU)
362 val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf);
363
364- if (td->tx_rate_ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU))
365+ if (ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU))
366 val |= MT_TXD6_LDPC;
367
developerf40484f2022-08-25 15:33:33 +0800368 txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID);
developer4c6b6002022-05-30 16:36:44 +0800369+ if (phy->test.bf_en)
370+ val |= MT_TXD6_TX_IBF | MT_TXD6_TX_EBF;
371+
372 txwi[6] |= cpu_to_le32(val);
373- txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
374- phy->test.spe_idx));
375 #endif
376 }
377
developerc04f5402023-02-03 09:22:26 +0800378@@ -1479,7 +1502,7 @@ mt7915_mac_restart(struct mt7915_dev *dev)
developer356ecec2022-11-14 10:25:04 +0800379 goto out;
380
381 /* set the necessary init items */
382- ret = mt7915_mcu_set_eeprom(dev);
383+ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
384 if (ret)
385 goto out;
386
developer4c6b6002022-05-30 16:36:44 +0800387diff --git a/mt7915/main.c b/mt7915/main.c
developerc1997a82023-03-30 15:28:14 +0800388index 3a9f343..8789444 100644
developer4c6b6002022-05-30 16:36:44 +0800389--- a/mt7915/main.c
390+++ b/mt7915/main.c
developer9851a292022-12-15 17:33:43 +0800391@@ -238,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
developer4c6b6002022-05-30 16:36:44 +0800392 mvif->phy = phy;
developereb6a0182022-12-12 18:53:32 +0800393 mvif->mt76.band_idx = phy->mt76->band_idx;
developer4c6b6002022-05-30 16:36:44 +0800394
395- mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
396+ mvif->mt76.wmm_idx = (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_MONITOR);
397 if (ext_phy)
398 mvif->mt76.wmm_idx += 2;
399
400diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developerc1997a82023-03-30 15:28:14 +0800401index b0cdd4a..6f9acd8 100644
developer4c6b6002022-05-30 16:36:44 +0800402--- a/mt7915/mcu.c
403+++ b/mt7915/mcu.c
developereb6a0182022-12-12 18:53:32 +0800404@@ -383,6 +383,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
developer4c6b6002022-05-30 16:36:44 +0800405 case MCU_EXT_EVENT_BCC_NOTIFY:
406 mt7915_mcu_rx_bcc_notify(dev, skb);
407 break;
408+#ifdef CONFIG_NL80211_TESTMODE
409+ case MCU_EXT_EVENT_BF_STATUS_READ:
410+ mt7915_tm_txbf_status_read(dev, skb);
411+ break;
412+#endif
413 default:
414 break;
415 }
developereb6a0182022-12-12 18:53:32 +0800416@@ -414,6 +419,7 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
developer4c6b6002022-05-30 16:36:44 +0800417 rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
418 rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
419 rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
420+ rxd->ext_eid == MCU_EXT_EVENT_BF_STATUS_READ ||
421 !rxd->seq)
422 mt7915_mcu_rx_unsolicited_event(dev, skb);
423 else
developerc1997a82023-03-30 15:28:14 +0800424@@ -2860,21 +2866,21 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
developer4c6b6002022-05-30 16:36:44 +0800425 return 0;
426 }
427
428-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
429+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
430 {
431 struct mt7915_mcu_eeprom req = {
432 .buffer_mode = EE_MODE_EFUSE,
433 .format = EE_FORMAT_WHOLE,
434 };
435
436- if (dev->flash_mode)
437+ if (flash_mode)
438 return mt7915_mcu_set_eeprom_flash(dev);
439
440 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
developerc1997a82023-03-30 15:28:14 +0800441 &req, sizeof(req), true);
442 }
443
444-int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
445+int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
446 {
447 struct mt7915_mcu_eeprom_info req = {
448 .addr = cpu_to_le32(round_down(offset,
449@@ -2883,7 +2889,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
450 struct mt7915_mcu_eeprom_info *res;
451 struct sk_buff *skb;
452 int ret;
453- u8 *buf;
454+ u8 *buf = read_buf;
455
456 ret = mt76_mcu_send_and_get_msg(&dev->mt76,
457 MCU_EXT_QUERY(EFUSE_ACCESS),
458@@ -2892,8 +2898,11 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
459 return ret;
460
461 res = (struct mt7915_mcu_eeprom_info *)skb->data;
462- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
463+
464+ if (!buf)
465+ buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
466 memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
467+
468 dev_kfree_skb(skb);
469
470 return 0;
developer4c6b6002022-05-30 16:36:44 +0800471diff --git a/mt7915/mcu.h b/mt7915/mcu.h
developerc1997a82023-03-30 15:28:14 +0800472index 99d733b..dd6a44d 100644
developer4c6b6002022-05-30 16:36:44 +0800473--- a/mt7915/mcu.h
474+++ b/mt7915/mcu.h
developerf64861f2022-06-22 11:44:53 +0800475@@ -8,10 +8,15 @@
developer4c6b6002022-05-30 16:36:44 +0800476
477 enum {
478 MCU_ATE_SET_TRX = 0x1,
479+ MCU_ATE_SET_TSSI = 0x5,
480+ MCU_ATE_SET_DPD = 0x6,
481+ MCU_ATE_SET_RATE_POWER_OFFSET = 0x7,
482+ MCU_ATE_SET_THERMAL_COMP = 0x8,
483 MCU_ATE_SET_FREQ_OFFSET = 0xa,
484 MCU_ATE_SET_PHY_COUNT = 0x11,
485 MCU_ATE_SET_SLOT_TIME = 0x13,
486 MCU_ATE_CLEAN_TXQUEUE = 0x1c,
487+ MCU_ATE_SET_MU_RX_AID = 0x1e,
488 };
489
developerf64861f2022-06-22 11:44:53 +0800490 struct mt7915_mcu_thermal_ctrl {
developerc04f5402023-02-03 09:22:26 +0800491@@ -472,6 +477,12 @@ enum {
developer4c6b6002022-05-30 16:36:44 +0800492
493 enum {
494 MT_BF_SOUNDING_ON = 1,
495+ MT_BF_DATA_PACKET_APPLY = 2,
496+ MT_BF_PFMU_TAG_READ = 5,
497+ MT_BF_PFMU_TAG_WRITE = 6,
498+ MT_BF_PHASE_CAL = 14,
499+ MT_BF_IBF_PHASE_COMP = 15,
500+ MT_BF_PROFILE_WRITE_ALL = 17,
501 MT_BF_TYPE_UPDATE = 20,
502 MT_BF_MODULE_UPDATE = 25
503 };
developerc1997a82023-03-30 15:28:14 +0800504@@ -717,10 +728,19 @@ struct mt7915_muru {
developer4c6b6002022-05-30 16:36:44 +0800505 #define MURU_OFDMA_SCH_TYPE_UL BIT(1)
506
developerf64861f2022-06-22 11:44:53 +0800507 /* Common Config */
developer4c6b6002022-05-30 16:36:44 +0800508-#define MURU_COMM_PPDU_FMT BIT(0)
509-#define MURU_COMM_SCH_TYPE BIT(1)
510-#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE)
developer4c6b6002022-05-30 16:36:44 +0800511-/* DL&UL User config*/
developer4c6b6002022-05-30 16:36:44 +0800512+/* #define MURU_COMM_PPDU_FMT BIT(0) */
513+/* #define MURU_COMM_SCH_TYPE BIT(1) */
514+/* #define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE) */
developer4721e252022-06-21 16:41:28 +0800515+#define MURU_COMM_PPDU_FMT BIT(0)
516+#define MURU_COMM_SCH_TYPE BIT(1)
517+#define MURU_COMM_BAND BIT(2)
518+#define MURU_COMM_WMM BIT(3)
519+#define MURU_COMM_SPE_IDX BIT(4)
520+#define MURU_COMM_PROC_TYPE BIT(5)
521+#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \
522+ MURU_COMM_WMM | MURU_COMM_SPE_IDX)
developer4c6b6002022-05-30 16:36:44 +0800523+
524+/* DL&UL User config */
525 #define MURU_USER_CNT BIT(4)
526
527 enum {
528diff --git a/mt7915/mmio.c b/mt7915/mmio.c
developer62713c82023-03-20 10:46:08 +0800529index dbafb5f..bb752a8 100644
developer4c6b6002022-05-30 16:36:44 +0800530--- a/mt7915/mmio.c
531+++ b/mt7915/mmio.c
developerc04f5402023-02-03 09:22:26 +0800532@@ -134,6 +134,7 @@ static const u32 mt7915_offs[] = {
developer4c6b6002022-05-30 16:36:44 +0800533 [ARB_DRNGR0] = 0x194,
534 [ARB_SCR] = 0x080,
535 [RMAC_MIB_AIRTIME14] = 0x3b8,
536+ [AGG_AALCR0] = 0x048,
537 [AGG_AWSCR0] = 0x05c,
538 [AGG_PCR0] = 0x06c,
539 [AGG_ACR0] = 0x084,
developerc04f5402023-02-03 09:22:26 +0800540@@ -209,6 +210,7 @@ static const u32 mt7916_offs[] = {
developer4c6b6002022-05-30 16:36:44 +0800541 [ARB_DRNGR0] = 0x1e0,
542 [ARB_SCR] = 0x000,
543 [RMAC_MIB_AIRTIME14] = 0x0398,
544+ [AGG_AALCR0] = 0x028,
545 [AGG_AWSCR0] = 0x030,
546 [AGG_PCR0] = 0x040,
547 [AGG_ACR0] = 0x054,
548diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developerc1997a82023-03-30 15:28:14 +0800549index 055cbb5..416606a 100644
developer4c6b6002022-05-30 16:36:44 +0800550--- a/mt7915/mt7915.h
551+++ b/mt7915/mt7915.h
developer287ee9f2023-03-02 20:13:34 +0800552@@ -323,6 +323,9 @@ struct mt7915_phy {
developer4c6b6002022-05-30 16:36:44 +0800553 u8 last_snr;
554
555 u8 spe_idx;
556+
557+ bool bf_en;
558+ bool bf_ever_en;
559 } test;
560 #endif
561
developer287ee9f2023-03-02 20:13:34 +0800562@@ -422,6 +425,14 @@ struct mt7915_dev {
developer4c6b6002022-05-30 16:36:44 +0800563 void __iomem *dcm;
564 void __iomem *sku;
565
566+#ifdef CONFIG_NL80211_TESTMODE
567+ struct {
568+ void *txbf_phase_cal;
569+ void *txbf_pfmu_data;
570+ void *txbf_pfmu_tag;
571+ } test;
572+#endif
573+
574 #ifdef MTK_DEBUG
575 u16 wlan_idx;
576 struct {
developerc1997a82023-03-30 15:28:14 +0800577@@ -594,8 +605,8 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
developer4c6b6002022-05-30 16:36:44 +0800578 struct ieee80211_vif *vif,
579 struct ieee80211_sta *sta,
580 void *data, u32 field);
581-int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
developerc1997a82023-03-30 15:28:14 +0800582-int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
developer4c6b6002022-05-30 16:36:44 +0800583+int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode);
developerc1997a82023-03-30 15:28:14 +0800584+int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf);
developer4c6b6002022-05-30 16:36:44 +0800585 int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
586 int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
developerc1997a82023-03-30 15:28:14 +0800587 bool hdr_trans);
588@@ -632,6 +643,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
developer4c6b6002022-05-30 16:36:44 +0800589 int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
590 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
591 void mt7915_mcu_exit(struct mt7915_dev *dev);
592+int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
593
594 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
595 {
596diff --git a/mt7915/regs.h b/mt7915/regs.h
developer287ee9f2023-03-02 20:13:34 +0800597index d6a05f1..e876848 100644
developer4c6b6002022-05-30 16:36:44 +0800598--- a/mt7915/regs.h
599+++ b/mt7915/regs.h
developer144824b2022-11-25 21:27:43 +0800600@@ -62,6 +62,7 @@ enum offs_rev {
developer4c6b6002022-05-30 16:36:44 +0800601 ARB_DRNGR0,
602 ARB_SCR,
603 RMAC_MIB_AIRTIME14,
604+ AGG_AALCR0,
605 AGG_AWSCR0,
606 AGG_PCR0,
607 AGG_ACR0,
developer144824b2022-11-25 21:27:43 +0800608@@ -482,6 +483,8 @@ enum offs_rev {
developer4c6b6002022-05-30 16:36:44 +0800609 #define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000)
610 #define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
611
612+#define MT_AGG_AALCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_AALCR0) + \
613+ (_n) * 4))
614 #define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_AWSCR0) + \
615 (_n) * 4))
616 #define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \
617diff --git a/mt7915/testmode.c b/mt7915/testmode.c
developerc1997a82023-03-30 15:28:14 +0800618index 4693919..1ed2ea8 100644
developer4c6b6002022-05-30 16:36:44 +0800619--- a/mt7915/testmode.c
620+++ b/mt7915/testmode.c
621@@ -9,6 +9,9 @@
622 enum {
623 TM_CHANGED_TXPOWER,
624 TM_CHANGED_FREQ_OFFSET,
625+ TM_CHANGED_AID,
626+ TM_CHANGED_CFG,
627+ TM_CHANGED_TXBF_ACT,
628
629 /* must be last */
630 NUM_TM_CHANGED
631@@ -17,6 +20,9 @@ enum {
632 static const u8 tm_change_map[] = {
633 [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
634 [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
635+ [TM_CHANGED_AID] = MT76_TM_ATTR_AID,
636+ [TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
637+ [TM_CHANGED_TXBF_ACT] = MT76_TM_ATTR_TXBF_ACT,
638 };
639
640 struct reg_band {
developerc6f56bb2022-06-14 18:36:30 +0800641@@ -33,6 +39,38 @@ struct reg_band {
developer4c6b6002022-05-30 16:36:44 +0800642 #define TM_REG_MAX_ID 20
643 static struct reg_band reg_backup_list[TM_REG_MAX_ID];
644
developerc6f56bb2022-06-14 18:36:30 +0800645+static void mt7915_tm_update_entry(struct mt7915_phy *phy);
646+
developer4c6b6002022-05-30 16:36:44 +0800647+static u8 mt7915_tm_chan_bw(enum nl80211_chan_width width)
648+{
649+ static const u8 width_to_bw[] = {
650+ [NL80211_CHAN_WIDTH_40] = TM_CBW_40MHZ,
651+ [NL80211_CHAN_WIDTH_80] = TM_CBW_80MHZ,
652+ [NL80211_CHAN_WIDTH_80P80] = TM_CBW_8080MHZ,
653+ [NL80211_CHAN_WIDTH_160] = TM_CBW_160MHZ,
654+ [NL80211_CHAN_WIDTH_5] = TM_CBW_5MHZ,
655+ [NL80211_CHAN_WIDTH_10] = TM_CBW_10MHZ,
656+ [NL80211_CHAN_WIDTH_20] = TM_CBW_20MHZ,
657+ [NL80211_CHAN_WIDTH_20_NOHT] = TM_CBW_20MHZ,
658+ };
659+
660+ if (width >= ARRAY_SIZE(width_to_bw))
661+ return 0;
662+
663+ return width_to_bw[width];
664+}
665+
666+static void
667+mt7915_tm_update_channel(struct mt7915_phy *phy)
668+{
669+ mutex_unlock(&phy->dev->mt76.mutex);
670+ mt7915_set_channel(phy);
671+ mutex_lock(&phy->dev->mt76.mutex);
672+
673+ mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
developerc6f56bb2022-06-14 18:36:30 +0800674+
675+ mt7915_tm_update_entry(phy);
developer4c6b6002022-05-30 16:36:44 +0800676+}
677
678 static int
679 mt7915_tm_set_tx_power(struct mt7915_phy *phy)
developerc6f56bb2022-06-14 18:36:30 +0800680@@ -119,18 +157,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
developer4c6b6002022-05-30 16:36:44 +0800681 }
682
683 static int
684-mt7915_tm_clean_hwq(struct mt7915_phy *phy, u8 wcid)
685+mt7915_tm_clean_hwq(struct mt7915_phy *phy)
686 {
687+ struct mt76_testmode_entry_data *ed;
688+ struct mt76_wcid *wcid;
689 struct mt7915_dev *dev = phy->dev;
690 struct mt7915_tm_cmd req = {
691 .testmode_en = 1,
692 .param_idx = MCU_ATE_CLEAN_TXQUEUE,
693- .param.clean.wcid = wcid,
developereb6a0182022-12-12 18:53:32 +0800694 .param.clean.band = phy->mt76->band_idx,
developer4c6b6002022-05-30 16:36:44 +0800695 };
696
697- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
698- sizeof(req), false);
699+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
700+ int ret;
701+
702+ req.param.clean.wcid = wcid->idx;
703+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL),
704+ &req, sizeof(req), false);
705+ if (ret)
706+ return ret;
707+ }
708+
709+ return 0;
710 }
711
712 static int
developereb6a0182022-12-12 18:53:32 +0800713@@ -141,7 +189,7 @@ mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control)
714 .testmode_en = 1,
715 .param_idx = MCU_ATE_SET_PHY_COUNT,
716 .param.cfg.enable = control,
717- .param.cfg.band = phy != &dev->phy,
718+ .param.cfg.band = phy->mt76->band_idx,
719 };
720
721 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
developerf64861f2022-06-22 11:44:53 +0800722@@ -182,12 +230,738 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
developer4c6b6002022-05-30 16:36:44 +0800723 return mt7915_mcu_set_muru_ctrl(dev, MURU_SET_ARB_OP_MODE, op_mode);
724 }
725
726+static int
727+mt7915_tm_set_cfg(struct mt7915_phy *phy)
728+{
729+ static const u8 cfg_cmd[] = {
730+ [MT76_TM_CFG_TSSI] = MCU_ATE_SET_TSSI,
731+ [MT76_TM_CFG_DPD] = MCU_ATE_SET_DPD,
732+ [MT76_TM_CFG_RATE_POWER_OFFSET] = MCU_ATE_SET_RATE_POWER_OFFSET,
733+ [MT76_TM_CFG_THERMAL_COMP] = MCU_ATE_SET_THERMAL_COMP,
734+ };
735+ struct mt76_testmode_data *td = &phy->mt76->test;
736+ struct mt7915_dev *dev = phy->dev;
737+ struct mt7915_tm_cmd req = {
738+ .testmode_en = !(phy->mt76->test.state == MT76_TM_STATE_OFF),
739+ .param_idx = cfg_cmd[td->cfg.type],
740+ .param.cfg.enable = td->cfg.enable,
developereb6a0182022-12-12 18:53:32 +0800741+ .param.cfg.band = phy->mt76->band_idx,
developer4c6b6002022-05-30 16:36:44 +0800742+ };
743+
744+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
745+ sizeof(req), false);
746+}
747+
748+static int
749+mt7915_tm_add_txbf(struct mt7915_phy *phy, struct ieee80211_vif *vif,
750+ struct ieee80211_sta *sta, u8 pfmu_idx, u8 nr,
751+ u8 nc, bool ebf)
752+{
753+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
754+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
755+ struct mt7915_dev *dev = phy->dev;
756+ struct sk_buff *skb;
757+ struct sta_rec_bf *bf;
758+ struct tlv *tlv;
759+ u8 ndp_rate;
760+
761+ if (nr == 1)
762+ ndp_rate = 8;
763+ else if (nr == 2)
764+ ndp_rate = 16;
765+ else
766+ ndp_rate = 24;
767+
768+ skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
769+ &msta->wcid);
770+ if (IS_ERR(skb))
771+ return PTR_ERR(skb);
772+
773+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
774+ bf = (struct sta_rec_bf *)tlv;
775+
776+ bf->pfmu = cpu_to_le16(pfmu_idx);
777+ bf->sounding_phy = 1;
778+ bf->bf_cap = ebf;
779+ bf->ncol = nc;
780+ bf->nrow = nr;
781+ bf->ndp_rate = ndp_rate;
782+ bf->ibf_timeout = 0xff;
783+ bf->tx_mode = MT_PHY_TYPE_HT;
784+
785+ if (ebf) {
786+ bf->mem[0].row = 0;
787+ bf->mem[1].row = 1;
788+ bf->mem[2].row = 2;
789+ bf->mem[3].row = 3;
790+ } else {
791+ bf->mem[0].row = 4;
792+ bf->mem[1].row = 5;
793+ bf->mem[2].row = 6;
794+ bf->mem[3].row = 7;
795+ }
796+
797+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
798+ MCU_EXT_CMD(STA_REC_UPDATE), true);
799+}
800+
801+static int
802+mt7915_tm_entry_add(struct mt7915_phy *phy, u8 aid)
803+{
804+ struct mt76_testmode_data *td = &phy->mt76->test;
805+ struct mt76_testmode_entry_data *ed;
806+ struct ieee80211_sband_iftype_data *sdata;
807+ struct ieee80211_supported_band *sband;
808+ struct ieee80211_sta *sta;
809+ struct mt7915_sta *msta;
810+ int tid, ret;
811+
812+ if (td->entry_num >= MT76_TM_MAX_ENTRY_NUM)
813+ return -EINVAL;
814+
815+ sta = kzalloc(sizeof(*sta) + phy->mt76->hw->sta_data_size +
816+ sizeof(*ed), GFP_KERNEL);
817+ if (!sta)
818+ return -ENOMEM;
819+
820+ msta = (struct mt7915_sta *)sta->drv_priv;
821+ ed = mt76_testmode_entry_data(phy->mt76, &msta->wcid);
822+ memcpy(ed, &td->ed, sizeof(*ed));
823+
824+ if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) {
825+ sband = &phy->mt76->sband_5g.sband;
826+ sdata = phy->iftype[NL80211_BAND_5GHZ];
827+ } else if (phy->mt76->chandef.chan->band == NL80211_BAND_6GHZ) {
828+ sband = &phy->mt76->sband_6g.sband;
829+ sdata = phy->iftype[NL80211_BAND_6GHZ];
830+ } else {
831+ sband = &phy->mt76->sband_2g.sband;
832+ sdata = phy->iftype[NL80211_BAND_2GHZ];
833+ }
834+
835+ memcpy(sta->addr, ed->addr[0], ETH_ALEN);
836+ if (phy->test.bf_en) {
837+ u8 addr[ETH_ALEN] = {0x00, 0x11, 0x11, 0x11, 0x11, 0x11};
838+
839+ memcpy(sta->addr, addr, ETH_ALEN);
840+ }
841+
842+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_HT)
developereb6a0182022-12-12 18:53:32 +0800843+ memcpy(&sta->deflink.ht_cap, &sband->ht_cap, sizeof(sta->deflink.ht_cap));
developer4c6b6002022-05-30 16:36:44 +0800844+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_VHT)
developereb6a0182022-12-12 18:53:32 +0800845+ memcpy(&sta->deflink.vht_cap, &sband->vht_cap, sizeof(sta->deflink.vht_cap));
developer4c6b6002022-05-30 16:36:44 +0800846+ if (td->tx_rate_mode >= MT76_TM_TX_MODE_HE_SU)
developereb6a0182022-12-12 18:53:32 +0800847+ memcpy(&sta->deflink.he_cap, &sdata[NL80211_IFTYPE_STATION].he_cap,
848+ sizeof(sta->deflink.he_cap));
developer4c6b6002022-05-30 16:36:44 +0800849+ sta->aid = aid;
850+ sta->wme = 1;
851+
852+ ret = mt7915_mac_sta_add(&phy->dev->mt76, phy->monitor_vif, sta);
853+ if (ret) {
854+ kfree(sta);
855+ return ret;
856+ }
857+
858+ /* prevent from starting tx ba session */
859+ for (tid = 0; tid < 8; tid++)
860+ set_bit(tid, &msta->ampdu_state);
861+
862+ list_add_tail(&msta->wcid.list, &td->tm_entry_list);
863+ td->entry_num++;
864+
865+ return 0;
866+}
867+
868+static void
869+mt7915_tm_entry_remove(struct mt7915_phy *phy, u8 aid)
870+{
871+ struct mt76_testmode_data *td = &phy->mt76->test;
872+ struct mt76_wcid *wcid, *tmp;
873+
874+ if (list_empty(&td->tm_entry_list))
875+ return;
876+
877+ list_for_each_entry_safe(wcid, tmp, &td->tm_entry_list, list) {
developerc6f56bb2022-06-14 18:36:30 +0800878+ struct mt76_testmode_entry_data *ed;
developer4c6b6002022-05-30 16:36:44 +0800879+ struct mt7915_dev *dev = phy->dev;
developerc6f56bb2022-06-14 18:36:30 +0800880+ struct ieee80211_sta *sta;
developer4c6b6002022-05-30 16:36:44 +0800881+
developerc6f56bb2022-06-14 18:36:30 +0800882+ ed = mt76_testmode_entry_data(phy->mt76, wcid);
883+ if (aid && ed->aid != aid)
884+ continue;
885+
886+ sta = wcid_to_sta(wcid);
developer4c6b6002022-05-30 16:36:44 +0800887+ mt7915_mac_sta_remove(&dev->mt76, phy->monitor_vif, sta);
888+ mt76_wcid_mask_clear(dev->mt76.wcid_mask, wcid->idx);
889+
890+ list_del_init(&wcid->list);
891+ kfree(sta);
892+ phy->mt76->test.entry_num--;
893+ }
894+}
895+
896+static int
897+mt7915_tm_set_entry(struct mt7915_phy *phy)
898+{
899+ struct mt76_testmode_data *td = &phy->mt76->test;
900+ struct mt76_testmode_entry_data *ed;
901+ struct mt76_wcid *wcid;
902+
903+ if (!td->aid) {
904+ if (td->state > MT76_TM_STATE_IDLE)
905+ mt76_testmode_set_state(phy->mt76, MT76_TM_STATE_IDLE);
906+ mt7915_tm_entry_remove(phy, td->aid);
907+ return 0;
908+ }
909+
910+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
911+ if (ed->aid == td->aid) {
912+ struct sk_buff *skb;
913+
914+ local_bh_disable();
915+ skb = ed->tx_skb;
916+ memcpy(ed, &td->ed, sizeof(*ed));
917+ ed->tx_skb = skb;
918+ local_bh_enable();
919+
920+ return 0;
921+ }
922+ }
923+
924+ return mt7915_tm_entry_add(phy, td->aid);
925+}
926+
developerc6f56bb2022-06-14 18:36:30 +0800927+static void
928+mt7915_tm_update_entry(struct mt7915_phy *phy)
929+{
930+ struct mt76_testmode_data *td = &phy->mt76->test;
931+ struct mt76_testmode_entry_data *ed, tmp;
932+ struct mt76_wcid *wcid, *last;
933+
934+ if (!td->aid || phy->test.bf_en)
935+ return;
936+
937+ memcpy(&tmp, &td->ed, sizeof(tmp));
938+ last = list_last_entry(&td->tm_entry_list,
939+ struct mt76_wcid, list);
940+
941+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
942+ memcpy(&td->ed, ed, sizeof(td->ed));
943+ mt7915_tm_entry_remove(phy, td->aid);
944+ mt7915_tm_entry_add(phy, td->aid);
945+ if (wcid == last)
946+ break;
947+ }
948+
949+ memcpy(&td->ed, &tmp, sizeof(td->ed));
950+}
951+
developer4c6b6002022-05-30 16:36:44 +0800952+static int
953+mt7915_tm_txbf_init(struct mt7915_phy *phy, u16 *val)
954+{
955+ struct mt76_testmode_data *td = &phy->mt76->test;
956+ struct mt7915_dev *dev = phy->dev;
957+ bool enable = val[0];
958+ void *phase_cal, *pfmu_data, *pfmu_tag;
959+ u8 addr[ETH_ALEN] = {0x00, 0x22, 0x22, 0x22, 0x22, 0x22};
960+
961+ if (!enable) {
962+ phy->test.bf_en = 0;
963+ return 0;
964+ }
965+
966+ if (!dev->test.txbf_phase_cal) {
967+ phase_cal = devm_kzalloc(dev->mt76.dev,
968+ sizeof(struct mt7915_tm_txbf_phase) *
969+ MAX_PHASE_GROUP_NUM,
970+ GFP_KERNEL);
971+ if (!phase_cal)
972+ return -ENOMEM;
973+
974+ dev->test.txbf_phase_cal = phase_cal;
975+ }
976+
977+ if (!dev->test.txbf_pfmu_data) {
978+ pfmu_data = devm_kzalloc(dev->mt76.dev, 512, GFP_KERNEL);
979+ if (!pfmu_data)
980+ return -ENOMEM;
981+
982+ dev->test.txbf_pfmu_data = pfmu_data;
983+ }
984+
985+ if (!dev->test.txbf_pfmu_tag) {
986+ pfmu_tag = devm_kzalloc(dev->mt76.dev,
987+ sizeof(struct mt7915_tm_pfmu_tag), GFP_KERNEL);
988+ if (!pfmu_tag)
989+ return -ENOMEM;
990+
991+ dev->test.txbf_pfmu_tag = pfmu_tag;
992+ }
993+
994+ memcpy(phy->monitor_vif->addr, addr, ETH_ALEN);
995+ mt7915_mcu_add_dev_info(phy, phy->monitor_vif, true);
996+
997+ td->tx_rate_mode = MT76_TM_TX_MODE_HT;
998+ td->tx_mpdu_len = 1024;
999+ td->tx_rate_sgi = 0;
1000+ td->tx_ipg = 100;
1001+ phy->test.bf_en = 1;
1002+
1003+ return mt7915_tm_set_trx(phy, TM_MAC_TX, true);
1004+}
1005+
1006+static int
1007+mt7915_tm_txbf_phase_comp(struct mt7915_phy *phy, u16 *val)
1008+{
1009+ struct mt7915_dev *dev = phy->dev;
1010+ struct {
1011+ u8 category;
1012+ u8 wlan_idx_lo;
1013+ u8 bw;
1014+ u8 jp_band;
1015+ u8 dbdc_idx;
1016+ bool read_from_e2p;
1017+ bool disable;
1018+ u8 wlan_idx_hi;
1019+ u8 buf[40];
1020+ } __packed req = {
1021+ .category = MT_BF_IBF_PHASE_COMP,
1022+ .bw = val[0],
1023+ .jp_band = (val[2] == 1) ? 1 : 0,
developereb6a0182022-12-12 18:53:32 +08001024+ .dbdc_idx = phy->mt76->band_idx,
developer4c6b6002022-05-30 16:36:44 +08001025+ .read_from_e2p = val[3],
1026+ .disable = val[4],
1027+ };
1028+ struct mt7915_tm_txbf_phase *phase =
1029+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1030+
1031+ wait_event_timeout(dev->mt76.tx_wait, phase[val[2]].status != 0, HZ);
1032+ memcpy(req.buf, &phase[val[2]].phase, sizeof(req.buf));
1033+
1034+ pr_info("ibf cal process: phase comp info\n");
1035+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
1036+ &req, sizeof(req), 0);
1037+
1038+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1039+ sizeof(req), true);
1040+}
1041+
1042+static int
1043+mt7915_tm_txbf_profile_tag_read(struct mt7915_phy *phy, u8 pfmu_idx)
1044+{
1045+ struct mt7915_dev *dev = phy->dev;
1046+ struct {
1047+ u8 format_id;
1048+ u8 pfmu_idx;
1049+ bool bfer;
1050+ u8 dbdc_idx;
1051+ } __packed req = {
1052+ .format_id = MT_BF_PFMU_TAG_READ,
1053+ .pfmu_idx = pfmu_idx,
1054+ .bfer = 1,
1055+ .dbdc_idx = phy != &dev->phy,
1056+ };
1057+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
1058+
1059+ tag->t1.pfmu_idx = 0;
1060+
1061+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1062+ sizeof(req), true);
1063+}
1064+
1065+static int
1066+mt7915_tm_txbf_profile_tag_write(struct mt7915_phy *phy, u8 pfmu_idx,
1067+ struct mt7915_tm_pfmu_tag *tag)
1068+{
1069+ struct mt7915_dev *dev = phy->dev;
1070+ struct {
1071+ u8 format_id;
1072+ u8 pfmu_idx;
1073+ bool bfer;
1074+ u8 dbdc_idx;
1075+ u8 buf[64];
1076+ } __packed req = {
1077+ .format_id = MT_BF_PFMU_TAG_WRITE,
1078+ .pfmu_idx = pfmu_idx,
1079+ .bfer = 1,
1080+ .dbdc_idx = phy != &dev->phy,
1081+ };
1082+
1083+ memcpy(req.buf, tag, sizeof(*tag));
1084+ wait_event_timeout(dev->mt76.tx_wait, tag->t1.pfmu_idx != 0, HZ);
1085+
1086+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1087+ sizeof(req), false);
1088+}
1089+
1090+static int
1091+mt7915_tm_txbf_apply_tx(struct mt7915_phy *phy, u16 wlan_idx, bool ebf,
1092+ bool ibf, bool phase_cal)
1093+{
1094+#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
1095+#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
1096+ struct mt7915_dev *dev = phy->dev;
1097+ struct {
1098+ u8 category;
1099+ u8 wlan_idx_lo;
1100+ bool ebf;
1101+ bool ibf;
1102+ bool mu_txbf;
1103+ bool phase_cal;
1104+ u8 wlan_idx_hi;
1105+ u8 _rsv;
1106+ } __packed req = {
1107+ .category = MT_BF_DATA_PACKET_APPLY,
1108+ .wlan_idx_lo = to_wcid_lo(wlan_idx),
1109+ .ebf = ebf,
1110+ .ibf = ibf,
1111+ .phase_cal = phase_cal,
1112+ .wlan_idx_hi = to_wcid_hi(wlan_idx),
1113+ };
1114+
1115+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1116+ sizeof(req), false);
1117+}
1118+
1119+static int mt7915_tm_txbf_set_rate(struct mt7915_phy *phy,
1120+ struct mt76_wcid *wcid)
1121+{
1122+ struct mt7915_dev *dev = phy->dev;
1123+ struct mt76_testmode_entry_data *ed = mt76_testmode_entry_data(phy->mt76, wcid);
1124+ struct ieee80211_sta *sta = wcid_to_sta(wcid);
1125+ struct sta_phy rate = {};
1126+
1127+ if (!sta)
1128+ return 0;
1129+
1130+ rate.type = MT_PHY_TYPE_HT;
1131+ rate.bw = mt7915_tm_chan_bw(phy->mt76->chandef.width);
1132+ rate.nss = ed->tx_rate_nss;
1133+ rate.mcs = ed->tx_rate_idx;
1134+ rate.ldpc = (rate.bw || ed->tx_rate_ldpc) * GENMASK(2, 0);
1135+
1136+ return mt7915_mcu_set_fixed_rate_ctrl(dev, phy->monitor_vif, sta,
1137+ &rate, RATE_PARAM_FIXED);
1138+}
1139+
1140+static int
1141+mt7915_tm_txbf_set_tx(struct mt7915_phy *phy, u16 *val)
1142+{
1143+ bool bf_on = val[0], update = val[3];
1144+ /* u16 wlan_idx = val[2]; */
1145+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
1146+ struct mt76_testmode_data *td = &phy->mt76->test;
1147+ struct mt76_wcid *wcid;
1148+
1149+ if (bf_on) {
1150+ mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1151+ mt7915_tm_txbf_profile_tag_read(phy, 2);
1152+ tag->t1.invalid_prof = false;
1153+ mt7915_tm_txbf_profile_tag_write(phy, 2, tag);
1154+
1155+ phy->test.bf_ever_en = true;
1156+
1157+ if (update)
1158+ mt7915_tm_txbf_apply_tx(phy, 1, 0, 1, 1);
1159+ } else {
1160+ if (!phy->test.bf_ever_en) {
1161+ if (update)
1162+ mt7915_tm_txbf_apply_tx(phy, 1, 0, 0, 0);
1163+ } else {
1164+ phy->test.bf_ever_en = false;
1165+
1166+ mt7915_tm_txbf_profile_tag_read(phy, 2);
1167+ tag->t1.invalid_prof = true;
1168+ mt7915_tm_txbf_profile_tag_write(phy, 2, tag);
1169+ }
1170+ }
1171+
1172+ wcid = list_first_entry(&td->tm_entry_list, struct mt76_wcid, list);
1173+ mt7915_tm_txbf_set_rate(phy, wcid);
1174+
1175+ return 0;
1176+}
1177+
1178+static int
1179+mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
1180+{
1181+ static const u8 mode_to_lm[] = {
1182+ [MT76_TM_TX_MODE_CCK] = 0,
1183+ [MT76_TM_TX_MODE_OFDM] = 0,
1184+ [MT76_TM_TX_MODE_HT] = 1,
1185+ [MT76_TM_TX_MODE_VHT] = 2,
1186+ [MT76_TM_TX_MODE_HE_SU] = 3,
1187+ [MT76_TM_TX_MODE_HE_EXT_SU] = 3,
1188+ [MT76_TM_TX_MODE_HE_TB] = 3,
1189+ [MT76_TM_TX_MODE_HE_MU] = 3,
1190+ };
1191+ struct mt76_testmode_data *td = &phy->mt76->test;
1192+ struct mt76_wcid *wcid;
1193+ struct ieee80211_vif *vif = phy->monitor_vif;
1194+ struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
1195+ u8 pfmu_idx = val[0], nc = val[2], nr;
1196+ int ret;
1197+
1198+ if (td->tx_antenna_mask == 3)
1199+ nr = 1;
1200+ else if (td->tx_antenna_mask == 7)
1201+ nr = 2;
1202+ else
1203+ nr = 3;
1204+
1205+ memset(tag, 0, sizeof(*tag));
1206+ tag->t1.pfmu_idx = pfmu_idx;
1207+ tag->t1.ebf = ebf;
1208+ tag->t1.nr = nr;
1209+ tag->t1.nc = nc;
1210+ tag->t1.invalid_prof = true;
1211+
1212+ tag->t1.snr_sts4 = 0xc0;
1213+ tag->t1.snr_sts5 = 0xff;
1214+ tag->t1.snr_sts6 = 0xff;
1215+ tag->t1.snr_sts7 = 0xff;
1216+
1217+ if (ebf) {
1218+ tag->t1.row_id1 = 0;
1219+ tag->t1.row_id2 = 1;
1220+ tag->t1.row_id3 = 2;
1221+ tag->t1.row_id4 = 3;
1222+ tag->t1.lm = mode_to_lm[MT76_TM_TX_MODE_HT];
1223+ } else {
1224+ tag->t1.row_id1 = 4;
1225+ tag->t1.row_id2 = 5;
1226+ tag->t1.row_id3 = 6;
1227+ tag->t1.row_id4 = 7;
1228+ tag->t1.lm = mode_to_lm[MT76_TM_TX_MODE_OFDM];
1229+
1230+ tag->t2.ibf_timeout = 0xff;
1231+ tag->t2.ibf_nr = nr;
1232+ }
1233+
1234+ ret = mt7915_tm_txbf_profile_tag_write(phy, pfmu_idx, tag);
1235+ if (ret)
1236+ return ret;
1237+
1238+ wcid = list_first_entry(&td->tm_entry_list, struct mt76_wcid, list);
1239+ ret = mt7915_tm_add_txbf(phy, vif, wcid_to_sta(wcid), pfmu_idx, nr, nc, ebf);
1240+ if (ret)
1241+ return ret;
1242+
1243+ if (!ebf)
1244+ return mt7915_tm_txbf_apply_tx(phy, 1, false, true, true);
1245+
1246+ return 0;
1247+}
1248+
1249+static int
1250+mt7915_tm_txbf_phase_cal(struct mt7915_phy *phy, u16 *val)
1251+{
1252+#define GROUP_L 0
1253+#define GROUP_M 1
1254+#define GROUP_H 2
1255+ struct mt7915_dev *dev = phy->dev;
1256+ struct {
1257+ u8 category;
1258+ u8 group_l_m_n;
1259+ u8 group;
1260+ bool sx2;
1261+ u8 cal_type;
1262+ u8 lna_gain_level;
1263+ u8 _rsv[2];
1264+ } __packed req = {
1265+ .category = MT_BF_PHASE_CAL,
1266+ .group = val[0],
1267+ .group_l_m_n = val[1],
1268+ .sx2 = val[2],
1269+ .cal_type = val[3],
1270+ .lna_gain_level = 0, /* for test purpose */
1271+ };
1272+ struct mt7915_tm_txbf_phase *phase =
1273+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1274+
1275+ phase[req.group].status = 0;
1276+
1277+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
1278+ sizeof(req), true);
1279+}
1280+
1281+int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb)
1282+{
1283+#define BF_PFMU_TAG 16
1284+#define BF_CAL_PHASE 21
1285+ u8 format_id;
1286+
developerf64861f2022-06-22 11:44:53 +08001287+ skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
developer4c6b6002022-05-30 16:36:44 +08001288+ format_id = *(u8 *)skb->data;
1289+
1290+ if (format_id == BF_PFMU_TAG) {
1291+ struct mt7915_tm_pfmu_tag *tag = dev->test.txbf_pfmu_tag;
1292+
1293+ skb_pull(skb, 8);
1294+ memcpy(tag, skb->data, sizeof(struct mt7915_tm_pfmu_tag));
1295+ } else if (format_id == BF_CAL_PHASE) {
1296+ struct mt7915_tm_ibf_cal_info *cal;
1297+ struct mt7915_tm_txbf_phase *phase =
1298+ (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1299+
1300+ cal = (struct mt7915_tm_ibf_cal_info *)skb->data;
1301+ switch (cal->cal_type) {
1302+ case IBF_PHASE_CAL_NORMAL:
1303+ case IBF_PHASE_CAL_NORMAL_INSTRUMENT:
1304+ if (cal->group_l_m_n != GROUP_M)
1305+ break;
1306+ phase = &phase[cal->group];
1307+ memcpy(&phase->phase, cal->buf + 16, sizeof(phase->phase));
1308+ phase->status = cal->status;
1309+ break;
1310+ case IBF_PHASE_CAL_VERIFY:
1311+ case IBF_PHASE_CAL_VERIFY_INSTRUMENT:
1312+ break;
1313+ default:
1314+ break;
1315+ }
1316+ }
1317+
1318+ wake_up(&dev->mt76.tx_wait);
1319+
1320+ return 0;
1321+}
1322+
1323+static int
1324+mt7915_tm_txbf_profile_update_all(struct mt7915_phy *phy, u16 *val)
1325+{
1326+ struct mt76_testmode_data *td = &phy->mt76->test;
1327+ u16 pfmu_idx = val[0];
1328+ u16 subc_id = val[1];
1329+ u16 angle11 = val[2];
1330+ u16 angle21 = val[3];
1331+ u16 angle31 = val[4];
1332+ u16 angle41 = val[5];
1333+ s16 phi11 = 0, phi21 = 0, phi31 = 0;
1334+ struct mt7915_tm_pfmu_data *pfmu_data;
1335+
1336+ if (subc_id > 63)
1337+ return -EINVAL;
1338+
1339+ if (td->tx_antenna_mask == 2) {
1340+ phi11 = (s16)(angle21 - angle11);
1341+ } else if (td->tx_antenna_mask == 3) {
1342+ phi11 = (s16)(angle31 - angle11);
1343+ phi21 = (s16)(angle31 - angle21);
1344+ } else {
1345+ phi11 = (s16)(angle41 - angle11);
1346+ phi21 = (s16)(angle41 - angle21);
1347+ phi31 = (s16)(angle41 - angle31);
1348+ }
1349+
1350+ pfmu_data = (struct mt7915_tm_pfmu_data *)phy->dev->test.txbf_pfmu_data;
1351+ pfmu_data = &pfmu_data[subc_id];
1352+
1353+ if (subc_id < 32)
1354+ pfmu_data->subc_idx = cpu_to_le16(subc_id + 224);
1355+ else
1356+ pfmu_data->subc_idx = cpu_to_le16(subc_id - 32);
1357+ pfmu_data->phi11 = cpu_to_le16(phi11);
1358+ pfmu_data->phi21 = cpu_to_le16(phi21);
1359+ pfmu_data->phi31 = cpu_to_le16(phi31);
1360+
1361+ if (subc_id == 63) {
1362+ struct mt7915_dev *dev = phy->dev;
1363+ struct {
1364+ u8 format_id;
1365+ u8 pfmu_idx;
1366+ u8 dbdc_idx;
1367+ u8 _rsv;
1368+ u8 buf[512];
1369+ } __packed req = {
1370+ .format_id = MT_BF_PROFILE_WRITE_ALL,
1371+ .pfmu_idx = pfmu_idx,
1372+ .dbdc_idx = phy != &dev->phy,
1373+ };
1374+
1375+ memcpy(req.buf, dev->test.txbf_pfmu_data, 512);
1376+
1377+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION),
1378+ &req, sizeof(req), true);
1379+ }
1380+
1381+ return 0;
1382+}
1383+
1384+static int
1385+mt7915_tm_txbf_e2p_update(struct mt7915_phy *phy)
1386+{
1387+ struct mt7915_tm_txbf_phase *phase, *p;
1388+ struct mt7915_dev *dev = phy->dev;
1389+ u8 *eeprom = dev->mt76.eeprom.data;
1390+ u16 offset;
1391+ bool is_7976;
1392+ int i;
1393+
1394+ is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
1395+ offset = is_7976 ? 0x60a : 0x651;
1396+
1397+ phase = (struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
1398+ for (i = 0; i < MAX_PHASE_GROUP_NUM; i++) {
1399+ p = &phase[i];
1400+
1401+ if (!p->status)
1402+ continue;
1403+
1404+ /* copy phase cal data to eeprom */
1405+ memcpy(eeprom + offset + i * sizeof(p->phase), &p->phase,
1406+ sizeof(p->phase));
1407+ }
1408+
1409+ return 0;
1410+}
1411+
1412+static int
1413+mt7915_tm_set_txbf(struct mt7915_phy *phy)
1414+{
1415+ struct mt76_testmode_data *td = &phy->mt76->test;
1416+ u16 *val = td->txbf_param;
1417+
1418+ pr_info("ibf cal process: act = %u, val = %u, %u, %u, %u, %u\n",
1419+ td->txbf_act, val[0], val[1], val[2], val[3], val[4]);
1420+
1421+ switch (td->txbf_act) {
1422+ case MT76_TM_TXBF_ACT_INIT:
1423+ return mt7915_tm_txbf_init(phy, val);
1424+ case MT76_TM_TXBF_ACT_UPDATE_CH:
1425+ mt7915_tm_update_channel(phy);
1426+ break;
1427+ case MT76_TM_TXBF_ACT_PHASE_COMP:
1428+ return mt7915_tm_txbf_phase_comp(phy, val);
1429+ case MT76_TM_TXBF_ACT_TX_PREP:
1430+ return mt7915_tm_txbf_set_tx(phy, val);
1431+ case MT76_TM_TXBF_ACT_IBF_PROF_UPDATE:
1432+ return mt7915_tm_txbf_profile_update(phy, val, false);
1433+ case MT76_TM_TXBF_ACT_EBF_PROF_UPDATE:
1434+ return mt7915_tm_txbf_profile_update(phy, val, true);
1435+ case MT76_TM_TXBF_ACT_PHASE_CAL:
1436+ return mt7915_tm_txbf_phase_cal(phy, val);
1437+ case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL:
1438+ return mt7915_tm_txbf_profile_update_all(phy, val);
1439+ case MT76_TM_TXBF_ACT_E2P_UPDATE:
1440+ return mt7915_tm_txbf_e2p_update(phy);
1441+ default:
1442+ break;
1443+ };
1444+
1445+ return 0;
1446+}
1447+
1448 static int
developerf64861f2022-06-22 11:44:53 +08001449 mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min,
developer4c6b6002022-05-30 16:36:44 +08001450- u16 cw_max, u16 txop)
1451+ u16 cw_max, u16 txop, u8 tx_cmd)
1452 {
developerf64861f2022-06-22 11:44:53 +08001453 struct mt7915_vif *mvif = (struct mt7915_vif *)phy->monitor_vif->drv_priv;
developer4c6b6002022-05-30 16:36:44 +08001454- struct mt7915_mcu_tx req = { .total = 1 };
1455+ struct mt7915_mcu_tx req = {
1456+ .valid = true,
1457+ .mode = tx_cmd,
1458+ .total = 1,
1459+ };
1460 struct edca *e = &req.edca[0];
1461
developerf64861f2022-06-22 11:44:53 +08001462 e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
developereb6a0182022-12-12 18:53:32 +08001463@@ -263,7 +1037,8 @@ done:
developer4c6b6002022-05-30 16:36:44 +08001464
developerf64861f2022-06-22 11:44:53 +08001465 return mt7915_tm_set_wmm_qid(phy,
developer4c6b6002022-05-30 16:36:44 +08001466 mt76_connac_lmac_mapping(IEEE80211_AC_BE),
1467- aifsn, cw, cw, 0);
1468+ aifsn, cw, cw, 0,
1469+ mode == MT76_TM_TX_MODE_HE_MU);
1470 }
1471
1472 static int
developereb6a0182022-12-12 18:53:32 +08001473@@ -339,7 +1114,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
developer4c6b6002022-05-30 16:36:44 +08001474 bitrate = cfg80211_calculate_bitrate(&rate);
1475 tx_len = bitrate * tx_time / 10 / 8;
1476
1477- ret = mt76_testmode_alloc_skb(phy->mt76, tx_len);
1478+ ret = mt76_testmode_init_skb(phy->mt76, tx_len, &td->tx_skb, td->addr);
1479 if (ret)
1480 return ret;
1481
developereb6a0182022-12-12 18:53:32 +08001482@@ -458,64 +1233,227 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001483
1484 phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
1485
1486- if (!en)
1487+ if (!en) {
1488 mt7915_tm_set_tam_arb(phy, en, 0);
1489+
1490+ phy->mt76->test.aid = 0;
1491+ phy->mt76->test.tx_mpdu_len = 0;
1492+ phy->test.bf_en = 0;
1493+ mt7915_tm_set_entry(phy);
1494+ }
1495+}
1496+
1497+static bool
1498+mt7915_tm_check_skb(struct mt7915_phy *phy)
1499+{
1500+ struct mt76_testmode_entry_data *ed;
1501+ struct mt76_wcid *wcid;
1502+
1503+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
1504+ struct ieee80211_tx_info *info;
1505+
1506+ if (!ed->tx_skb)
1507+ return false;
1508+
1509+ info = IEEE80211_SKB_CB(ed->tx_skb);
1510+ info->control.vif = phy->monitor_vif;
1511+ }
1512+
1513+ return true;
1514+}
1515+
1516+static int
1517+mt7915_tm_set_ba(struct mt7915_phy *phy)
1518+{
1519+ struct mt7915_dev *dev = phy->dev;
1520+ struct mt76_testmode_data *td = &phy->mt76->test;
1521+ struct mt76_wcid *wcid;
1522+ struct ieee80211_vif *vif = phy->monitor_vif;
1523+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1524+ struct ieee80211_ampdu_params params = { .buf_size = 256 };
1525+
1526+ list_for_each_entry(wcid, &td->tm_entry_list, list) {
1527+ int tid, ret;
1528+
1529+ params.sta = wcid_to_sta(wcid);
1530+ for (tid = 0; tid < 8; tid++) {
1531+ params.tid = tid;
1532+ ret = mt7915_mcu_add_tx_ba(phy->dev, &params, true);
1533+ if (ret)
1534+ return ret;
1535+ }
1536+ }
1537+
1538+ mt76_wr(dev, MT_AGG_AALCR0(mvif->mt76.band_idx, mvif->mt76.wmm_idx),
1539+ 0x01010101);
1540+
1541+ return 0;
1542+}
1543+
1544+static int
1545+mt7915_tm_set_muru_cfg(struct mt7915_phy *phy, struct mt7915_tm_muru *muru)
1546+{
1547+/* #define MURU_SET_MANUAL_CFG 100 */
1548+ struct mt7915_dev *dev = phy->dev;
1549+ struct {
1550+ __le32 cmd;
1551+ struct mt7915_tm_muru muru;
1552+ } __packed req = {
1553+ .cmd = cpu_to_le32(MURU_SET_MANUAL_CFG),
1554+ };
1555+
1556+ memcpy(&req.muru, muru, sizeof(struct mt7915_tm_muru));
1557+
1558+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1559+ sizeof(req), false);
1560+}
1561+
1562+static int
1563+mt7915_tm_set_muru_dl(struct mt7915_phy *phy)
1564+{
1565+ struct mt76_testmode_data *td = &phy->mt76->test;
1566+ struct mt76_testmode_entry_data *ed;
1567+ struct mt76_wcid *wcid;
1568+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
1569+ struct ieee80211_vif *vif = phy->monitor_vif;
1570+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1571+ struct mt7915_tm_muru muru = {};
1572+ struct mt7915_tm_muru_comm *comm = &muru.comm;
1573+ struct mt7915_tm_muru_dl *dl = &muru.dl;
1574+ int i;
1575+
1576+ comm->ppdu_format = MURU_PPDU_HE_MU;
1577+ comm->band = mvif->mt76.band_idx;
1578+ comm->wmm_idx = mvif->mt76.wmm_idx;
1579+ comm->spe_idx = phy->test.spe_idx;
1580+
1581+ dl->bw = mt7915_tm_chan_bw(chandef->width);
1582+ dl->gi = td->tx_rate_sgi;;
1583+ dl->ltf = td->tx_ltf;
1584+ dl->tx_mode = MT_PHY_TYPE_HE_MU;
1585+
1586+ for (i = 0; i < sizeof(dl->ru); i++)
1587+ dl->ru[i] = 0x71;
1588+
1589+ mt76_tm_for_each_entry(phy->mt76, wcid, ed) {
1590+ struct mt7915_tm_muru_dl_usr *dl_usr = &dl->usr[dl->user_num];
1591+
1592+ dl_usr->wlan_idx = cpu_to_le16(wcid->idx);
1593+ dl_usr->ru_alloc_seg = ed->aid < 8 ? 0 : 1;
1594+ dl_usr->ru_idx = ed->ru_idx;
1595+ dl_usr->mcs = ed->tx_rate_idx;
1596+ dl_usr->nss = ed->tx_rate_nss - 1;
1597+ dl_usr->ldpc = ed->tx_rate_ldpc;
1598+ dl->ru[dl->user_num] = ed->ru_alloc;
1599+
1600+ dl->user_num++;
1601+ }
1602+
1603+ muru.cfg_comm = cpu_to_le32(MURU_COMM_SET);
1604+ muru.cfg_dl = cpu_to_le32(MURU_DL_SET);
1605+
1606+ return mt7915_tm_set_muru_cfg(phy, &muru);
1607+}
1608+
1609+static int
1610+mt7915_tm_set_muru_pkt_cnt(struct mt7915_phy *phy, bool enable, u32 tx_count)
1611+{
1612+#define MURU_SET_TX_PKT_CNT 105
1613+#define MURU_SET_TX_EN 106
1614+ struct mt7915_dev *dev = phy->dev;
1615+ struct {
1616+ __le32 cmd;
1617+ u8 band;
1618+ u8 enable;
1619+ u8 _rsv[2];
1620+ __le32 tx_count;
1621+ } __packed req = {
developereb6a0182022-12-12 18:53:32 +08001622+ .band = phy->mt76->band_idx,
developer4c6b6002022-05-30 16:36:44 +08001623+ .enable = enable,
1624+ .tx_count = enable ? cpu_to_le32(tx_count) : 0,
1625+ };
1626+ int ret;
1627+
1628+ req.cmd = enable ? cpu_to_le32(MURU_SET_TX_PKT_CNT) :
1629+ cpu_to_le32(MURU_SET_TX_EN);
1630+
1631+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1632+ sizeof(req), false);
1633+ if (ret)
1634+ return ret;
1635+
1636+ req.cmd = enable ? cpu_to_le32(MURU_SET_TX_EN) :
1637+ cpu_to_le32(MURU_SET_TX_PKT_CNT);
1638+
1639+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
1640+ sizeof(req), false);
1641 }
1642
1643 static void
1644-mt7915_tm_update_channel(struct mt7915_phy *phy)
1645+mt7915_tm_tx_frames_mu(struct mt7915_phy *phy, bool enable)
1646 {
1647- mutex_unlock(&phy->dev->mt76.mutex);
1648- mt7915_set_channel(phy);
1649- mutex_lock(&phy->dev->mt76.mutex);
1650+ struct mt76_testmode_data *td = &phy->mt76->test;
1651
1652- mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
1653+ if (enable) {
1654+ struct mt7915_dev *dev = phy->dev;
1655+
1656+ mt7915_tm_set_ba(phy);
1657+ mt7915_tm_set_muru_dl(phy);
1658+ mt76_rr(dev, MT_MIB_DR8(phy != &dev->phy));
1659+ } else {
1660+ /* set to zero for counting real tx free num */
1661+ td->tx_done = 0;
1662+ }
1663+
1664+ mt7915_tm_set_muru_pkt_cnt(phy, enable, td->tx_count);
1665+ usleep_range(100000, 200000);
1666 }
1667
1668 static void
developerd59e4772022-07-14 13:48:49 +08001669 mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
1670 {
developer4c6b6002022-05-30 16:36:44 +08001671 struct mt76_testmode_data *td = &phy->mt76->test;
1672- struct mt7915_dev *dev = phy->dev;
1673- struct ieee80211_tx_info *info;
1674- u8 duty_cycle = td->tx_duty_cycle;
1675- u32 tx_time = td->tx_time;
1676- u32 ipg = td->tx_ipg;
1677
1678 mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1679- mt7915_tm_clean_hwq(phy, dev->mt76.global_wcid.idx);
1680+ mt7915_tm_set_trx(phy, TM_MAC_TX, false);
1681
1682 if (en) {
1683- mt7915_tm_update_channel(phy);
1684+ u32 tx_time = td->tx_time, ipg = td->tx_ipg;
1685+ u8 duty_cycle = td->tx_duty_cycle;
1686+
1687+ if (!phy->test.bf_en)
1688+ mt7915_tm_update_channel(phy);
1689
developerd59e4772022-07-14 13:48:49 +08001690 if (td->tx_spe_idx)
developer4c6b6002022-05-30 16:36:44 +08001691 phy->test.spe_idx = td->tx_spe_idx;
developerd59e4772022-07-14 13:48:49 +08001692 else
1693 phy->test.spe_idx = mt76_connac_spe_idx(td->tx_antenna_mask);
developer4c6b6002022-05-30 16:36:44 +08001694- }
1695
1696- mt7915_tm_set_tam_arb(phy, en,
1697- td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU);
1698+ /* if all three params are set, duty_cycle will be ignored */
1699+ if (duty_cycle && tx_time && !ipg) {
1700+ ipg = tx_time * 100 / duty_cycle - tx_time;
1701+ } else if (duty_cycle && !tx_time && ipg) {
1702+ if (duty_cycle < 100)
1703+ tx_time = duty_cycle * ipg / (100 - duty_cycle);
1704+ }
1705
1706- /* if all three params are set, duty_cycle will be ignored */
1707- if (duty_cycle && tx_time && !ipg) {
1708- ipg = tx_time * 100 / duty_cycle - tx_time;
1709- } else if (duty_cycle && !tx_time && ipg) {
1710- if (duty_cycle < 100)
1711- tx_time = duty_cycle * ipg / (100 - duty_cycle);
1712- }
1713+ mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
1714+ mt7915_tm_set_tx_len(phy, tx_time);
1715
1716- mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
1717- mt7915_tm_set_tx_len(phy, tx_time);
1718+ if (ipg)
1719+ td->tx_queued_limit = MT76_TM_TIMEOUT * 1000000 / ipg / 2;
1720
1721- if (ipg)
1722- td->tx_queued_limit = MT76_TM_TIMEOUT * 1000000 / ipg / 2;
1723+ if (!mt7915_tm_check_skb(phy))
1724+ return;
1725+ } else {
1726+ mt7915_tm_clean_hwq(phy);
1727+ }
1728
1729- if (!en || !td->tx_skb)
1730- return;
1731+ mt7915_tm_set_tam_arb(phy, en,
1732+ td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU);
1733
1734- info = IEEE80211_SKB_CB(td->tx_skb);
1735- info->control.vif = phy->monitor_vif;
1736+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1737+ mt7915_tm_tx_frames_mu(phy, en);
1738
1739 mt7915_tm_set_trx(phy, TM_MAC_TX, en);
1740 }
developereb6a0182022-12-12 18:53:32 +08001741@@ -544,10 +1482,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
developer4c6b6002022-05-30 16:36:44 +08001742 return ret;
1743
1744 rs_band = (struct mt7915_tm_rx_stat_band *)skb->data;
1745- /* pr_info("mdrdy_cnt = %d\n", le32_to_cpu(rs_band->mdrdy_cnt)); */
1746- /* pr_info("fcs_err = %d\n", le16_to_cpu(rs_band->fcs_err)); */
1747- /* pr_info("len_mismatch = %d\n", le16_to_cpu(rs_band->len_mismatch)); */
1748- /* pr_info("fcs_ok = %d\n", le16_to_cpu(rs_band->fcs_succ)); */
1749
1750 if (!clear) {
developer1d9fede2022-08-29 15:24:07 +08001751 enum mt76_rxq_id q = req.band ? MT_RXQ_BAND1 : MT_RXQ_MAIN;
developereb6a0182022-12-12 18:53:32 +08001752@@ -562,13 +1496,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
developer4c6b6002022-05-30 16:36:44 +08001753 return 0;
1754 }
1755
1756+static int
1757+mt7915_tm_set_rx_user_idx(struct mt7915_phy *phy, u8 aid)
1758+{
1759+ struct mt7915_dev *dev = phy->dev;
1760+ struct mt76_wcid *wcid = NULL;
1761+ struct mt76_testmode_entry_data *ed;
1762+ struct {
1763+ u8 band;
1764+ u8 _rsv;
1765+ __le16 wlan_idx;
1766+ } __packed req = {
developereb6a0182022-12-12 18:53:32 +08001767+ .band = phy->mt76->band_idx,
developer4c6b6002022-05-30 16:36:44 +08001768+ };
1769+
1770+ mt76_tm_for_each_entry(phy->mt76, wcid, ed)
1771+ if (ed->aid == aid)
1772+ break;
1773+
1774+ if (!wcid)
1775+ return -EINVAL;
1776+
1777+ req.wlan_idx = cpu_to_le16(wcid->idx);
1778+
1779+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_STAT_USER_CTRL),
1780+ &req, sizeof(req), false);
1781+}
1782+
1783+static int
1784+mt7915_tm_set_muru_aid(struct mt7915_phy *phy, u16 aid)
1785+{
1786+ struct mt7915_dev *dev = phy->dev;
1787+ struct mt7915_tm_cmd req = {
1788+ .testmode_en = 1,
1789+ .param_idx = MCU_ATE_SET_MU_RX_AID,
developereb6a0182022-12-12 18:53:32 +08001790+ .param.rx_aid.band = cpu_to_le32(phy->mt76->band_idx),
developer4c6b6002022-05-30 16:36:44 +08001791+ .param.rx_aid.aid = cpu_to_le16(aid),
1792+ };
1793+
1794+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
1795+ sizeof(req), false);
1796+}
1797+
1798 static void
1799 mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
1800 {
1801+ struct mt76_testmode_data *td = &phy->mt76->test;
1802+
1803+ mt7915_tm_set_trx(phy, TM_MAC_TX, false);
1804 mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
1805
1806 if (en) {
1807- mt7915_tm_update_channel(phy);
1808+ if (!phy->test.bf_en)
1809+ mt7915_tm_update_channel(phy);
1810+ if (td->aid)
1811+ mt7915_tm_set_rx_user_idx(phy, td->aid);
1812
1813 /* read-clear */
1814 mt7915_tm_get_rx_stats(phy, true);
developereb6a0182022-12-12 18:53:32 +08001815@@ -576,9 +1558,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001816 /* clear fw count */
1817 mt7915_tm_set_phy_count(phy, 0);
1818 mt7915_tm_set_phy_count(phy, 1);
1819-
1820- mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
1821 }
1822+
1823+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1824+ mt7915_tm_set_muru_aid(phy, en ? td->aid : 0xf800);
1825+
1826+ mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
1827 }
1828
1829 static int
developereb6a0182022-12-12 18:53:32 +08001830@@ -617,34 +1602,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
developer4c6b6002022-05-30 16:36:44 +08001831 tx_cont->tx_ant = td->tx_antenna_mask;
developereb6a0182022-12-12 18:53:32 +08001832 tx_cont->band = band;
developer144824b2022-11-25 21:27:43 +08001833
developer4c6b6002022-05-30 16:36:44 +08001834- switch (chandef->width) {
1835- case NL80211_CHAN_WIDTH_40:
1836- tx_cont->bw = CMD_CBW_40MHZ;
1837- break;
1838- case NL80211_CHAN_WIDTH_80:
1839- tx_cont->bw = CMD_CBW_80MHZ;
1840- break;
1841- case NL80211_CHAN_WIDTH_80P80:
1842- tx_cont->bw = CMD_CBW_8080MHZ;
1843- break;
1844- case NL80211_CHAN_WIDTH_160:
1845- tx_cont->bw = CMD_CBW_160MHZ;
1846- break;
1847- case NL80211_CHAN_WIDTH_5:
1848- tx_cont->bw = CMD_CBW_5MHZ;
1849- break;
1850- case NL80211_CHAN_WIDTH_10:
1851- tx_cont->bw = CMD_CBW_10MHZ;
1852- break;
1853- case NL80211_CHAN_WIDTH_20:
1854- tx_cont->bw = CMD_CBW_20MHZ;
1855- break;
1856- case NL80211_CHAN_WIDTH_20_NOHT:
1857- tx_cont->bw = CMD_CBW_20MHZ;
1858- break;
1859- default:
1860- return -EINVAL;
1861- }
1862+ tx_cont->bw = mt7915_tm_chan_bw(chandef->width);
1863
1864 if (!en) {
developereb6a0182022-12-12 18:53:32 +08001865 req.op.rf.param.func_data = cpu_to_le32(band);
1866@@ -728,6 +1686,12 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
developer4c6b6002022-05-30 16:36:44 +08001867 mt7915_tm_set_freq_offset(phy, en, en ? td->freq_offset : 0);
1868 if (changed & BIT(TM_CHANGED_TXPOWER))
1869 mt7915_tm_set_tx_power(phy);
1870+ if (changed & BIT(TM_CHANGED_AID))
1871+ mt7915_tm_set_entry(phy);
1872+ if (changed & BIT(TM_CHANGED_CFG))
1873+ mt7915_tm_set_cfg(phy);
1874+ if (changed & BIT(TM_CHANGED_TXBF_ACT))
1875+ mt7915_tm_set_txbf(phy);
1876 }
1877
1878 static int
developer287ee9f2023-03-02 20:13:34 +08001879@@ -737,6 +1701,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
1880 struct mt7915_phy *phy = mphy->priv;
1881 enum mt76_testmode_state prev_state = td->state;
1882
1883+ if (!phy->monitor_vif) {
1884+ dev_err(phy->dev->mt76.dev, "Please make sure monitor interface is up\n");
1885+ return -ENOTCONN;
1886+ }
1887+
1888 mphy->test.state = state;
1889
1890 if (prev_state == MT76_TM_STATE_TX_FRAMES ||
1891@@ -807,6 +1776,7 @@ static int
developer4c6b6002022-05-30 16:36:44 +08001892 mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
1893 {
1894 struct mt7915_phy *phy = mphy->priv;
1895+ struct mt7915_dev *dev = phy->dev;
1896 void *rx, *rssi;
1897 int i;
1898
developerc1997a82023-03-30 15:28:14 +08001899@@ -852,11 +1822,75 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
developer4c6b6002022-05-30 16:36:44 +08001900
1901 nla_nest_end(msg, rx);
1902
1903+ if (mphy->test.tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
1904+ mphy->test.tx_done += mt76_rr(dev, MT_MIB_DR8(phy != &dev->phy));
1905+
1906 return mt7915_tm_get_rx_stats(phy, false);
1907 }
1908
1909+static int
1910+mt7915_tm_write_back_to_efuse(struct mt7915_dev *dev)
1911+{
1912+ struct mt7915_mcu_eeprom_info req = {};
developerc1997a82023-03-30 15:28:14 +08001913+ u8 read_buf[MT76_TM_EEPROM_BLOCK_SIZE], *eeprom = dev->mt76.eeprom.data;
developer4c6b6002022-05-30 16:36:44 +08001914+ int i, ret = -EINVAL;
1915+
1916+ /* prevent from damaging chip id in efuse */
1917+ if (mt76_chip(&dev->mt76) != get_unaligned_le16(eeprom))
1918+ goto out;
1919+
1920+ for (i = 0; i < mt7915_eeprom_size(dev); i += MT76_TM_EEPROM_BLOCK_SIZE) {
1921+ req.addr = cpu_to_le32(i);
developerc1997a82023-03-30 15:28:14 +08001922+ memcpy(req.data, eeprom + i, MT76_TM_EEPROM_BLOCK_SIZE);
1923+
1924+ ret = mt7915_mcu_get_eeprom(dev, i, read_buf);
1925+ if (ret < 0)
1926+ return ret;
1927+
1928+ if (!memcmp(req.data, read_buf, MT76_TM_EEPROM_BLOCK_SIZE))
1929+ continue;
developer4c6b6002022-05-30 16:36:44 +08001930+
1931+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_ACCESS),
1932+ &req, sizeof(req), true);
1933+ if (ret)
1934+ return ret;
1935+ }
1936+
1937+out:
1938+ return ret;
1939+}
1940+
1941+static int
1942+mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
1943+{
1944+ struct mt7915_phy *phy = mphy->priv;
1945+ struct mt7915_dev *dev = phy->dev;
1946+ u8 *eeprom = dev->mt76.eeprom.data;
1947+ int ret = 0;
1948+
1949+ if (offset >= mt7915_eeprom_size(dev))
1950+ return -EINVAL;
1951+
1952+ switch (action) {
1953+ case MT76_TM_EEPROM_ACTION_UPDATE_DATA:
1954+ memcpy(eeprom + offset, val, MT76_TM_EEPROM_BLOCK_SIZE);
1955+ break;
1956+ case MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE:
1957+ ret = mt7915_mcu_set_eeprom(dev, true);
1958+ break;
1959+ case MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE:
1960+ ret = mt7915_tm_write_back_to_efuse(dev);
1961+ break;
1962+ default:
1963+ break;
1964+ }
1965+
1966+ return ret;
1967+}
1968+
1969 const struct mt76_testmode_ops mt7915_testmode_ops = {
1970 .set_state = mt7915_tm_set_state,
1971 .set_params = mt7915_tm_set_params,
1972 .dump_stats = mt7915_tm_dump_stats,
1973+ .set_eeprom = mt7915_tm_set_eeprom,
1974 };
1975diff --git a/mt7915/testmode.h b/mt7915/testmode.h
developer287ee9f2023-03-02 20:13:34 +08001976index a1c54c8..01b08e9 100644
developer4c6b6002022-05-30 16:36:44 +08001977--- a/mt7915/testmode.h
1978+++ b/mt7915/testmode.h
1979@@ -4,6 +4,8 @@
1980 #ifndef __MT7915_TESTMODE_H
1981 #define __MT7915_TESTMODE_H
1982
1983+#include "mcu.h"
1984+
1985 struct mt7915_tm_trx {
1986 u8 type;
1987 u8 enable;
1988@@ -39,6 +41,11 @@ struct mt7915_tm_cfg {
1989 u8 _rsv[2];
1990 };
1991
1992+struct mt7915_tm_mu_rx_aid {
1993+ __le32 band;
1994+ __le16 aid;
1995+};
1996+
1997 struct mt7915_tm_cmd {
1998 u8 testmode_en;
1999 u8 param_idx;
2000@@ -50,6 +57,7 @@ struct mt7915_tm_cmd {
2001 struct mt7915_tm_slot_time slot;
2002 struct mt7915_tm_clean_txq clean;
2003 struct mt7915_tm_cfg cfg;
2004+ struct mt7915_tm_mu_rx_aid rx_aid;
2005 u8 test[72];
2006 } param;
2007 } __packed;
2008@@ -109,6 +117,16 @@ enum {
2009 TAM_ARB_OP_MODE_FORCE_SU = 5,
2010 };
2011
2012+enum {
2013+ TM_CBW_20MHZ,
2014+ TM_CBW_40MHZ,
2015+ TM_CBW_80MHZ,
2016+ TM_CBW_10MHZ,
2017+ TM_CBW_5MHZ,
2018+ TM_CBW_160MHZ,
2019+ TM_CBW_8080MHZ,
2020+};
2021+
2022 struct mt7915_tm_rx_stat_band {
2023 u8 category;
2024
2025@@ -130,4 +148,264 @@ struct mt7915_tm_rx_stat_band {
2026 __le16 mdrdy_cnt_ofdm;
2027 };
2028
2029+struct mt7915_tm_muru_comm {
2030+ u8 ppdu_format;
2031+ u8 sch_type;
2032+ u8 band;
2033+ u8 wmm_idx;
2034+ u8 spe_idx;
2035+ u8 proc_type;
2036+};
2037+
2038+struct mt7915_tm_muru_dl_usr {
2039+ __le16 wlan_idx;
2040+ u8 ru_alloc_seg;
2041+ u8 ru_idx;
2042+ u8 ldpc;
2043+ u8 nss;
2044+ u8 mcs;
2045+ u8 mu_group_idx;
2046+ u8 vht_groud_id;
2047+ u8 vht_up;
2048+ u8 he_start_stream;
2049+ u8 he_mu_spatial;
2050+ u8 ack_policy;
2051+ __le16 tx_power_alpha;
2052+};
2053+
2054+struct mt7915_tm_muru_dl {
2055+ u8 user_num;
2056+ u8 tx_mode;
2057+ u8 bw;
2058+ u8 gi;
2059+ u8 ltf;
2060+ /* sigB */
2061+ u8 mcs;
2062+ u8 dcm;
2063+ u8 cmprs;
2064+
2065+ u8 tx_power;
2066+ u8 ru[8];
2067+ u8 c26[2];
2068+ u8 ack_policy;
2069+
2070+ struct mt7915_tm_muru_dl_usr usr[16];
2071+};
2072+
2073+struct mt7915_tm_muru_ul_usr {
2074+ __le16 wlan_idx;
2075+ u8 ru_alloc;
2076+ u8 ru_idx;
2077+ u8 ldpc;
2078+ u8 nss;
2079+ u8 mcs;
2080+ u8 target_rssi;
2081+ __le32 trig_pkt_size;
2082+};
2083+
2084+struct mt7915_tm_muru_ul {
2085+ u8 user_num;
2086+
2087+ /* UL TX */
2088+ u8 trig_type;
2089+ __le16 trig_cnt;
2090+ __le16 trig_intv;
2091+ u8 bw;
2092+ u8 gi_ltf;
2093+ __le16 ul_len;
2094+ u8 pad;
2095+ u8 trig_ta[ETH_ALEN];
2096+ u8 ru[8];
2097+ u8 c26[2];
2098+
2099+ struct mt7915_tm_muru_ul_usr usr[16];
2100+ /* HE TB RX Debug */
2101+ __le32 rx_hetb_nonsf_en_bitmap;
2102+ __le32 rx_hetb_cfg[2];
2103+
2104+ /* DL TX */
2105+ u8 ba_type;
2106+};
2107+
2108+struct mt7915_tm_muru {
2109+ __le32 cfg_comm;
2110+ __le32 cfg_dl;
2111+ __le32 cfg_ul;
2112+
2113+ struct mt7915_tm_muru_comm comm;
2114+ struct mt7915_tm_muru_dl dl;
2115+ struct mt7915_tm_muru_ul ul;
2116+};
2117+
2118+#define MURU_PPDU_HE_MU BIT(3)
2119+
2120+/* Common Config */
2121+/* #define MURU_COMM_PPDU_FMT BIT(0) */
2122+/* #define MURU_COMM_SCH_TYPE BIT(1) */
2123+/* #define MURU_COMM_BAND BIT(2) */
2124+/* #define MURU_COMM_WMM BIT(3) */
2125+/* #define MURU_COMM_SPE_IDX BIT(4) */
2126+/* #define MURU_COMM_PROC_TYPE BIT(5) */
2127+/* #define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \ */
2128+/* MURU_COMM_WMM | MURU_COMM_SPE_IDX) */
2129+/* DL Config */
2130+#define MURU_DL_BW BIT(0)
2131+#define MURU_DL_GI BIT(1)
2132+#define MURU_DL_TX_MODE BIT(2)
2133+#define MURU_DL_TONE_PLAN BIT(3)
2134+#define MURU_DL_USER_CNT BIT(4)
2135+#define MURU_DL_LTF BIT(5)
2136+#define MURU_DL_SIGB_MCS BIT(6)
2137+#define MURU_DL_SIGB_DCM BIT(7)
2138+#define MURU_DL_SIGB_CMPRS BIT(8)
2139+#define MURU_DL_ACK_POLICY BIT(9)
2140+#define MURU_DL_TXPOWER BIT(10)
2141+/* DL Per User Config */
2142+#define MURU_DL_USER_WLAN_ID BIT(16)
2143+#define MURU_DL_USER_COD BIT(17)
2144+#define MURU_DL_USER_MCS BIT(18)
2145+#define MURU_DL_USER_NSS BIT(19)
2146+#define MURU_DL_USER_RU_ALLOC BIT(20)
2147+#define MURU_DL_USER_MUMIMO_GRP BIT(21)
2148+#define MURU_DL_USER_MUMIMO_VHT BIT(22)
2149+#define MURU_DL_USER_ACK_POLICY BIT(23)
2150+#define MURU_DL_USER_MUMIMO_HE BIT(24)
2151+#define MURU_DL_USER_PWR_ALPHA BIT(25)
2152+#define MURU_DL_SET (GENMASK(7, 0) | GENMASK(20, 16) | BIT(25))
2153+
2154+#define MAX_PHASE_GROUP_NUM 9
2155+
2156+struct mt7915_tm_txbf_phase {
2157+ u8 status;
2158+ struct {
2159+ u8 r0_uh;
2160+ u8 r0_h;
2161+ u8 r0_m;
2162+ u8 r0_l;
2163+ u8 r0_ul;
2164+ u8 r1_uh;
2165+ u8 r1_h;
2166+ u8 r1_m;
2167+ u8 r1_l;
2168+ u8 r1_ul;
2169+ u8 r2_uh;
2170+ u8 r2_h;
2171+ u8 r2_m;
2172+ u8 r2_l;
2173+ u8 r2_ul;
2174+ u8 r3_uh;
2175+ u8 r3_h;
2176+ u8 r3_m;
2177+ u8 r3_l;
2178+ u8 r3_ul;
2179+ u8 r2_uh_sx2;
2180+ u8 r2_h_sx2;
2181+ u8 r2_m_sx2;
2182+ u8 r2_l_sx2;
2183+ u8 r2_ul_sx2;
2184+ u8 r3_uh_sx2;
2185+ u8 r3_h_sx2;
2186+ u8 r3_m_sx2;
2187+ u8 r3_l_sx2;
2188+ u8 r3_ul_sx2;
2189+ u8 m_t0_h;
2190+ u8 m_t1_h;
2191+ u8 m_t2_h;
2192+ u8 m_t2_h_sx2;
2193+ u8 r0_reserved;
2194+ u8 r1_reserved;
2195+ u8 r2_reserved;
2196+ u8 r3_reserved;
2197+ u8 r2_sx2_reserved;
2198+ u8 r3_sx2_reserved;
2199+ } phase;
2200+};
2201+
2202+struct mt7915_tm_pfmu_tag1 {
2203+ __le32 pfmu_idx:10;
2204+ __le32 ebf:1;
2205+ __le32 data_bw:2;
2206+ __le32 lm:2;
2207+ __le32 is_mu:1;
2208+ __le32 nr:3, nc:3;
2209+ __le32 codebook:2;
2210+ __le32 ngroup:2;
2211+ __le32 _rsv:2;
2212+ __le32 invalid_prof:1;
2213+ __le32 rmsd:3;
2214+
2215+ __le32 col_id1:6, row_id1:10;
2216+ __le32 col_id2:6, row_id2:10;
2217+ __le32 col_id3:6, row_id3:10;
2218+ __le32 col_id4:6, row_id4:10;
2219+
2220+ __le32 ru_start_id:7;
2221+ __le32 _rsv1:1;
2222+ __le32 ru_end_id:7;
2223+ __le32 _rsv2:1;
2224+ __le32 mob_cal_en:1;
2225+ __le32 _rsv3:15;
2226+
2227+ __le32 snr_sts0:8, snr_sts1:8, snr_sts2:8, snr_sts3:8;
2228+ __le32 snr_sts4:8, snr_sts5:8, snr_sts6:8, snr_sts7:8;
2229+
2230+ __le32 _rsv4;
2231+} __packed;
2232+
2233+struct mt7915_tm_pfmu_tag2 {
2234+ __le32 smart_ant:24;
2235+ __le32 se_idx:5;
2236+ __le32 _rsv:3;
2237+
2238+ __le32 _rsv1:8;
2239+ __le32 rmsd_thres:3;
2240+ __le32 _rsv2:5;
2241+ __le32 ibf_timeout:8;
2242+ __le32 _rsv3:8;
2243+
2244+ __le32 _rsv4:16;
2245+ __le32 ibf_data_bw:2;
2246+ __le32 ibf_nc:3;
2247+ __le32 ibf_nr:3;
2248+ __le32 ibf_ru:8;
2249+
2250+ __le32 mob_delta_t:8;
2251+ __le32 mob_lq_result:7;
2252+ __le32 _rsv5:1;
2253+ __le32 _rsv6:16;
2254+
2255+ __le32 _rsv7;
2256+} __packed;
2257+
2258+struct mt7915_tm_pfmu_tag {
2259+ struct mt7915_tm_pfmu_tag1 t1;
2260+ struct mt7915_tm_pfmu_tag2 t2;
2261+};
2262+
2263+struct mt7915_tm_pfmu_data {
2264+ __le16 subc_idx;
2265+ __le16 phi11;
2266+ __le16 phi21;
2267+ __le16 phi31;
2268+};
2269+
2270+struct mt7915_tm_ibf_cal_info {
2271+ u8 format_id;
2272+ u8 group_l_m_n;
2273+ u8 group;
2274+ bool sx2;
2275+ u8 status;
2276+ u8 cal_type;
2277+ u8 _rsv[2];
2278+ u8 buf[1000];
2279+} __packed;
2280+
2281+enum {
2282+ IBF_PHASE_CAL_UNSPEC,
2283+ IBF_PHASE_CAL_NORMAL,
2284+ IBF_PHASE_CAL_VERIFY,
2285+ IBF_PHASE_CAL_NORMAL_INSTRUMENT,
2286+ IBF_PHASE_CAL_VERIFY_INSTRUMENT,
2287+};
2288+
2289 #endif
2290diff --git a/testmode.c b/testmode.c
developer62713c82023-03-20 10:46:08 +08002291index 1d0d5d3..fd3b9b2 100644
developer4c6b6002022-05-30 16:36:44 +08002292--- a/testmode.c
2293+++ b/testmode.c
developere9954402022-07-12 10:15:11 -07002294@@ -27,28 +27,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
developer4c6b6002022-05-30 16:36:44 +08002295 };
2296 EXPORT_SYMBOL_GPL(mt76_tm_policy);
2297
2298-void mt76_testmode_tx_pending(struct mt76_phy *phy)
2299+static void
2300+mt76_testmode_queue_tx(struct mt76_phy *phy, struct mt76_wcid *wcid,
developerf1b69ea2022-07-04 10:54:39 +08002301+ struct sk_buff *skb, struct mt76_queue *q, int qid,
2302+ u16 limit)
developer4c6b6002022-05-30 16:36:44 +08002303 {
2304 struct mt76_testmode_data *td = &phy->test;
2305 struct mt76_dev *dev = phy->dev;
2306- struct mt76_wcid *wcid = &dev->global_wcid;
2307- struct sk_buff *skb = td->tx_skb;
2308- struct mt76_queue *q;
2309- u16 tx_queued_limit;
2310- int qid;
2311-
2312- if (!skb || !td->tx_pending)
2313- return;
2314+ u16 count = limit;
2315
2316- qid = skb_get_queue_mapping(skb);
2317- q = phy->q_tx[qid];
2318-
2319- tx_queued_limit = td->tx_queued_limit ? td->tx_queued_limit : 1000;
2320-
2321- spin_lock_bh(&q->lock);
2322-
2323- while (td->tx_pending > 0 &&
2324- td->tx_queued - td->tx_done < tx_queued_limit &&
2325+ while (td->tx_pending > 0 && count &&
2326 q->queued < q->ndesc / 2) {
2327 int ret;
2328
developer62713c82023-03-20 10:46:08 +08002329@@ -57,13 +45,68 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002330 if (ret < 0)
2331 break;
2332
developer62713c82023-03-20 10:46:08 +08002333- td->tx_pending--;
developer4c6b6002022-05-30 16:36:44 +08002334+ count--;
developer62713c82023-03-20 10:46:08 +08002335+
2336+ /* tx_count == UINT_MAX for continuous tx */
2337+ if (td->tx_count != UINT_MAX)
2338+ td->tx_pending--;
developer4c6b6002022-05-30 16:36:44 +08002339 td->tx_queued++;
2340+
2341+ if (td->tx_rate_mode != MT76_TM_TX_MODE_HE_MU)
2342+ if (td->tx_queued - td->tx_done >= limit)
2343+ break;
2344 }
2345
2346 dev->queue_ops->kick(dev, q);
2347+}
2348+
2349+void mt76_testmode_tx_pending(struct mt76_phy *phy)
2350+{
2351+ struct mt76_testmode_data *td = &phy->test;
2352+ struct mt76_testmode_entry_data *ed;
2353+ struct mt76_queue *q;
2354+ int qid;
2355+ u16 tx_queued_limit;
2356+ u32 remain;
2357+ bool is_mu;
2358+
2359+ if (!td->tx_pending)
2360+ return;
2361+
2362+ /* tx_queued_limit = td->tx_queued_limit ?: 100; */
2363+ tx_queued_limit = 100;
2364+
2365+ if (!td->aid) {
2366+ qid = skb_get_queue_mapping(td->tx_skb);
2367+ q = phy->q_tx[qid];
2368+ spin_lock_bh(&q->lock);
2369+ mt76_testmode_queue_tx(phy, &phy->dev->global_wcid,
developerf1b69ea2022-07-04 10:54:39 +08002370+ td->tx_skb, q, qid, tx_queued_limit);
developer4c6b6002022-05-30 16:36:44 +08002371+ spin_unlock_bh(&q->lock);
2372+
2373+ return;
2374+ }
2375+
2376+ is_mu = td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU;
2377+ ed = mt76_testmode_entry_data(phy, td->cur_entry);
2378+ qid = skb_get_queue_mapping(ed->tx_skb);
2379+ q = phy->q_tx[qid];
2380+
2381+ spin_lock_bh(&q->lock);
2382+
2383+ remain = is_mu ? 1 : (td->tx_pending % td->tx_count) ?: td->tx_count;
2384+ if (remain < tx_queued_limit)
2385+ tx_queued_limit = remain;
2386+
developerf1b69ea2022-07-04 10:54:39 +08002387+ mt76_testmode_queue_tx(phy, td->cur_entry, ed->tx_skb, q, qid, tx_queued_limit);
developer4c6b6002022-05-30 16:36:44 +08002388+
2389+ if (td->tx_pending % td->tx_count == 0 || is_mu)
2390+ td->cur_entry = list_next_entry(td->cur_entry, list);
2391
2392 spin_unlock_bh(&q->lock);
2393+
2394+ if (is_mu && td->tx_pending)
2395+ mt76_worker_schedule(&phy->dev->tx_worker);
2396 }
2397
2398 static u32
developer62713c82023-03-20 10:46:08 +08002399@@ -89,15 +132,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
developer4c6b6002022-05-30 16:36:44 +08002400 }
2401
2402 static void
2403-mt76_testmode_free_skb(struct mt76_phy *phy)
2404+mt76_testmode_free_skb(struct sk_buff **tx_skb)
2405+{
2406+ if (!(*tx_skb))
2407+ return;
2408+
2409+ dev_kfree_skb(*tx_skb);
2410+ *tx_skb = NULL;
2411+}
2412+
2413+static void
2414+mt76_testmode_free_skb_all(struct mt76_phy *phy)
2415 {
2416 struct mt76_testmode_data *td = &phy->test;
2417+ struct mt76_testmode_entry_data *ed = &td->ed;
2418+ struct mt76_wcid *wcid;
2419+
2420+ mt76_testmode_free_skb(&ed->tx_skb);
2421
2422- dev_kfree_skb(td->tx_skb);
2423- td->tx_skb = NULL;
2424+ mt76_tm_for_each_entry(phy, wcid, ed)
2425+ mt76_testmode_free_skb(&ed->tx_skb);
2426 }
2427
2428-int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
2429+static int
2430+mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len,
2431+ struct sk_buff **tx_skb, u8 (*addr)[ETH_ALEN])
2432 {
2433 #define MT_TXP_MAX_LEN 4095
2434 u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
developer62713c82023-03-20 10:46:08 +08002435@@ -118,7 +177,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
developer4c6b6002022-05-30 16:36:44 +08002436 nfrags = len / MT_TXP_MAX_LEN;
2437 head_len = nfrags ? MT_TXP_MAX_LEN : len;
2438
2439- if (len > IEEE80211_MAX_FRAME_LEN)
2440+ if (len > IEEE80211_MAX_FRAME_LEN ||
2441+ td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2442 fc |= IEEE80211_STYPE_QOS_DATA;
2443
2444 head = alloc_skb(head_len, GFP_KERNEL);
developer62713c82023-03-20 10:46:08 +08002445@@ -127,9 +187,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
developer4c6b6002022-05-30 16:36:44 +08002446
developere9954402022-07-12 10:15:11 -07002447 hdr = __skb_put_zero(head, sizeof(*hdr));
developer4c6b6002022-05-30 16:36:44 +08002448 hdr->frame_control = cpu_to_le16(fc);
2449- memcpy(hdr->addr1, td->addr[0], ETH_ALEN);
2450- memcpy(hdr->addr2, td->addr[1], ETH_ALEN);
2451- memcpy(hdr->addr3, td->addr[2], ETH_ALEN);
2452+ memcpy(hdr->addr1, addr[0], ETH_ALEN);
2453+ memcpy(hdr->addr2, addr[1], ETH_ALEN);
2454+ memcpy(hdr->addr3, addr[2], ETH_ALEN);
2455 skb_set_queue_mapping(head, IEEE80211_AC_BE);
developere9954402022-07-12 10:15:11 -07002456 get_random_bytes(__skb_put(head, head_len - sizeof(*hdr)),
2457 head_len - sizeof(*hdr));
developer62713c82023-03-20 10:46:08 +08002458@@ -153,7 +213,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
developer4c6b6002022-05-30 16:36:44 +08002459
2460 frag = alloc_skb(frag_len, GFP_KERNEL);
2461 if (!frag) {
2462- mt76_testmode_free_skb(phy);
2463+ mt76_testmode_free_skb(tx_skb);
2464 dev_kfree_skb(head);
2465 return -ENOMEM;
2466 }
developer62713c82023-03-20 10:46:08 +08002467@@ -166,15 +226,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
developer4c6b6002022-05-30 16:36:44 +08002468 frag_tail = &(*frag_tail)->next;
2469 }
2470
2471- mt76_testmode_free_skb(phy);
2472- td->tx_skb = head;
2473+ mt76_testmode_free_skb(tx_skb);
2474+ *tx_skb = head;
2475
2476 return 0;
2477 }
2478-EXPORT_SYMBOL(mt76_testmode_alloc_skb);
2479
2480-static int
2481-mt76_testmode_tx_init(struct mt76_phy *phy)
2482+int mt76_testmode_init_skb(struct mt76_phy *phy, u32 len,
2483+ struct sk_buff **tx_skb, u8 (*addr)[ETH_ALEN])
2484 {
2485 struct mt76_testmode_data *td = &phy->test;
2486 struct ieee80211_tx_info *info;
developer62713c82023-03-20 10:46:08 +08002487@@ -182,7 +241,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002488 u8 max_nss = hweight8(phy->antenna_mask);
2489 int ret;
2490
2491- ret = mt76_testmode_alloc_skb(phy, td->tx_mpdu_len);
2492+ ret = mt76_testmode_alloc_skb(phy, len, tx_skb, addr);
2493 if (ret)
2494 return ret;
2495
developer62713c82023-03-20 10:46:08 +08002496@@ -192,7 +251,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002497 if (td->tx_antenna_mask)
2498 max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
2499
2500- info = IEEE80211_SKB_CB(td->tx_skb);
2501+ info = IEEE80211_SKB_CB(*tx_skb);
2502 rate = &info->control.rates[0];
2503 rate->count = 1;
2504 rate->idx = td->tx_rate_idx;
developer62713c82023-03-20 10:46:08 +08002505@@ -264,6 +323,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002506 out:
2507 return 0;
2508 }
2509+EXPORT_SYMBOL(mt76_testmode_init_skb);
2510+
2511+static int
2512+mt76_testmode_tx_init(struct mt76_phy *phy)
2513+{
2514+ struct mt76_testmode_entry_data *ed;
2515+ struct mt76_wcid *wcid;
2516+
2517+ mt76_tm_for_each_entry(phy, wcid, ed) {
2518+ int ret;
2519+
2520+ ret = mt76_testmode_init_skb(phy, ed->tx_mpdu_len,
2521+ &ed->tx_skb, ed->addr);
2522+ if (ret)
2523+ return ret;
2524+ }
2525+
2526+ return 0;
2527+}
2528
2529 static void
2530 mt76_testmode_tx_start(struct mt76_phy *phy)
developer62713c82023-03-20 10:46:08 +08002531@@ -274,6 +352,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002532 td->tx_queued = 0;
2533 td->tx_done = 0;
2534 td->tx_pending = td->tx_count;
2535+ if (td->tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2536+ td->tx_pending = 1;
2537+ if (td->entry_num) {
2538+ td->tx_pending *= td->entry_num;
2539+ td->cur_entry = list_first_entry(&td->tm_entry_list,
2540+ struct mt76_wcid, list);
2541+ }
2542+
2543 mt76_worker_schedule(&dev->tx_worker);
2544 }
2545
developer62713c82023-03-20 10:46:08 +08002546@@ -292,7 +378,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002547 wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
2548 MT76_TM_TIMEOUT * HZ);
2549
2550- mt76_testmode_free_skb(phy);
2551+ mt76_testmode_free_skb_all(phy);
2552 }
2553
2554 static inline void
developer62713c82023-03-20 10:46:08 +08002555@@ -323,6 +409,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
developer4c6b6002022-05-30 16:36:44 +08002556 memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
2557 memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
2558 memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
2559+
2560+ INIT_LIST_HEAD(&phy->test.tm_entry_list);
2561 }
2562
2563 static int
developer62713c82023-03-20 10:46:08 +08002564@@ -332,8 +420,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
developer4c6b6002022-05-30 16:36:44 +08002565 struct mt76_dev *dev = phy->dev;
2566 int err;
2567
2568- if (prev_state == MT76_TM_STATE_TX_FRAMES)
2569+ if (prev_state == MT76_TM_STATE_TX_FRAMES) {
2570+ /* MU needs to clean hwq for free done event */
2571+ if (phy->test.tx_rate_mode == MT76_TM_TX_MODE_HE_MU)
2572+ dev->test_ops->set_state(phy, MT76_TM_STATE_IDLE);
2573 mt76_testmode_tx_stop(phy);
2574+ }
2575
2576 if (state == MT76_TM_STATE_TX_FRAMES) {
2577 err = mt76_testmode_tx_init(phy);
developer62713c82023-03-20 10:46:08 +08002578@@ -403,6 +495,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
developer4c6b6002022-05-30 16:36:44 +08002579 return 0;
2580 }
2581
2582+static int
2583+mt76_testmode_set_eeprom(struct mt76_phy *phy, struct nlattr **tb)
2584+{
2585+ struct mt76_dev *dev = phy->dev;
2586+ u8 action, val[MT76_TM_EEPROM_BLOCK_SIZE];
2587+ u32 offset = 0;
2588+ int err = -EINVAL;
2589+
2590+ if (!dev->test_ops->set_eeprom)
2591+ return -EOPNOTSUPP;
2592+
2593+ if (mt76_tm_get_u8(tb[MT76_TM_ATTR_EEPROM_ACTION], &action,
2594+ 0, MT76_TM_EEPROM_ACTION_MAX))
2595+ goto out;
2596+
2597+ if (tb[MT76_TM_ATTR_EEPROM_OFFSET]) {
2598+ struct nlattr *cur;
2599+ int rem, idx = 0;
2600+
2601+ offset = nla_get_u32(tb[MT76_TM_ATTR_EEPROM_OFFSET]);
2602+ if (!!(offset % MT76_TM_EEPROM_BLOCK_SIZE) ||
2603+ !tb[MT76_TM_ATTR_EEPROM_VAL])
2604+ goto out;
2605+
2606+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_EEPROM_VAL], rem) {
2607+ if (nla_len(cur) != 1 || idx >= ARRAY_SIZE(val))
2608+ goto out;
2609+
2610+ val[idx++] = nla_get_u8(cur);
2611+ }
2612+ }
2613+
2614+ err = dev->test_ops->set_eeprom(phy, offset, val, action);
2615+
2616+out:
2617+ return err;
2618+}
2619+
2620 int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2621 void *data, int len)
2622 {
developer62713c82023-03-20 10:46:08 +08002623@@ -426,6 +556,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer4c6b6002022-05-30 16:36:44 +08002624
2625 mutex_lock(&dev->mutex);
2626
2627+ if (tb[MT76_TM_ATTR_EEPROM_ACTION]) {
2628+ err = mt76_testmode_set_eeprom(phy, tb);
2629+ goto out;
2630+ }
2631+
2632 if (tb[MT76_TM_ATTR_RESET]) {
2633 mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
2634 memset(td, 0, sizeof(*td));
developer62713c82023-03-20 10:46:08 +08002635@@ -452,7 +587,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer4c6b6002022-05-30 16:36:44 +08002636 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
2637 &td->tx_duty_cycle, 0, 99) ||
2638 mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
2639- &td->tx_power_control, 0, 1))
2640+ &td->tx_power_control, 0, 1) ||
2641+ mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16) ||
2642+ mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_ALLOC], &td->ru_alloc, 0, 0xff) ||
2643+ mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_IDX], &td->ru_idx, 0, 68))
2644 goto out;
2645
2646 if (tb[MT76_TM_ATTR_TX_LENGTH]) {
developer62713c82023-03-20 10:46:08 +08002647@@ -484,8 +622,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer4c6b6002022-05-30 16:36:44 +08002648
2649 if (tb[MT76_TM_ATTR_TX_POWER]) {
2650 struct nlattr *cur;
2651- int idx = 0;
2652- int rem;
2653+ int rem, idx = 0;
2654
2655 nla_for_each_nested(cur, tb[MT76_TM_ATTR_TX_POWER], rem) {
2656 if (nla_len(cur) != 1 ||
developer62713c82023-03-20 10:46:08 +08002657@@ -505,11 +642,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer4c6b6002022-05-30 16:36:44 +08002658 if (nla_len(cur) != ETH_ALEN || idx >= 3)
2659 goto out;
2660
2661- memcpy(td->addr[idx], nla_data(cur), ETH_ALEN);
2662+ memcpy(td->addr[idx++], nla_data(cur), ETH_ALEN);
2663+ }
2664+ }
2665+
2666+ if (tb[MT76_TM_ATTR_CFG]) {
2667+ struct nlattr *cur;
2668+ int rem, idx = 0;
2669+
2670+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_CFG], rem) {
2671+ if (nla_len(cur) != 1 || idx >= 2)
2672+ goto out;
2673+
2674+ if (idx == 0)
2675+ td->cfg.type = nla_get_u8(cur);
2676+ else
2677+ td->cfg.enable = nla_get_u8(cur);
2678 idx++;
2679 }
2680 }
2681
2682+ if (tb[MT76_TM_ATTR_TXBF_ACT]) {
2683+ struct nlattr *cur;
2684+ int rem, idx = 0;
2685+
2686+ if (!tb[MT76_TM_ATTR_TXBF_PARAM] ||
2687+ mt76_tm_get_u8(tb[MT76_TM_ATTR_TXBF_ACT], &td->txbf_act,
2688+ 0, MT76_TM_TXBF_ACT_MAX))
2689+ goto out;
2690+
2691+ memset(td->txbf_param, 0, sizeof(td->txbf_param));
2692+ nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
2693+ if (nla_len(cur) != 2 ||
2694+ idx >= ARRAY_SIZE(td->txbf_param))
2695+ goto out;
2696+
2697+ td->txbf_param[idx++] = nla_get_u16(cur);
2698+ }
2699+ }
2700+
2701 if (dev->test_ops->set_params) {
2702 err = dev->test_ops->set_params(phy, tb, state);
2703 if (err)
developer62713c82023-03-20 10:46:08 +08002704@@ -574,6 +745,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer4c6b6002022-05-30 16:36:44 +08002705 struct mt76_phy *phy = hw->priv;
2706 struct mt76_dev *dev = phy->dev;
2707 struct mt76_testmode_data *td = &phy->test;
2708+ struct mt76_testmode_entry_data *ed = &td->ed;
2709 struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
2710 int err = 0;
2711 void *a;
developer62713c82023-03-20 10:46:08 +08002712@@ -606,6 +778,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer4c6b6002022-05-30 16:36:44 +08002713 goto out;
2714 }
2715
2716+ if (tb[MT76_TM_ATTR_AID]) {
2717+ struct mt76_wcid *wcid;
2718+ u8 aid;
2719+
2720+ err = mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &aid, 1, 16);
2721+ if (err)
2722+ goto out;
2723+
2724+ mt76_tm_for_each_entry(phy, wcid, ed)
2725+ if (ed->aid == aid)
2726+ ed = mt76_testmode_entry_data(phy, wcid);
2727+ }
2728+
2729 mt76_testmode_init_defaults(phy);
2730
2731 err = -EMSGSIZE;
developer62713c82023-03-20 10:46:08 +08002732@@ -618,12 +803,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer4c6b6002022-05-30 16:36:44 +08002733 goto out;
2734
2735 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
2736- nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, td->tx_mpdu_len) ||
2737 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, td->tx_rate_mode) ||
2738- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, td->tx_rate_nss) ||
2739- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, td->tx_rate_idx) ||
2740 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) ||
2741- nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) ||
2742 nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
2743 (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
2744 nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
developer62713c82023-03-20 10:46:08 +08002745@@ -643,6 +824,15 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
developer4c6b6002022-05-30 16:36:44 +08002746 nla_put_u8(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset)))
2747 goto out;
2748
2749+ if (nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, ed->tx_mpdu_len) ||
2750+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, ed->tx_rate_nss) ||
2751+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, ed->tx_rate_idx) ||
2752+ nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, ed->tx_rate_ldpc) ||
2753+ nla_put_u8(msg, MT76_TM_ATTR_AID, ed->aid) ||
2754+ nla_put_u8(msg, MT76_TM_ATTR_RU_ALLOC, ed->ru_alloc) ||
2755+ nla_put_u8(msg, MT76_TM_ATTR_RU_IDX, ed->ru_idx))
2756+ goto out;
2757+
2758 if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
2759 a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
2760 if (!a)
2761diff --git a/testmode.h b/testmode.h
developer287ee9f2023-03-02 20:13:34 +08002762index 8961326..57949f2 100644
developer4c6b6002022-05-30 16:36:44 +08002763--- a/testmode.h
2764+++ b/testmode.h
2765@@ -6,6 +6,8 @@
2766 #define __MT76_TESTMODE_H
2767
2768 #define MT76_TM_TIMEOUT 10
2769+#define MT76_TM_MAX_ENTRY_NUM 16
2770+#define MT76_TM_EEPROM_BLOCK_SIZE 16
2771
2772 /**
2773 * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
2774@@ -47,6 +49,15 @@
2775 * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
2776 *
2777 * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
2778+ *
2779+ * @MT76_TM_ATTR_EEPROM_ACTION: eeprom setting actions
2780+ * (u8, see &enum mt76_testmode_eeprom_action)
2781+ * @MT76_TM_ATTR_EEPROM_OFFSET: offset of eeprom data block for writing (u32)
2782+ * @MT76_TM_ATTR_EEPROM_VAL: values for writing into a 16-byte data block
2783+ * (nested, u8 attrs)
2784+ *
2785+ * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg)
2786+ *
2787 */
2788 enum mt76_testmode_attr {
2789 MT76_TM_ATTR_UNSPEC,
2790@@ -84,6 +95,17 @@ enum mt76_testmode_attr {
2791 MT76_TM_ATTR_DRV_DATA,
2792
2793 MT76_TM_ATTR_MAC_ADDRS,
2794+ MT76_TM_ATTR_AID,
2795+ MT76_TM_ATTR_RU_ALLOC,
2796+ MT76_TM_ATTR_RU_IDX,
2797+
2798+ MT76_TM_ATTR_EEPROM_ACTION,
2799+ MT76_TM_ATTR_EEPROM_OFFSET,
2800+ MT76_TM_ATTR_EEPROM_VAL,
2801+
2802+ MT76_TM_ATTR_CFG,
2803+ MT76_TM_ATTR_TXBF_ACT,
2804+ MT76_TM_ATTR_TXBF_PARAM,
2805
2806 /* keep last */
2807 NUM_MT76_TM_ATTRS,
2808@@ -198,4 +220,57 @@ enum mt76_testmode_tx_mode {
2809
2810 extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
2811
2812+/**
2813+ * enum mt76_testmode_eeprom_action - eeprom setting actions
2814+ *
2815+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
2816+ * eeprom data block
2817+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
2818+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
2819+ */
2820+enum mt76_testmode_eeprom_action {
2821+ MT76_TM_EEPROM_ACTION_UPDATE_DATA,
2822+ MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE,
2823+ MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE,
2824+
2825+ /* keep last */
2826+ NUM_MT76_TM_EEPROM_ACTION,
2827+ MT76_TM_EEPROM_ACTION_MAX = NUM_MT76_TM_EEPROM_ACTION - 1,
2828+};
2829+
2830+/**
2831+ * enum mt76_testmode_cfg - packet tx phy mode
2832+ *
2833+ * @MT76_TM_EEPROM_ACTION_UPDATE_DATA: update rf values to specific
2834+ * eeprom data block
2835+ * @MT76_TM_EEPROM_ACTION_UPDATE_BUFFER_MODE: send updated eeprom data to fw
2836+ * @MT76_TM_EEPROM_ACTION_WRITE_TO_EFUSE: write eeprom data back to efuse
2837+ */
2838+enum mt76_testmode_cfg {
2839+ MT76_TM_CFG_TSSI,
2840+ MT76_TM_CFG_DPD,
2841+ MT76_TM_CFG_RATE_POWER_OFFSET,
2842+ MT76_TM_CFG_THERMAL_COMP,
2843+
2844+ /* keep last */
2845+ NUM_MT76_TM_CFG,
2846+ MT76_TM_CFG_MAX = NUM_MT76_TM_CFG - 1,
2847+};
2848+
2849+enum mt76_testmode_txbf_act {
2850+ MT76_TM_TXBF_ACT_INIT,
2851+ MT76_TM_TXBF_ACT_UPDATE_CH,
2852+ MT76_TM_TXBF_ACT_PHASE_COMP,
2853+ MT76_TM_TXBF_ACT_TX_PREP,
2854+ MT76_TM_TXBF_ACT_IBF_PROF_UPDATE,
2855+ MT76_TM_TXBF_ACT_EBF_PROF_UPDATE,
2856+ MT76_TM_TXBF_ACT_PHASE_CAL,
2857+ MT76_TM_TXBF_ACT_PROF_UPDATE_ALL,
2858+ MT76_TM_TXBF_ACT_E2P_UPDATE,
2859+
2860+ /* keep last */
2861+ NUM_MT76_TM_TXBF_ACT,
2862+ MT76_TM_TXBF_ACT_MAX = NUM_MT76_TM_TXBF_ACT - 1,
2863+};
2864+
2865 #endif
2866diff --git a/tools/fields.c b/tools/fields.c
developer62713c82023-03-20 10:46:08 +08002867index e3f6908..7e564a3 100644
developer4c6b6002022-05-30 16:36:44 +08002868--- a/tools/fields.c
2869+++ b/tools/fields.c
2870@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
2871 [MT76_TM_STATE_IDLE] = "idle",
2872 [MT76_TM_STATE_TX_FRAMES] = "tx_frames",
2873 [MT76_TM_STATE_RX_FRAMES] = "rx_frames",
2874+ [MT76_TM_STATE_TX_CONT] = "tx_cont",
2875 };
2876
2877 static const char * const testmode_tx_mode[] = {
developer62713c82023-03-20 10:46:08 +08002878@@ -86,12 +87,12 @@ static void print_s32(const struct tm_field *field, struct nlattr *attr)
2879
2880 static void print_u32(const struct tm_field *field, struct nlattr *attr)
2881 {
2882- printf("%d", nla_get_u32(attr));
2883+ printf("%u", nla_get_u32(attr));
2884 }
2885
2886 static void print_u64(const struct tm_field *field, struct nlattr *attr)
2887 {
2888- printf("%lld", (unsigned long long)nla_get_u64(attr));
2889+ printf("%llu", (unsigned long long)nla_get_u64(attr));
2890 }
2891
2892 static bool parse_flag(const struct tm_field *field, int idx,
developer4c6b6002022-05-30 16:36:44 +08002893@@ -201,6 +202,63 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2894 printf("%srx_per=%.02f%%\n", prefix, 100 * failed / total);
2895 }
2896
2897+static bool parse_mac(const struct tm_field *field, int idx,
2898+ struct nl_msg *msg, const char *val)
2899+{
2900+#define ETH_ALEN 6
2901+ bool ret = true;
2902+ char *str, *cur, *ap;
2903+ void *a;
2904+
2905+ ap = str = strdup(val);
2906+
2907+ a = nla_nest_start(msg, idx);
2908+
2909+ idx = 0;
2910+ while ((cur = strsep(&ap, ",")) != NULL) {
2911+ unsigned char addr[ETH_ALEN];
2912+ char *val, *tmp = cur;
2913+ int i = 0;
2914+
2915+ while ((val = strsep(&tmp, ":")) != NULL) {
2916+ if (i >= ETH_ALEN)
2917+ break;
2918+
2919+ addr[i++] = strtoul(val, NULL, 16);
2920+ }
2921+
2922+ nla_put(msg, idx, ETH_ALEN, addr);
2923+
2924+ idx++;
2925+ }
2926+
2927+ nla_nest_end(msg, a);
2928+
2929+ free(str);
2930+
2931+ return ret;
2932+}
2933+
2934+static void print_mac(const struct tm_field *field, struct nlattr *attr)
2935+{
2936+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
2937+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
2938+ unsigned char addr[3][6];
2939+ struct nlattr *cur;
2940+ int idx = 0;
2941+ int rem;
2942+
2943+ nla_for_each_nested(cur, attr, rem) {
2944+ if (nla_len(cur) != 6)
2945+ continue;
2946+ memcpy(addr[idx++], nla_data(cur), 6);
2947+ }
2948+
2949+ printf("" MACSTR "," MACSTR "," MACSTR "",
2950+ MAC2STR(addr[0]), MAC2STR(addr[1]), MAC2STR(addr[2]));
2951+
2952+ return;
2953+}
2954
2955 #define FIELD_GENERIC(_field, _name, ...) \
2956 [FIELD_NAME(_field)] = { \
2957@@ -250,6 +308,13 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
2958 ##__VA_ARGS__ \
2959 )
2960
2961+#define FIELD_MAC(_field, _name) \
2962+ [FIELD_NAME(_field)] = { \
2963+ .name = _name, \
2964+ .parse = parse_mac, \
2965+ .print = print_mac \
2966+ }
2967+
2968 #define FIELD_NAME(_field) MT76_TM_RX_ATTR_##_field
2969 static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
2970 FIELD_RO(s32, FREQ_OFFSET, "freq_offset"),
2971@@ -300,10 +365,18 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
2972 FIELD(u8, TX_RATE_LDPC, "tx_rate_ldpc"),
2973 FIELD(u8, TX_RATE_STBC, "tx_rate_stbc"),
2974 FIELD(u8, TX_LTF, "tx_ltf"),
2975+ FIELD(u8, TX_DUTY_CYCLE, "tx_duty_cycle"),
2976+ FIELD(u32, TX_IPG, "tx_ipg"),
2977+ FIELD(u32, TX_TIME, "tx_time"),
2978 FIELD(u8, TX_POWER_CONTROL, "tx_power_control"),
2979 FIELD_ARRAY(u8, TX_POWER, "tx_power"),
2980 FIELD(u8, TX_ANTENNA, "tx_antenna"),
2981+ FIELD(u8, TX_SPE_IDX, "tx_spe_idx"),
2982 FIELD(u32, FREQ_OFFSET, "freq_offset"),
2983+ FIELD(u8, AID, "aid"),
2984+ FIELD(u8, RU_ALLOC, "ru_alloc"),
2985+ FIELD(u8, RU_IDX, "ru_idx"),
2986+ FIELD_MAC(MAC_ADDRS, "mac_addrs"),
2987 FIELD_NESTED_RO(STATS, stats, "",
2988 .print_extra = print_extra_stats),
2989 };
2990@@ -322,9 +395,16 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
2991 [MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 },
2992 [MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
2993 [MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
2994+ [MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 },
2995+ [MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 },
2996+ [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
2997 [MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },
2998 [MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },
2999+ [MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 },
3000 [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
3001+ [MT76_TM_ATTR_AID] = { .type = NLA_U8 },
3002+ [MT76_TM_ATTR_RU_ALLOC] = { .type = NLA_U8 },
3003+ [MT76_TM_ATTR_RU_IDX] = { .type = NLA_U8 },
3004 [MT76_TM_ATTR_STATS] = { .type = NLA_NESTED },
3005 };
3006
3007diff --git a/tx.c b/tx.c
developer287ee9f2023-03-02 20:13:34 +08003008index 1f309d0..6d55566 100644
developer4c6b6002022-05-30 16:36:44 +08003009--- a/tx.c
3010+++ b/tx.c
developereb6a0182022-12-12 18:53:32 +08003011@@ -250,8 +250,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
developer4c6b6002022-05-30 16:36:44 +08003012 if (mt76_is_testmode_skb(dev, skb, &hw)) {
3013 struct mt76_phy *phy = hw->priv;
3014
3015- if (skb == phy->test.tx_skb)
3016- phy->test.tx_done++;
3017+ phy->test.tx_done++;
3018 if (phy->test.tx_queued == phy->test.tx_done)
3019 wake_up(&dev->tx_wait);
3020
3021--
developer4feb1012023-01-30 17:29:07 +080030222.18.0
developer4c6b6002022-05-30 16:36:44 +08003023