1// SPDX-License-Identifier: ISC
2/* Copyright (C) 2020 MediaTek Inc. */
3
4#include <linux/relay.h>
5#include "mt7915.h"
6#include "eeprom.h"
7#include "mcu.h"
8#include "mac.h"
9
10#define FW_BIN_LOG_MAGIC	0x44e98caf
11
12/** global debugfs **/
13
14struct hw_queue_map {
15	const char *name;
16	u8 index;
17	u8 pid;
18	u8 qid;
19};
20
21static int
22mt7915_implicit_txbf_set(void *data, u64 val)
23{
24	struct mt7915_dev *dev = data;
25
26	/* The existing connected stations shall reconnect to apply
27	 * new implicit txbf configuration.
28	 */
29	dev->ibf = !!val;
30
31	return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
32}
33
34static int
35mt7915_implicit_txbf_get(void *data, u64 *val)
36{
37	struct mt7915_dev *dev = data;
38
39	*val = dev->ibf;
40
41	return 0;
42}
43
44DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
45			 mt7915_implicit_txbf_set, "%lld\n");
46
47/* test knob of system error recovery */
48static ssize_t
49mt7915_sys_recovery_set(struct file *file, const char __user *user_buf,
50			size_t count, loff_t *ppos)
51{
52	struct mt7915_phy *phy = file->private_data;
53	struct mt7915_dev *dev = phy->dev;
54	bool band = phy->mt76->band_idx;
55	char buf[16];
56	int ret = 0;
57	u16 val;
58
59	if (count >= sizeof(buf))
60		return -EINVAL;
61
62	if (copy_from_user(buf, user_buf, count))
63		return -EFAULT;
64
65	if (count && buf[count - 1] == '\n')
66		buf[count - 1] = '\0';
67	else
68		buf[count] = '\0';
69
70	if (kstrtou16(buf, 0, &val))
71		return -EINVAL;
72
73	switch (val) {
74	/*
75	 * 0: grab firmware current SER state.
76	 * 1: trigger & enable system error L1 recovery.
77	 * 2: trigger & enable system error L2 recovery.
78	 * 3: trigger & enable system error L3 rx abort.
79	 * 4: trigger & enable system error L3 tx abort
80	 * 5: trigger & enable system error L3 tx disable.
81	 * 6: trigger & enable system error L3 bf recovery.
82	 * 7: trigger & enable system error full recovery.
83	 * 8: trigger firmware crash.
84	 */
85	case SER_QUERY:
86		ret = mt7915_mcu_set_ser(dev, 0, 0, band);
87		break;
88	case SER_SET_RECOVER_L1:
89	case SER_SET_RECOVER_L2:
90	case SER_SET_RECOVER_L3_RX_ABORT:
91	case SER_SET_RECOVER_L3_TX_ABORT:
92	case SER_SET_RECOVER_L3_TX_DISABLE:
93	case SER_SET_RECOVER_L3_BF:
94		ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), band);
95		if (ret)
96			return ret;
97
98		ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, band);
99		break;
100
101	/* enable full chip reset */
102	case SER_SET_RECOVER_FULL:
103		mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
104		ret = mt7915_mcu_set_ser(dev, 1, 3, band);
105		if (ret)
106			return ret;
107
108		dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
109		mt7915_reset(dev);
110		break;
111
112	/* WARNING: trigger firmware crash */
113	case SER_SET_SYSTEM_ASSERT:
114		mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR, BIT(18));
115		mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_SOFT_ADDR, BIT(18));
116		break;
117	default:
118		break;
119	}
120
121	return ret ? ret : count;
122}
123
124static ssize_t
125mt7915_sys_recovery_get(struct file *file, char __user *user_buf,
126			size_t count, loff_t *ppos)
127{
128	struct mt7915_phy *phy = file->private_data;
129	struct mt7915_dev *dev = phy->dev;
130	char *buff;
131	int desc = 0;
132	ssize_t ret;
133	static const size_t bufsz = 1024;
134
135	buff = kmalloc(bufsz, GFP_KERNEL);
136	if (!buff)
137		return -ENOMEM;
138
139	/* HELP */
140	desc += scnprintf(buff + desc, bufsz - desc,
141			  "Please echo the correct value ...\n");
142	desc += scnprintf(buff + desc, bufsz - desc,
143			  "0: grab firmware transient SER state\n");
144	desc += scnprintf(buff + desc, bufsz - desc,
145			  "1: trigger system error L1 recovery\n");
146	desc += scnprintf(buff + desc, bufsz - desc,
147			  "2: trigger system error L2 recovery\n");
148	desc += scnprintf(buff + desc, bufsz - desc,
149			  "3: trigger system error L3 rx abort\n");
150	desc += scnprintf(buff + desc, bufsz - desc,
151			  "4: trigger system error L3 tx abort\n");
152	desc += scnprintf(buff + desc, bufsz - desc,
153			  "5: trigger system error L3 tx disable\n");
154	desc += scnprintf(buff + desc, bufsz - desc,
155			  "6: trigger system error L3 bf recovery\n");
156	desc += scnprintf(buff + desc, bufsz - desc,
157			  "7: trigger system error full recovery\n");
158	desc += scnprintf(buff + desc, bufsz - desc,
159			  "8: trigger firmware crash\n");
160
161	/* SER statistics */
162	desc += scnprintf(buff + desc, bufsz - desc,
163			  "\nlet's dump firmware SER statistics...\n");
164	desc += scnprintf(buff + desc, bufsz - desc,
165			  "::E  R , SER_STATUS        = 0x%08x\n",
166			  mt76_rr(dev, MT_SWDEF_SER_STATS));
167	desc += scnprintf(buff + desc, bufsz - desc,
168			  "::E  R , SER_PLE_ERR       = 0x%08x\n",
169			  mt76_rr(dev, MT_SWDEF_PLE_STATS));
170	desc += scnprintf(buff + desc, bufsz - desc,
171			  "::E  R , SER_PLE_ERR_1     = 0x%08x\n",
172			  mt76_rr(dev, MT_SWDEF_PLE1_STATS));
173	desc += scnprintf(buff + desc, bufsz - desc,
174			  "::E  R , SER_PLE_ERR_AMSDU = 0x%08x\n",
175			  mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
176	desc += scnprintf(buff + desc, bufsz - desc,
177			  "::E  R , SER_PSE_ERR       = 0x%08x\n",
178			  mt76_rr(dev, MT_SWDEF_PSE_STATS));
179	desc += scnprintf(buff + desc, bufsz - desc,
180			  "::E  R , SER_PSE_ERR_1     = 0x%08x\n",
181			  mt76_rr(dev, MT_SWDEF_PSE1_STATS));
182	desc += scnprintf(buff + desc, bufsz - desc,
183			  "::E  R , SER_LMAC_WISR6_B0 = 0x%08x\n",
184			  mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
185	desc += scnprintf(buff + desc, bufsz - desc,
186			  "::E  R , SER_LMAC_WISR6_B1 = 0x%08x\n",
187			  mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
188	desc += scnprintf(buff + desc, bufsz - desc,
189			  "::E  R , SER_LMAC_WISR7_B0 = 0x%08x\n",
190			  mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
191	desc += scnprintf(buff + desc, bufsz - desc,
192			  "::E  R , SER_LMAC_WISR7_B1 = 0x%08x\n",
193			  mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
194	desc += scnprintf(buff + desc, bufsz - desc,
195			  "\nSYS_RESET_COUNT: WM %d, WA %d\n",
196			  dev->recovery.wm_reset_count,
197			  dev->recovery.wa_reset_count);
198
199	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
200	kfree(buff);
201	return ret;
202}
203
204static const struct file_operations mt7915_sys_recovery_ops = {
205	.write = mt7915_sys_recovery_set,
206	.read = mt7915_sys_recovery_get,
207	.open = simple_open,
208	.llseek = default_llseek,
209};
210
211static int
212mt7915_radar_trigger(void *data, u64 val)
213{
214	struct mt7915_dev *dev = data;
215
216	if (val > MT_RX_SEL2)
217		return -EINVAL;
218
219	return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE,
220				       val, 0, 0);
221}
222
223DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
224			 mt7915_radar_trigger, "%lld\n");
225
226static int
227mt7915_muru_debug_set(void *data, u64 val)
228{
229	struct mt7915_dev *dev = data;
230
231	dev->muru_debug = val;
232	mt7915_mcu_muru_debug_set(dev, dev->muru_debug);
233
234	return 0;
235}
236
237static int
238mt7915_muru_debug_get(void *data, u64 *val)
239{
240	struct mt7915_dev *dev = data;
241
242	*val = dev->muru_debug;
243
244	return 0;
245}
246
247DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_debug, mt7915_muru_debug_get,
248			 mt7915_muru_debug_set, "%lld\n");
249
250static int mt7915_muru_stats_show(struct seq_file *file, void *data)
251{
252	struct mt7915_phy *phy = file->private;
253	struct mt7915_dev *dev = phy->dev;
254	static const char * const dl_non_he_type[] = {
255		"CCK", "OFDM", "HT MIX", "HT GF",
256		"VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU"
257	};
258	static const char * const dl_he_type[] = {
259		"HE SU", "HE EXT", "HE 2MU", "HE 3MU", "HE 4MU",
260		"HE 2RU", "HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU",
261		"HE >16RU"
262	};
263	static const char * const ul_he_type[] = {
264		"HE 2MU", "HE 3MU", "HE 4MU", "HE SU", "HE 2RU",
265		"HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU", "HE >16RU"
266	};
267	int ret, i;
268	u64 total_ppdu_cnt, sub_total_cnt;
269
270	if (!dev->muru_debug) {
271		seq_puts(file, "Please enable muru_debug first.\n");
272		return 0;
273	}
274
275	mutex_lock(&dev->mt76.mutex);
276
277	ret = mt7915_mcu_muru_debug_get(phy);
278	if (ret)
279		goto exit;
280
281	/* Non-HE Downlink*/
282	seq_puts(file, "[Non-HE]\nDownlink\nData Type:  ");
283
284	for (i = 0; i < 5; i++)
285		seq_printf(file, "%8s | ", dl_non_he_type[i]);
286
287	seq_puts(file, "\nTotal Count:");
288	seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ",
289		   phy->mib.dl_cck_cnt,
290		   phy->mib.dl_ofdm_cnt,
291		   phy->mib.dl_htmix_cnt,
292		   phy->mib.dl_htgf_cnt,
293		   phy->mib.dl_vht_su_cnt);
294
295	seq_puts(file, "\nDownlink MU-MIMO\nData Type:  ");
296
297	for (i = 5; i < 8; i++)
298		seq_printf(file, "%8s | ", dl_non_he_type[i]);
299
300	seq_puts(file, "\nTotal Count:");
301	seq_printf(file, "%8u | %8u | %8u | ",
302		   phy->mib.dl_vht_2mu_cnt,
303		   phy->mib.dl_vht_3mu_cnt,
304		   phy->mib.dl_vht_4mu_cnt);
305
306	sub_total_cnt = phy->mib.dl_vht_2mu_cnt +
307			phy->mib.dl_vht_3mu_cnt +
308			phy->mib.dl_vht_4mu_cnt;
309
310	seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld",
311		   sub_total_cnt);
312
313	total_ppdu_cnt = sub_total_cnt +
314			 phy->mib.dl_cck_cnt +
315			 phy->mib.dl_ofdm_cnt +
316			 phy->mib.dl_htmix_cnt +
317			 phy->mib.dl_htgf_cnt +
318			 phy->mib.dl_vht_su_cnt;
319
320	seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt);
321
322	/* HE Downlink */
323	seq_puts(file, "\n\n[HE]\nDownlink\nData Type:  ");
324
325	for (i = 0; i < 2; i++)
326		seq_printf(file, "%8s | ", dl_he_type[i]);
327
328	seq_puts(file, "\nTotal Count:");
329	seq_printf(file, "%8u | %8u | ",
330		   phy->mib.dl_he_su_cnt, phy->mib.dl_he_ext_su_cnt);
331
332	seq_puts(file, "\nDownlink MU-MIMO\nData Type:  ");
333
334	for (i = 2; i < 5; i++)
335		seq_printf(file, "%8s | ", dl_he_type[i]);
336
337	seq_puts(file, "\nTotal Count:");
338	seq_printf(file, "%8u | %8u | %8u | ",
339		   phy->mib.dl_he_2mu_cnt, phy->mib.dl_he_3mu_cnt,
340		   phy->mib.dl_he_4mu_cnt);
341
342	seq_puts(file, "\nDownlink OFDMA\nData Type:  ");
343
344	for (i = 5; i < 11; i++)
345		seq_printf(file, "%8s | ", dl_he_type[i]);
346
347	seq_puts(file, "\nTotal Count:");
348	seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ",
349		   phy->mib.dl_he_2ru_cnt,
350		   phy->mib.dl_he_3ru_cnt,
351		   phy->mib.dl_he_4ru_cnt,
352		   phy->mib.dl_he_5to8ru_cnt,
353		   phy->mib.dl_he_9to16ru_cnt,
354		   phy->mib.dl_he_gtr16ru_cnt);
355
356	sub_total_cnt = phy->mib.dl_he_2mu_cnt +
357			phy->mib.dl_he_3mu_cnt +
358			phy->mib.dl_he_4mu_cnt;
359	total_ppdu_cnt = sub_total_cnt;
360
361	seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld",
362		   sub_total_cnt);
363
364	sub_total_cnt = phy->mib.dl_he_2ru_cnt +
365			phy->mib.dl_he_3ru_cnt +
366			phy->mib.dl_he_4ru_cnt +
367			phy->mib.dl_he_5to8ru_cnt +
368			phy->mib.dl_he_9to16ru_cnt +
369			phy->mib.dl_he_gtr16ru_cnt;
370	total_ppdu_cnt += sub_total_cnt;
371
372	seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld",
373		   sub_total_cnt);
374
375	total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt;
376
377	seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt);
378
379	/* HE Uplink */
380	seq_puts(file, "\n\nUplink");
381	seq_puts(file, "\nTrigger-based Uplink MU-MIMO\nData Type:  ");
382
383	for (i = 0; i < 3; i++)
384		seq_printf(file, "%8s | ", ul_he_type[i]);
385
386	seq_puts(file, "\nTotal Count:");
387	seq_printf(file, "%8u | %8u | %8u | ",
388		   phy->mib.ul_hetrig_2mu_cnt,
389		   phy->mib.ul_hetrig_3mu_cnt,
390		   phy->mib.ul_hetrig_4mu_cnt);
391
392	seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type:  ");
393
394	for (i = 3; i < 10; i++)
395		seq_printf(file, "%8s | ", ul_he_type[i]);
396
397	seq_puts(file, "\nTotal Count:");
398	seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u |  %7u | ",
399		   phy->mib.ul_hetrig_su_cnt,
400		   phy->mib.ul_hetrig_2ru_cnt,
401		   phy->mib.ul_hetrig_3ru_cnt,
402		   phy->mib.ul_hetrig_4ru_cnt,
403		   phy->mib.ul_hetrig_5to8ru_cnt,
404		   phy->mib.ul_hetrig_9to16ru_cnt,
405		   phy->mib.ul_hetrig_gtr16ru_cnt);
406
407	sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt +
408			phy->mib.ul_hetrig_3mu_cnt +
409			phy->mib.ul_hetrig_4mu_cnt;
410	total_ppdu_cnt = sub_total_cnt;
411
412	seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld",
413		   sub_total_cnt);
414
415	sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt +
416			phy->mib.ul_hetrig_3ru_cnt +
417			phy->mib.ul_hetrig_4ru_cnt +
418			phy->mib.ul_hetrig_5to8ru_cnt +
419			phy->mib.ul_hetrig_9to16ru_cnt +
420			phy->mib.ul_hetrig_gtr16ru_cnt;
421	total_ppdu_cnt += sub_total_cnt;
422
423	seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld",
424		   sub_total_cnt);
425
426	total_ppdu_cnt += phy->mib.ul_hetrig_su_cnt;
427
428	seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt);
429
430exit:
431	mutex_unlock(&dev->mt76.mutex);
432
433	return ret;
434}
435DEFINE_SHOW_ATTRIBUTE(mt7915_muru_stats);
436
437static int
438mt7915_rdd_monitor(struct seq_file *s, void *data)
439{
440	struct mt7915_dev *dev = dev_get_drvdata(s->private);
441	struct cfg80211_chan_def *chandef = &dev->rdd2_chandef;
442	const char *bw;
443	int ret = 0;
444
445	mutex_lock(&dev->mt76.mutex);
446
447	if (!cfg80211_chandef_valid(chandef)) {
448		ret = -EINVAL;
449		goto out;
450	}
451
452	if (!dev->rdd2_phy) {
453		seq_puts(s, "not running\n");
454		goto out;
455	}
456
457	switch (chandef->width) {
458	case NL80211_CHAN_WIDTH_40:
459		bw = "40";
460		break;
461	case NL80211_CHAN_WIDTH_80:
462		bw = "80";
463		break;
464	case NL80211_CHAN_WIDTH_160:
465		bw = "160";
466		break;
467	case NL80211_CHAN_WIDTH_80P80:
468		bw = "80P80";
469		break;
470	default:
471		bw = "20";
472		break;
473	}
474
475	seq_printf(s, "channel %d (%d MHz) width %s MHz center1: %d MHz\n",
476		   chandef->chan->hw_value, chandef->chan->center_freq,
477		   bw, chandef->center_freq1);
478out:
479	mutex_unlock(&dev->mt76.mutex);
480
481	return ret;
482}
483
484static int
485mt7915_fw_debug_wm_set(void *data, u64 val)
486{
487	struct mt7915_dev *dev = data;
488	enum {
489		DEBUG_TXCMD = 62,
490		DEBUG_CMD_RPT_TX,
491		DEBUG_CMD_RPT_TRIG,
492		DEBUG_SPL,
493		DEBUG_RPT_RX,
494	} debug;
495	bool tx, rx, en;
496	int ret;
497
498	dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
499
500	if (dev->fw.debug_bin)
501		val = 16;
502	else
503		val = dev->fw.debug_wm;
504
505	tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1));
506	rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2));
507	en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0));
508
509	ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val);
510	if (ret)
511		goto out;
512
513	for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) {
514		if (debug == DEBUG_RPT_RX)
515			val = en && rx;
516		else
517			val = en && tx;
518
519		ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val);
520		if (ret)
521			goto out;
522	}
523
524	/* WM CPU info record control */
525	mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
526	mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm);
527	mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
528	mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
529
530out:
531	if (ret)
532		dev->fw.debug_wm = 0;
533
534	return ret;
535}
536
537static int
538mt7915_fw_debug_wm_get(void *data, u64 *val)
539{
540	struct mt7915_dev *dev = data;
541
542	*val = dev->fw.debug_wm;
543
544	return 0;
545}
546
547DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wm, mt7915_fw_debug_wm_get,
548			 mt7915_fw_debug_wm_set, "%lld\n");
549
550static int
551mt7915_fw_debug_wa_set(void *data, u64 val)
552{
553	struct mt7915_dev *dev = data;
554	int ret;
555
556	dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
557
558	ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa);
559	if (ret)
560		goto out;
561
562	ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
563				MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0);
564out:
565	if (ret)
566		dev->fw.debug_wa = 0;
567
568	return ret;
569}
570
571static int
572mt7915_fw_debug_wa_get(void *data, u64 *val)
573{
574	struct mt7915_dev *dev = data;
575
576	*val = dev->fw.debug_wa;
577
578	return 0;
579}
580
581DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wa, mt7915_fw_debug_wa_get,
582			 mt7915_fw_debug_wa_set, "%lld\n");
583
584static struct dentry *
585create_buf_file_cb(const char *filename, struct dentry *parent, umode_t mode,
586		   struct rchan_buf *buf, int *is_global)
587{
588	struct dentry *f;
589
590	f = debugfs_create_file("fwlog_data", mode, parent, buf,
591				&relay_file_operations);
592	if (IS_ERR(f))
593		return NULL;
594
595	*is_global = 1;
596
597	return f;
598}
599
600static int
601remove_buf_file_cb(struct dentry *f)
602{
603	debugfs_remove(f);
604
605	return 0;
606}
607
608static int
609mt7915_fw_debug_bin_set(void *data, u64 val)
610{
611	static struct rchan_callbacks relay_cb = {
612		.create_buf_file = create_buf_file_cb,
613		.remove_buf_file = remove_buf_file_cb,
614	};
615	struct mt7915_dev *dev = data;
616
617	if (!dev->relay_fwlog)
618		dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir,
619					    1500, 512, &relay_cb, NULL);
620	if (!dev->relay_fwlog)
621		return -ENOMEM;
622
623	dev->fw.debug_bin = val;
624
625	relay_reset(dev->relay_fwlog);
626
627	return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm);
628}
629
630static int
631mt7915_fw_debug_bin_get(void *data, u64 *val)
632{
633	struct mt7915_dev *dev = data;
634
635	*val = dev->fw.debug_bin;
636
637	return 0;
638}
639
640DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_bin, mt7915_fw_debug_bin_get,
641			 mt7915_fw_debug_bin_set, "%lld\n");
642
643static int
644mt7915_fw_util_wm_show(struct seq_file *file, void *data)
645{
646	struct mt7915_dev *dev = file->private;
647
648	seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC));
649
650	if (dev->fw.debug_wm) {
651		seq_printf(file, "Busy: %u%%  Peak busy: %u%%\n",
652			   mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT),
653			   mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT));
654		seq_printf(file, "Idle count: %u  Peak idle count: %u\n",
655			   mt76_rr(dev, MT_CPU_UTIL_IDLE_CNT),
656			   mt76_rr(dev, MT_CPU_UTIL_PEAK_IDLE_CNT));
657	}
658
659	return 0;
660}
661
662DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wm);
663
664static int
665mt7915_fw_util_wa_show(struct seq_file *file, void *data)
666{
667	struct mt7915_dev *dev = file->private;
668
669	seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC));
670
671	if (dev->fw.debug_wa)
672		return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY),
673					 MCU_WA_PARAM_CPU_UTIL, 0, 0);
674
675	return 0;
676}
677
678DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wa);
679
680static void
681mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
682			   struct seq_file *file)
683{
684	struct mt7915_dev *dev = phy->dev;
685	bool ext_phy = phy != &dev->phy;
686	int bound[15], range[4], i;
687	u8 band = phy->mt76->band_idx;
688
689	/* Tx ampdu stat */
690	for (i = 0; i < ARRAY_SIZE(range); i++)
691		range[i] = mt76_rr(dev, MT_MIB_ARNG(band, i));
692
693	for (i = 0; i < ARRAY_SIZE(bound); i++)
694		bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
695
696	seq_printf(file, "\nPhy %d, Phy band %d\n", ext_phy, band);
697
698	seq_printf(file, "Length: %8d | ", bound[0]);
699	for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
700		seq_printf(file, "%3d -%3d | ",
701			   bound[i] + 1, bound[i + 1]);
702
703	seq_puts(file, "\nCount:  ");
704	for (i = 0; i < ARRAY_SIZE(bound); i++)
705		seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);
706	seq_puts(file, "\n");
707
708	seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
709}
710
711static void
712mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
713{
714	struct mt76_mib_stats *mib = &phy->mib;
715	static const char * const bw[] = {
716		"BW20", "BW40", "BW80", "BW160"
717	};
718
719	/* Tx Beamformer monitor */
720	seq_puts(s, "\nTx Beamformer applied PPDU counts: ");
721
722	seq_printf(s, "iBF: %d, eBF: %d\n",
723		   mib->tx_bf_ibf_ppdu_cnt,
724		   mib->tx_bf_ebf_ppdu_cnt);
725
726	/* Tx Beamformer Rx feedback monitor */
727	seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
728
729	seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",
730		   mib->tx_bf_rx_fb_all_cnt,
731		   mib->tx_bf_rx_fb_he_cnt,
732		   mib->tx_bf_rx_fb_vht_cnt,
733		   mib->tx_bf_rx_fb_ht_cnt);
734
735	seq_printf(s, "%s, NC: %d, NR: %d\n",
736		   bw[mib->tx_bf_rx_fb_bw],
737		   mib->tx_bf_rx_fb_nc_cnt,
738		   mib->tx_bf_rx_fb_nr_cnt);
739
740	/* Tx Beamformee Rx NDPA & Tx feedback report */
741	seq_printf(s, "Tx Beamformee successful feedback frames: %d\n",
742		   mib->tx_bf_fb_cpl_cnt);
743	seq_printf(s, "Tx Beamformee feedback triggered counts: %d\n",
744		   mib->tx_bf_fb_trig_cnt);
745
746	/* Tx SU & MU counters */
747	seq_printf(s, "Tx multi-user Beamforming counts: %d\n",
748		   mib->tx_bf_cnt);
749	seq_printf(s, "Tx multi-user MPDU counts: %d\n", mib->tx_mu_mpdu_cnt);
750	seq_printf(s, "Tx multi-user successful MPDU counts: %d\n",
751		   mib->tx_mu_acked_mpdu_cnt);
752	seq_printf(s, "Tx single-user successful MPDU counts: %d\n",
753		   mib->tx_su_acked_mpdu_cnt);
754
755	seq_puts(s, "\n");
756}
757
758static int
759mt7915_tx_stats_show(struct seq_file *file, void *data)
760{
761	struct mt7915_phy *phy = file->private;
762	struct mt7915_dev *dev = phy->dev;
763	struct mt76_mib_stats *mib = &phy->mib;
764	int i;
765
766	mutex_lock(&dev->mt76.mutex);
767
768	mt7915_ampdu_stat_read_phy(phy, file);
769	mt7915_mac_update_stats(phy);
770	mt7915_txbf_stat_read_phy(phy, file);
771
772	/* Tx amsdu info */
773	seq_puts(file, "Tx MSDU statistics:\n");
774	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
775		seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
776			   i + 1, mib->tx_amsdu[i]);
777		if (mib->tx_amsdu_cnt)
778			seq_printf(file, "(%3d%%)\n",
779				   mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
780		else
781			seq_puts(file, "\n");
782	}
783
784	mutex_unlock(&dev->mt76.mutex);
785
786	return 0;
787}
788
789DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats);
790
791static void
792mt7915_hw_queue_read(struct seq_file *s, u32 size,
793		     const struct hw_queue_map *map)
794{
795	struct mt7915_phy *phy = s->private;
796	struct mt7915_dev *dev = phy->dev;
797	u32 i, val;
798
799	val = mt76_rr(dev, MT_FL_Q_EMPTY);
800	for (i = 0; i < size; i++) {
801		u32 ctrl, head, tail, queued;
802
803		if (val & BIT(map[i].index))
804			continue;
805
806		ctrl = BIT(31) | (map[i].pid << 10) | ((u32)map[i].qid << 24);
807		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl);
808
809		head = mt76_get_field(dev, MT_FL_Q2_CTRL,
810				      GENMASK(11, 0));
811		tail = mt76_get_field(dev, MT_FL_Q2_CTRL,
812				      GENMASK(27, 16));
813		queued = mt76_get_field(dev, MT_FL_Q3_CTRL,
814					GENMASK(11, 0));
815
816		seq_printf(s, "\t%s: ", map[i].name);
817		seq_printf(s, "queued:0x%03x head:0x%03x tail:0x%03x\n",
818			   queued, head, tail);
819	}
820}
821
822static void
823mt7915_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
824{
825	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
826	struct mt7915_dev *dev = msta->vif->phy->dev;
827	struct seq_file *s = data;
828	u8 ac;
829
830	for (ac = 0; ac < 4; ac++) {
831		u32 qlen, ctrl, val;
832		u32 idx = msta->wcid.idx >> 5;
833		u8 offs = msta->wcid.idx & GENMASK(4, 0);
834
835		ctrl = BIT(31) | BIT(11) | (ac << 24);
836		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
837
838		if (val & BIT(offs))
839			continue;
840
841		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx);
842		qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
843				      GENMASK(11, 0));
844		seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
845			   sta->addr, msta->wcid.idx,
846			   msta->vif->mt76.wmm_idx, ac, qlen);
847	}
848}
849
850static int
851mt7915_hw_queues_show(struct seq_file *file, void *data)
852{
853	struct mt7915_phy *phy = file->private;
854	struct mt7915_dev *dev = phy->dev;
855	static const struct hw_queue_map ple_queue_map[] = {
856		{ "CPU_Q0",  0,  1, MT_CTX0	      },
857		{ "CPU_Q1",  1,  1, MT_CTX0 + 1	      },
858		{ "CPU_Q2",  2,  1, MT_CTX0 + 2	      },
859		{ "CPU_Q3",  3,  1, MT_CTX0 + 3	      },
860		{ "ALTX_Q0", 8,  2, MT_LMAC_ALTX0     },
861		{ "BMC_Q0",  9,  2, MT_LMAC_BMC0      },
862		{ "BCN_Q0",  10, 2, MT_LMAC_BCN0      },
863		{ "PSMP_Q0", 11, 2, MT_LMAC_PSMP0     },
864		{ "ALTX_Q1", 12, 2, MT_LMAC_ALTX0 + 4 },
865		{ "BMC_Q1",  13, 2, MT_LMAC_BMC0  + 4 },
866		{ "BCN_Q1",  14, 2, MT_LMAC_BCN0  + 4 },
867		{ "PSMP_Q1", 15, 2, MT_LMAC_PSMP0 + 4 },
868	};
869	static const struct hw_queue_map pse_queue_map[] = {
870		{ "CPU Q0",  0,  1, MT_CTX0	      },
871		{ "CPU Q1",  1,  1, MT_CTX0 + 1	      },
872		{ "CPU Q2",  2,  1, MT_CTX0 + 2	      },
873		{ "CPU Q3",  3,  1, MT_CTX0 + 3	      },
874		{ "HIF_Q0",  8,  0, MT_HIF0	      },
875		{ "HIF_Q1",  9,  0, MT_HIF0 + 1	      },
876		{ "HIF_Q2",  10, 0, MT_HIF0 + 2	      },
877		{ "HIF_Q3",  11, 0, MT_HIF0 + 3	      },
878		{ "HIF_Q4",  12, 0, MT_HIF0 + 4	      },
879		{ "HIF_Q5",  13, 0, MT_HIF0 + 5	      },
880		{ "LMAC_Q",  16, 2, 0		      },
881		{ "MDP_TXQ", 17, 2, 1		      },
882		{ "MDP_RXQ", 18, 2, 2		      },
883		{ "SEC_TXQ", 19, 2, 3		      },
884		{ "SEC_RXQ", 20, 2, 4		      },
885	};
886	u32 val, head, tail;
887
888	/* ple queue */
889	val = mt76_rr(dev, MT_PLE_FREEPG_CNT);
890	head = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(11, 0));
891	tail = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(27, 16));
892	seq_puts(file, "PLE page info:\n");
893	seq_printf(file,
894		   "\tTotal free page: 0x%08x head: 0x%03x tail: 0x%03x\n",
895		   val, head, tail);
896
897	val = mt76_rr(dev, MT_PLE_PG_HIF_GROUP);
898	head = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(11, 0));
899	tail = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(27, 16));
900	seq_printf(file, "\tHIF free page: 0x%03x res: 0x%03x used: 0x%03x\n",
901		   val, head, tail);
902
903	seq_puts(file, "PLE non-empty queue info:\n");
904	mt7915_hw_queue_read(file, ARRAY_SIZE(ple_queue_map),
905			     &ple_queue_map[0]);
906
907	/* iterate per-sta ple queue */
908	ieee80211_iterate_stations_atomic(phy->mt76->hw,
909					  mt7915_sta_hw_queue_read, file);
910	/* pse queue */
911	seq_puts(file, "PSE non-empty queue info:\n");
912	mt7915_hw_queue_read(file, ARRAY_SIZE(pse_queue_map),
913			     &pse_queue_map[0]);
914
915	return 0;
916}
917
918DEFINE_SHOW_ATTRIBUTE(mt7915_hw_queues);
919
920static int
921mt7915_xmit_queues_show(struct seq_file *file, void *data)
922{
923	struct mt7915_phy *phy = file->private;
924	struct mt7915_dev *dev = phy->dev;
925	struct {
926		struct mt76_queue *q;
927		char *queue;
928	} queue_map[] = {
929		{ phy->mt76->q_tx[MT_TXQ_BE],	 "   MAIN"  },
930		{ dev->mt76.q_mcu[MT_MCUQ_WM],	 "  MCUWM"  },
931		{ dev->mt76.q_mcu[MT_MCUQ_WA],	 "  MCUWA"  },
932		{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWDL" },
933	};
934	int i;
935
936	seq_puts(file, "     queue | hw-queued |      head |      tail |\n");
937	for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
938		struct mt76_queue *q = queue_map[i].q;
939
940		if (!q)
941			continue;
942
943		seq_printf(file, "   %s | %9d | %9d | %9d |\n",
944			   queue_map[i].queue, q->queued, q->head,
945			   q->tail);
946	}
947
948	return 0;
949}
950
951DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
952
953#define mt7915_txpower_puts(rate)						\
954({										\
955	len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)");	\
956	for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++)		\
957		len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]);	\
958	len += scnprintf(buf + len, sz - len, "\n");				\
959})
960
961#define mt7915_txpower_sets(rate, pwr, flag)			\
962({								\
963	offs += len;						\
964	len = mt7915_sku_group_len[rate];			\
965	if (mode == flag) {					\
966		for (i = 0; i < len; i++)			\
967			req.txpower_sku[offs + i] = pwr;	\
968	}							\
969})
970
971static ssize_t
972mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
973			size_t count, loff_t *ppos)
974{
975	struct mt7915_phy *phy = file->private_data;
976	struct mt7915_dev *dev = phy->dev;
977	s8 txpwr[MT7915_SKU_RATE_NUM];
978	static const size_t sz = 2048;
979	u8 band = phy->mt76->band_idx;
980	int i, offs = 0, len = 0;
981	ssize_t ret;
982	char *buf;
983	u32 reg;
984
985	buf = kzalloc(sz, GFP_KERNEL);
986	if (!buf)
987		return -ENOMEM;
988
989	ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr));
990	if (ret)
991		goto out;
992
993	/* Txpower propagation path: TMAC -> TXV -> BBP */
994	len += scnprintf(buf + len, sz - len,
995			 "\nPhy%d Tx power table (channel %d)\n",
996			 phy != &dev->phy, phy->mt76->chandef.chan->hw_value);
997	len += scnprintf(buf + len, sz - len, "%-16s  %6s %6s %6s %6s\n",
998			 " ", "1m", "2m", "5m", "11m");
999	mt7915_txpower_puts(CCK);
1000
1001	len += scnprintf(buf + len, sz - len,
1002			 "%-16s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
1003			 " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
1004			 "54m");
1005	mt7915_txpower_puts(OFDM);
1006
1007	len += scnprintf(buf + len, sz - len,
1008			 "%-16s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
1009			 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
1010			 "mcs5", "mcs6", "mcs7");
1011	mt7915_txpower_puts(HT_BW20);
1012
1013	len += scnprintf(buf + len, sz - len,
1014			 "%-16s  %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
1015			 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
1016			 "mcs6", "mcs7", "mcs32");
1017	mt7915_txpower_puts(HT_BW40);
1018
1019	len += scnprintf(buf + len, sz - len,
1020			 "%-16s  %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
1021			 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
1022			 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
1023	mt7915_txpower_puts(VHT_BW20);
1024	mt7915_txpower_puts(VHT_BW40);
1025	mt7915_txpower_puts(VHT_BW80);
1026	mt7915_txpower_puts(VHT_BW160);
1027	mt7915_txpower_puts(HE_RU26);
1028	mt7915_txpower_puts(HE_RU52);
1029	mt7915_txpower_puts(HE_RU106);
1030	mt7915_txpower_puts(HE_RU242);
1031	mt7915_txpower_puts(HE_RU484);
1032	mt7915_txpower_puts(HE_RU996);
1033	mt7915_txpower_puts(HE_RU2x996);
1034
1035	reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) :
1036	      MT_WF_PHY_TPC_CTRL_STAT_MT7916(band);
1037
1038	len += scnprintf(buf + len, sz - len, "\nTx power (bbp)  : %6ld\n",
1039			 mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER));
1040
1041	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1042
1043out:
1044	kfree(buf);
1045	return ret;
1046}
1047
1048static ssize_t
1049mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
1050			size_t count, loff_t *ppos)
1051{
1052	struct mt7915_phy *phy = file->private_data;
1053	struct mt7915_dev *dev = phy->dev;
1054	struct mt76_phy *mphy = phy->mt76;
1055	struct mt7915_mcu_txpower_sku req = {
1056		.format_id = TX_POWER_LIMIT_TABLE,
1057		.band_idx = phy->mt76->band_idx,
1058	};
1059	char buf[100];
1060	int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
1061	enum mac80211_rx_encoding mode;
1062	u32 offs = 0, len = 0;
1063
1064	if (count >= sizeof(buf))
1065		return -EINVAL;
1066
1067	if (copy_from_user(buf, user_buf, count))
1068		return -EFAULT;
1069
1070	if (count && buf[count - 1] == '\n')
1071		buf[count - 1] = '\0';
1072	else
1073		buf[count] = '\0';
1074
1075	if (sscanf(buf, "%u %u %u %u %u",
1076		   &mode, &pwr160, &pwr80, &pwr40, &pwr20) != 5) {
1077		dev_warn(dev->mt76.dev,
1078			 "per bandwidth power limit: Mode BW160 BW80 BW40 BW20");
1079		return -EINVAL;
1080	}
1081
1082	if (mode > RX_ENC_HE)
1083		return -EINVAL;
1084
1085	if (pwr160)
1086		pwr160 = mt7915_get_power_bound(phy, pwr160);
1087	if (pwr80)
1088		pwr80 = mt7915_get_power_bound(phy, pwr80);
1089	if (pwr40)
1090		pwr40 = mt7915_get_power_bound(phy, pwr40);
1091	if (pwr20)
1092		pwr20 = mt7915_get_power_bound(phy, pwr20);
1093
1094	if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0)
1095		return -EINVAL;
1096
1097	mutex_lock(&dev->mt76.mutex);
1098	ret = mt7915_mcu_get_txpower_sku(phy, req.txpower_sku,
1099					 sizeof(req.txpower_sku));
1100	if (ret)
1101		goto out;
1102
1103	mt7915_txpower_sets(SKU_CCK, pwr20, RX_ENC_LEGACY);
1104	mt7915_txpower_sets(SKU_OFDM, pwr20, RX_ENC_LEGACY);
1105	if (mode == RX_ENC_LEGACY)
1106		goto skip;
1107
1108	mt7915_txpower_sets(SKU_HT_BW20, pwr20, RX_ENC_HT);
1109	mt7915_txpower_sets(SKU_HT_BW40, pwr40, RX_ENC_HT);
1110	if (mode == RX_ENC_HT)
1111		goto skip;
1112
1113	mt7915_txpower_sets(SKU_VHT_BW20, pwr20, RX_ENC_VHT);
1114	mt7915_txpower_sets(SKU_VHT_BW40, pwr40, RX_ENC_VHT);
1115	mt7915_txpower_sets(SKU_VHT_BW80, pwr80, RX_ENC_VHT);
1116	mt7915_txpower_sets(SKU_VHT_BW160, pwr160, RX_ENC_VHT);
1117	if (mode == RX_ENC_VHT)
1118		goto skip;
1119
1120	mt7915_txpower_sets(SKU_HE_RU26, pwr20, RX_ENC_HE + 1);
1121	mt7915_txpower_sets(SKU_HE_RU52, pwr20, RX_ENC_HE + 1);
1122	mt7915_txpower_sets(SKU_HE_RU106, pwr20, RX_ENC_HE + 1);
1123	mt7915_txpower_sets(SKU_HE_RU242, pwr20, RX_ENC_HE);
1124	mt7915_txpower_sets(SKU_HE_RU484, pwr40, RX_ENC_HE);
1125	mt7915_txpower_sets(SKU_HE_RU996, pwr80, RX_ENC_HE);
1126	mt7915_txpower_sets(SKU_HE_RU2x996, pwr160, RX_ENC_HE);
1127skip:
1128	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
1129				&req, sizeof(req), true);
1130	if (ret)
1131		goto out;
1132
1133	mphy->txpower_cur = max(mphy->txpower_cur,
1134				max(pwr160, max(pwr80, max(pwr40, pwr20))));
1135out:
1136	mutex_unlock(&dev->mt76.mutex);
1137
1138	return ret ? ret : count;
1139}
1140
1141static const struct file_operations mt7915_rate_txpower_fops = {
1142	.write = mt7915_rate_txpower_set,
1143	.read = mt7915_rate_txpower_get,
1144	.open = simple_open,
1145	.owner = THIS_MODULE,
1146	.llseek = default_llseek,
1147};
1148
1149static int
1150mt7915_twt_stats(struct seq_file *s, void *data)
1151{
1152	struct mt7915_dev *dev = dev_get_drvdata(s->private);
1153	struct mt7915_twt_flow *iter;
1154
1155	rcu_read_lock();
1156
1157	seq_puts(s, "     wcid |       id |    flags |      exp | mantissa");
1158	seq_puts(s, " | duration |            tsf |\n");
1159	list_for_each_entry_rcu(iter, &dev->twt_list, list)
1160		seq_printf(s,
1161			"%9d | %8d | %5c%c%c%c | %8d | %8d | %8d | %14lld |\n",
1162			iter->wcid, iter->id,
1163			iter->sched ? 's' : 'u',
1164			iter->protection ? 'p' : '-',
1165			iter->trigger ? 't' : '-',
1166			iter->flowtype ? '-' : 'a',
1167			iter->exp, iter->mantissa,
1168			iter->duration, iter->tsf);
1169
1170	rcu_read_unlock();
1171
1172	return 0;
1173}
1174
1175/* The index of RF registers use the generic regidx, combined with two parts:
1176 * WF selection [31:24] and offset [23:0].
1177 */
1178static int
1179mt7915_rf_regval_get(void *data, u64 *val)
1180{
1181	struct mt7915_dev *dev = data;
1182	u32 regval;
1183	int ret;
1184
1185	ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &regval, false);
1186	if (ret)
1187		return ret;
1188
1189	*val = regval;
1190
1191	return 0;
1192}
1193
1194static int
1195mt7915_rf_regval_set(void *data, u64 val)
1196{
1197	struct mt7915_dev *dev = data;
1198	u32 val32 = val;
1199
1200	return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true);
1201}
1202
1203DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get,
1204			 mt7915_rf_regval_set, "0x%08llx\n");
1205
1206int mt7915_init_debugfs(struct mt7915_phy *phy)
1207{
1208	struct mt7915_dev *dev = phy->dev;
1209	bool ext_phy = phy != &dev->phy;
1210	struct dentry *dir;
1211
1212	dir = mt76_register_debugfs_fops(phy->mt76, NULL);
1213	if (!dir)
1214		return -ENOMEM;
1215	debugfs_create_file("muru_debug", 0600, dir, dev, &fops_muru_debug);
1216	debugfs_create_file("muru_stats", 0400, dir, phy,
1217			    &mt7915_muru_stats_fops);
1218	debugfs_create_file("hw-queues", 0400, dir, phy,
1219			    &mt7915_hw_queues_fops);
1220	debugfs_create_file("xmit-queues", 0400, dir, phy,
1221			    &mt7915_xmit_queues_fops);
1222	debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
1223	debugfs_create_file("sys_recovery", 0600, dir, phy,
1224			    &mt7915_sys_recovery_ops);
1225	debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
1226	debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
1227	debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
1228	debugfs_create_file("fw_util_wm", 0400, dir, dev,
1229			    &mt7915_fw_util_wm_fops);
1230	debugfs_create_file("fw_util_wa", 0400, dir, dev,
1231			    &mt7915_fw_util_wa_fops);
1232	debugfs_create_file("implicit_txbf", 0600, dir, dev,
1233			    &fops_implicit_txbf);
1234	debugfs_create_file("txpower_sku", 0400, dir, phy,
1235			    &mt7915_rate_txpower_fops);
1236	debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
1237				    mt7915_twt_stats);
1238	debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
1239
1240	if (!dev->dbdc_support || phy->mt76->band_idx) {
1241		debugfs_create_u32("dfs_hw_pattern", 0400, dir,
1242				   &dev->hw_pattern);
1243		debugfs_create_file("radar_trigger", 0200, dir, dev,
1244				    &fops_radar_trigger);
1245		debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
1246					    mt7915_rdd_monitor);
1247	}
1248
1249	if (!ext_phy)
1250		dev->debugfs_dir = dir;
1251
1252	return 0;
1253}
1254
1255static void
1256mt7915_debugfs_write_fwlog(struct mt7915_dev *dev, const void *hdr, int hdrlen,
1257			 const void *data, int len)
1258{
1259	static DEFINE_SPINLOCK(lock);
1260	unsigned long flags;
1261	void *dest;
1262
1263	spin_lock_irqsave(&lock, flags);
1264	dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
1265	if (dest) {
1266		*(u32 *)dest = hdrlen + len;
1267		dest += 4;
1268
1269		if (hdrlen) {
1270			memcpy(dest, hdr, hdrlen);
1271			dest += hdrlen;
1272		}
1273
1274		memcpy(dest, data, len);
1275		relay_flush(dev->relay_fwlog);
1276	}
1277	spin_unlock_irqrestore(&lock, flags);
1278}
1279
1280void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len)
1281{
1282	struct {
1283		__le32 magic;
1284		__le32 timestamp;
1285		__le16 msg_type;
1286		__le16 len;
1287	} hdr = {
1288		.magic = cpu_to_le32(FW_BIN_LOG_MAGIC),
1289		.msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR),
1290	};
1291
1292	if (!dev->relay_fwlog)
1293		return;
1294
1295	hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0)));
1296	hdr.len = *(__le16 *)data;
1297	mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len);
1298}
1299
1300bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len)
1301{
1302	if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC)
1303		return false;
1304
1305	if (dev->relay_fwlog)
1306		mt7915_debugfs_write_fwlog(dev, NULL, 0, data, len);
1307
1308	return true;
1309}
1310
1311#ifdef CONFIG_MAC80211_DEBUGFS
1312/** per-station debugfs **/
1313
1314static ssize_t mt7915_sta_fixed_rate_set(struct file *file,
1315					 const char __user *user_buf,
1316					 size_t count, loff_t *ppos)
1317{
1318	struct ieee80211_sta *sta = file->private_data;
1319	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
1320	struct mt7915_dev *dev = msta->vif->phy->dev;
1321	struct ieee80211_vif *vif;
1322	struct sta_phy phy = {};
1323	char buf[100];
1324	int ret;
1325	u32 field;
1326	u8 i, gi, he_ltf;
1327
1328	if (count >= sizeof(buf))
1329		return -EINVAL;
1330
1331	if (copy_from_user(buf, user_buf, count))
1332		return -EFAULT;
1333
1334	if (count && buf[count - 1] == '\n')
1335		buf[count - 1] = '\0';
1336	else
1337		buf[count] = '\0';
1338
1339	/* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9
1340	 * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3
1341	 * nss - vht: 1~4, he: 1~4, others: ignore
1342	 * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2
1343	 * gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2
1344	 * ldpc - off: 0, on: 1
1345	 * stbc - off: 0, on: 1
1346	 * he_ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
1347	 */
1348	if (sscanf(buf, "%hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu",
1349		   &phy.type, &phy.bw, &phy.nss, &phy.mcs, &gi,
1350		   &phy.ldpc, &phy.stbc, &he_ltf) != 8) {
1351		dev_warn(dev->mt76.dev,
1352			 "format: Mode BW NSS MCS (HE)GI LDPC STBC HE_LTF\n");
1353		field = RATE_PARAM_AUTO;
1354		goto out;
1355	}
1356
1357	phy.ldpc = (phy.bw || phy.ldpc) * GENMASK(2, 0);
1358	for (i = 0; i <= phy.bw; i++) {
1359		phy.sgi |= gi << (i << sta->deflink.he_cap.has_he);
1360		phy.he_ltf |= he_ltf << (i << sta->deflink.he_cap.has_he);
1361	}
1362	field = RATE_PARAM_FIXED;
1363
1364out:
1365	vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
1366	ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, field);
1367	if (ret)
1368		return -EFAULT;
1369
1370	return count;
1371}
1372
1373static const struct file_operations fops_fixed_rate = {
1374	.write = mt7915_sta_fixed_rate_set,
1375	.open = simple_open,
1376	.owner = THIS_MODULE,
1377	.llseek = default_llseek,
1378};
1379
1380static int
1381mt7915_queues_show(struct seq_file *s, void *data)
1382{
1383	struct ieee80211_sta *sta = s->private;
1384
1385	mt7915_sta_hw_queue_read(s, sta);
1386
1387	return 0;
1388}
1389
1390DEFINE_SHOW_ATTRIBUTE(mt7915_queues);
1391
1392void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1393			    struct ieee80211_sta *sta, struct dentry *dir)
1394{
1395	debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate);
1396	debugfs_create_file("hw-queues", 0400, dir, sta, &mt7915_queues_fops);
1397}
1398
1399#endif
1400