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