Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath11k/debugfs.c
48375 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
4
*/
5
6
#include <linux/vmalloc.h>
7
8
#include "debugfs.h"
9
10
#include "core.h"
11
#include "debug.h"
12
#include "wmi.h"
13
#include "hal_rx.h"
14
#include "dp_tx.h"
15
#include "debugfs_htt_stats.h"
16
#include "peer.h"
17
#include "hif.h"
18
19
static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
20
"REO2SW1_RING",
21
"REO2SW2_RING",
22
"REO2SW3_RING",
23
"REO2SW4_RING",
24
"WBM2REO_LINK_RING",
25
"REO2TCL_RING",
26
"REO2FW_RING",
27
"RELEASE_RING",
28
"PPE_RELEASE_RING",
29
"TCL2TQM_RING",
30
"TQM_RELEASE_RING",
31
"REO_RELEASE_RING",
32
"WBM2SW0_RELEASE_RING",
33
"WBM2SW1_RELEASE_RING",
34
"WBM2SW2_RELEASE_RING",
35
"WBM2SW3_RELEASE_RING",
36
"REO_CMD_RING",
37
"REO_STATUS_RING",
38
};
39
40
static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
41
"FW2RXDMA_BUF_RING",
42
"FW2RXDMA_STATUS_RING",
43
"FW2RXDMA_LINK_RING",
44
"SW2RXDMA_BUF_RING",
45
"WBM2RXDMA_LINK_RING",
46
"RXDMA2FW_RING",
47
"RXDMA2SW_RING",
48
"RXDMA2RELEASE_RING",
49
"RXDMA2REO_RING",
50
"MONITOR_STATUS_RING",
51
"MONITOR_BUF_RING",
52
"MONITOR_DESC_RING",
53
"MONITOR_DEST_RING",
54
};
55
56
void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
57
enum wmi_direct_buffer_module id,
58
enum ath11k_dbg_dbr_event event,
59
struct hal_srng *srng)
60
{
61
struct ath11k_debug_dbr *dbr_debug;
62
struct ath11k_dbg_dbr_data *dbr_data;
63
struct ath11k_dbg_dbr_entry *entry;
64
65
if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
66
return;
67
68
dbr_debug = ar->debug.dbr_debug[id];
69
if (!dbr_debug)
70
return;
71
72
if (!dbr_debug->dbr_debug_enabled)
73
return;
74
75
dbr_data = &dbr_debug->dbr_dbg_data;
76
77
spin_lock_bh(&dbr_data->lock);
78
79
if (dbr_data->entries) {
80
entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
81
entry->hp = srng->u.src_ring.hp;
82
entry->tp = *srng->u.src_ring.tp_addr;
83
entry->timestamp = jiffies;
84
entry->event = event;
85
86
dbr_data->dbr_debug_idx++;
87
if (dbr_data->dbr_debug_idx ==
88
dbr_data->num_ring_debug_entries)
89
dbr_data->dbr_debug_idx = 0;
90
}
91
92
spin_unlock_bh(&dbr_data->lock);
93
}
94
95
static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
96
{
97
spin_lock_bh(&ar->data_lock);
98
ar->fw_stats_done = false;
99
ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
100
ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
101
spin_unlock_bh(&ar->data_lock);
102
}
103
104
void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
105
{
106
struct ath11k_base *ab = ar->ab;
107
struct ath11k_pdev *pdev;
108
bool is_end;
109
static unsigned int num_vdev, num_bcn;
110
size_t total_vdevs_started = 0;
111
int i;
112
113
/* WMI_REQUEST_PDEV_STAT request has been already processed */
114
115
if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
116
ar->fw_stats_done = true;
117
return;
118
}
119
120
if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
121
if (list_empty(&stats->vdevs)) {
122
ath11k_warn(ab, "empty vdev stats");
123
return;
124
}
125
/* FW sends all the active VDEV stats irrespective of PDEV,
126
* hence limit until the count of all VDEVs started
127
*/
128
for (i = 0; i < ab->num_radios; i++) {
129
pdev = rcu_dereference(ab->pdevs_active[i]);
130
if (pdev && pdev->ar)
131
total_vdevs_started += ar->num_started_vdevs;
132
}
133
134
is_end = ((++num_vdev) == total_vdevs_started);
135
136
list_splice_tail_init(&stats->vdevs,
137
&ar->fw_stats.vdevs);
138
139
if (is_end) {
140
ar->fw_stats_done = true;
141
num_vdev = 0;
142
}
143
return;
144
}
145
146
if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
147
if (list_empty(&stats->bcn)) {
148
ath11k_warn(ab, "empty bcn stats");
149
return;
150
}
151
/* Mark end until we reached the count of all started VDEVs
152
* within the PDEV
153
*/
154
is_end = ((++num_bcn) == ar->num_started_vdevs);
155
156
list_splice_tail_init(&stats->bcn,
157
&ar->fw_stats.bcn);
158
159
if (is_end) {
160
ar->fw_stats_done = true;
161
num_bcn = 0;
162
}
163
}
164
}
165
166
static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
167
struct stats_request_params *req_param)
168
{
169
struct ath11k_base *ab = ar->ab;
170
unsigned long timeout, time_left;
171
int ret;
172
173
lockdep_assert_held(&ar->conf_mutex);
174
175
/* FW stats can get split when exceeding the stats data buffer limit.
176
* In that case, since there is no end marking for the back-to-back
177
* received 'update stats' event, we keep a 3 seconds timeout in case,
178
* fw_stats_done is not marked yet
179
*/
180
timeout = jiffies + msecs_to_jiffies(3 * 1000);
181
182
ath11k_debugfs_fw_stats_reset(ar);
183
184
reinit_completion(&ar->fw_stats_complete);
185
186
ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
187
188
if (ret) {
189
ath11k_warn(ab, "could not request fw stats (%d)\n",
190
ret);
191
return ret;
192
}
193
194
time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
195
196
if (!time_left)
197
return -ETIMEDOUT;
198
199
for (;;) {
200
if (time_after(jiffies, timeout))
201
break;
202
203
spin_lock_bh(&ar->data_lock);
204
if (ar->fw_stats_done) {
205
spin_unlock_bh(&ar->data_lock);
206
break;
207
}
208
spin_unlock_bh(&ar->data_lock);
209
}
210
return 0;
211
}
212
213
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
214
u32 vdev_id, u32 stats_id)
215
{
216
struct ath11k_base *ab = ar->ab;
217
struct stats_request_params req_param;
218
int ret;
219
220
mutex_lock(&ar->conf_mutex);
221
222
if (ar->state != ATH11K_STATE_ON) {
223
ret = -ENETDOWN;
224
goto err_unlock;
225
}
226
227
req_param.pdev_id = pdev_id;
228
req_param.vdev_id = vdev_id;
229
req_param.stats_id = stats_id;
230
231
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
232
if (ret)
233
ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
234
235
ath11k_dbg(ab, ATH11K_DBG_WMI,
236
"debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
237
pdev_id, vdev_id, stats_id);
238
239
err_unlock:
240
mutex_unlock(&ar->conf_mutex);
241
242
return ret;
243
}
244
245
static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
246
{
247
struct ath11k *ar = inode->i_private;
248
struct ath11k_base *ab = ar->ab;
249
struct stats_request_params req_param;
250
void *buf = NULL;
251
int ret;
252
253
mutex_lock(&ar->conf_mutex);
254
255
if (ar->state != ATH11K_STATE_ON) {
256
ret = -ENETDOWN;
257
goto err_unlock;
258
}
259
260
buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
261
if (!buf) {
262
ret = -ENOMEM;
263
goto err_unlock;
264
}
265
266
req_param.pdev_id = ar->pdev->pdev_id;
267
req_param.vdev_id = 0;
268
req_param.stats_id = WMI_REQUEST_PDEV_STAT;
269
270
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
271
if (ret) {
272
ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
273
goto err_free;
274
}
275
276
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
277
278
file->private_data = buf;
279
280
mutex_unlock(&ar->conf_mutex);
281
return 0;
282
283
err_free:
284
vfree(buf);
285
286
err_unlock:
287
mutex_unlock(&ar->conf_mutex);
288
return ret;
289
}
290
291
static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
292
{
293
vfree(file->private_data);
294
295
return 0;
296
}
297
298
static ssize_t ath11k_read_pdev_stats(struct file *file,
299
char __user *user_buf,
300
size_t count, loff_t *ppos)
301
{
302
const char *buf = file->private_data;
303
size_t len = strlen(buf);
304
305
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
306
}
307
308
static const struct file_operations fops_pdev_stats = {
309
.open = ath11k_open_pdev_stats,
310
.release = ath11k_release_pdev_stats,
311
.read = ath11k_read_pdev_stats,
312
.owner = THIS_MODULE,
313
.llseek = default_llseek,
314
};
315
316
static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
317
{
318
struct ath11k *ar = inode->i_private;
319
struct stats_request_params req_param;
320
void *buf = NULL;
321
int ret;
322
323
mutex_lock(&ar->conf_mutex);
324
325
if (ar->state != ATH11K_STATE_ON) {
326
ret = -ENETDOWN;
327
goto err_unlock;
328
}
329
330
buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
331
if (!buf) {
332
ret = -ENOMEM;
333
goto err_unlock;
334
}
335
336
req_param.pdev_id = ar->pdev->pdev_id;
337
/* VDEV stats is always sent for all active VDEVs from FW */
338
req_param.vdev_id = 0;
339
req_param.stats_id = WMI_REQUEST_VDEV_STAT;
340
341
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
342
if (ret) {
343
ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
344
goto err_free;
345
}
346
347
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
348
349
file->private_data = buf;
350
351
mutex_unlock(&ar->conf_mutex);
352
return 0;
353
354
err_free:
355
vfree(buf);
356
357
err_unlock:
358
mutex_unlock(&ar->conf_mutex);
359
return ret;
360
}
361
362
static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
363
{
364
vfree(file->private_data);
365
366
return 0;
367
}
368
369
static ssize_t ath11k_read_vdev_stats(struct file *file,
370
char __user *user_buf,
371
size_t count, loff_t *ppos)
372
{
373
const char *buf = file->private_data;
374
size_t len = strlen(buf);
375
376
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
377
}
378
379
static const struct file_operations fops_vdev_stats = {
380
.open = ath11k_open_vdev_stats,
381
.release = ath11k_release_vdev_stats,
382
.read = ath11k_read_vdev_stats,
383
.owner = THIS_MODULE,
384
.llseek = default_llseek,
385
};
386
387
static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
388
{
389
struct ath11k *ar = inode->i_private;
390
struct ath11k_vif *arvif;
391
struct stats_request_params req_param;
392
void *buf = NULL;
393
int ret;
394
395
mutex_lock(&ar->conf_mutex);
396
397
if (ar->state != ATH11K_STATE_ON) {
398
ret = -ENETDOWN;
399
goto err_unlock;
400
}
401
402
buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
403
if (!buf) {
404
ret = -ENOMEM;
405
goto err_unlock;
406
}
407
408
req_param.stats_id = WMI_REQUEST_BCN_STAT;
409
req_param.pdev_id = ar->pdev->pdev_id;
410
411
/* loop all active VDEVs for bcn stats */
412
list_for_each_entry(arvif, &ar->arvifs, list) {
413
if (!arvif->is_up)
414
continue;
415
416
req_param.vdev_id = arvif->vdev_id;
417
ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
418
if (ret) {
419
ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
420
goto err_free;
421
}
422
}
423
424
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
425
426
/* since beacon stats request is looped for all active VDEVs, saved fw
427
* stats is not freed for each request until done for all active VDEVs
428
*/
429
spin_lock_bh(&ar->data_lock);
430
ath11k_fw_stats_bcn_free(&ar->fw_stats.bcn);
431
spin_unlock_bh(&ar->data_lock);
432
433
file->private_data = buf;
434
435
mutex_unlock(&ar->conf_mutex);
436
return 0;
437
438
err_free:
439
vfree(buf);
440
441
err_unlock:
442
mutex_unlock(&ar->conf_mutex);
443
return ret;
444
}
445
446
static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
447
{
448
vfree(file->private_data);
449
450
return 0;
451
}
452
453
static ssize_t ath11k_read_bcn_stats(struct file *file,
454
char __user *user_buf,
455
size_t count, loff_t *ppos)
456
{
457
const char *buf = file->private_data;
458
size_t len = strlen(buf);
459
460
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
461
}
462
463
static const struct file_operations fops_bcn_stats = {
464
.open = ath11k_open_bcn_stats,
465
.release = ath11k_release_bcn_stats,
466
.read = ath11k_read_bcn_stats,
467
.owner = THIS_MODULE,
468
.llseek = default_llseek,
469
};
470
471
static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
472
char __user *user_buf,
473
size_t count, loff_t *ppos)
474
{
475
const char buf[] =
476
"To simulate firmware crash write one of the keywords to this file:\n"
477
"`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
478
"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
479
480
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
481
}
482
483
/* Simulate firmware crash:
484
* 'soft': Call wmi command causing firmware hang. This firmware hang is
485
* recoverable by warm firmware reset.
486
* 'hard': Force firmware crash by setting any vdev parameter for not allowed
487
* vdev id. This is hard firmware crash because it is recoverable only by cold
488
* firmware reset.
489
*/
490
static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
491
const char __user *user_buf,
492
size_t count, loff_t *ppos)
493
{
494
struct ath11k_base *ab = file->private_data;
495
struct ath11k_pdev *pdev;
496
struct ath11k *ar = ab->pdevs[0].ar;
497
char buf[32] = {0};
498
ssize_t rc;
499
int i, ret, radioup = 0;
500
501
for (i = 0; i < ab->num_radios; i++) {
502
pdev = &ab->pdevs[i];
503
ar = pdev->ar;
504
if (ar && ar->state == ATH11K_STATE_ON) {
505
radioup = 1;
506
break;
507
}
508
}
509
/* filter partial writes and invalid commands */
510
if (*ppos != 0 || count >= sizeof(buf) || count == 0)
511
return -EINVAL;
512
513
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
514
if (rc < 0)
515
return rc;
516
517
/* drop the possible '\n' from the end */
518
if (buf[*ppos - 1] == '\n')
519
buf[*ppos - 1] = '\0';
520
521
if (radioup == 0) {
522
ret = -ENETDOWN;
523
goto exit;
524
}
525
526
if (!strcmp(buf, "assert")) {
527
ath11k_info(ab, "simulating firmware assert crash\n");
528
ret = ath11k_wmi_force_fw_hang_cmd(ar,
529
ATH11K_WMI_FW_HANG_ASSERT_TYPE,
530
ATH11K_WMI_FW_HANG_DELAY);
531
} else if (!strcmp(buf, "hw-restart")) {
532
ath11k_info(ab, "user requested hw restart\n");
533
queue_work(ab->workqueue_aux, &ab->reset_work);
534
ret = 0;
535
} else {
536
ret = -EINVAL;
537
goto exit;
538
}
539
540
if (ret) {
541
ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
542
goto exit;
543
}
544
545
ret = count;
546
547
exit:
548
return ret;
549
}
550
551
static const struct file_operations fops_simulate_fw_crash = {
552
.read = ath11k_read_simulate_fw_crash,
553
.write = ath11k_write_simulate_fw_crash,
554
.open = simple_open,
555
.owner = THIS_MODULE,
556
.llseek = default_llseek,
557
};
558
559
static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
560
const char __user *ubuf,
561
size_t count, loff_t *ppos)
562
{
563
struct ath11k *ar = file->private_data;
564
u32 filter;
565
int ret;
566
567
if (kstrtouint_from_user(ubuf, count, 0, &filter))
568
return -EINVAL;
569
570
mutex_lock(&ar->conf_mutex);
571
572
if (ar->state != ATH11K_STATE_ON) {
573
ret = -ENETDOWN;
574
goto out;
575
}
576
577
if (filter == ar->debug.extd_tx_stats) {
578
ret = count;
579
goto out;
580
}
581
582
ar->debug.extd_tx_stats = filter;
583
ret = count;
584
585
out:
586
mutex_unlock(&ar->conf_mutex);
587
return ret;
588
}
589
590
static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
591
char __user *ubuf,
592
size_t count, loff_t *ppos)
593
594
{
595
char buf[32] = {0};
596
struct ath11k *ar = file->private_data;
597
int len = 0;
598
599
mutex_lock(&ar->conf_mutex);
600
len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
601
ar->debug.extd_tx_stats);
602
mutex_unlock(&ar->conf_mutex);
603
604
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
605
}
606
607
static const struct file_operations fops_extd_tx_stats = {
608
.read = ath11k_read_enable_extd_tx_stats,
609
.write = ath11k_write_enable_extd_tx_stats,
610
.open = simple_open
611
};
612
613
static ssize_t ath11k_write_extd_rx_stats(struct file *file,
614
const char __user *ubuf,
615
size_t count, loff_t *ppos)
616
{
617
struct ath11k *ar = file->private_data;
618
struct ath11k_base *ab = ar->ab;
619
struct htt_rx_ring_tlv_filter tlv_filter = {0};
620
u32 enable, rx_filter = 0, ring_id;
621
int i;
622
int ret;
623
624
if (kstrtouint_from_user(ubuf, count, 0, &enable))
625
return -EINVAL;
626
627
mutex_lock(&ar->conf_mutex);
628
629
if (ar->state != ATH11K_STATE_ON) {
630
ret = -ENETDOWN;
631
goto exit;
632
}
633
634
if (enable > 1) {
635
ret = -EINVAL;
636
goto exit;
637
}
638
639
if (enable == ar->debug.extd_rx_stats) {
640
ret = count;
641
goto exit;
642
}
643
644
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
645
ar->debug.extd_rx_stats = enable;
646
ret = count;
647
goto exit;
648
}
649
650
if (enable) {
651
rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
652
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
653
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
654
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
655
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
656
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
657
658
tlv_filter.rx_filter = rx_filter;
659
tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
660
tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
661
tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
662
tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
663
HTT_RX_FP_DATA_FILTER_FLASG3;
664
} else {
665
tlv_filter = ath11k_mac_mon_status_filter_default;
666
}
667
668
ar->debug.rx_filter = tlv_filter.rx_filter;
669
670
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
671
ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
672
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
673
HAL_RXDMA_MONITOR_STATUS,
674
DP_RX_BUFFER_SIZE, &tlv_filter);
675
676
if (ret) {
677
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
678
goto exit;
679
}
680
}
681
682
ar->debug.extd_rx_stats = enable;
683
ret = count;
684
exit:
685
mutex_unlock(&ar->conf_mutex);
686
return ret;
687
}
688
689
static ssize_t ath11k_read_extd_rx_stats(struct file *file,
690
char __user *ubuf,
691
size_t count, loff_t *ppos)
692
{
693
struct ath11k *ar = file->private_data;
694
char buf[32];
695
int len = 0;
696
697
mutex_lock(&ar->conf_mutex);
698
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
699
ar->debug.extd_rx_stats);
700
mutex_unlock(&ar->conf_mutex);
701
702
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
703
}
704
705
static const struct file_operations fops_extd_rx_stats = {
706
.read = ath11k_read_extd_rx_stats,
707
.write = ath11k_write_extd_rx_stats,
708
.open = simple_open,
709
};
710
711
static int ath11k_fill_bp_stats(struct ath11k_base *ab,
712
struct ath11k_bp_stats *bp_stats,
713
char *buf, int len, int size)
714
{
715
lockdep_assert_held(&ab->base_lock);
716
717
len += scnprintf(buf + len, size - len, "count: %u\n",
718
bp_stats->count);
719
len += scnprintf(buf + len, size - len, "hp: %u\n",
720
bp_stats->hp);
721
len += scnprintf(buf + len, size - len, "tp: %u\n",
722
bp_stats->tp);
723
len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
724
jiffies_to_msecs(jiffies - bp_stats->jiffies));
725
return len;
726
}
727
728
static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
729
char *buf, int size)
730
{
731
struct ath11k_bp_stats *bp_stats;
732
bool stats_rxd = false;
733
u8 i, pdev_idx;
734
int len = 0;
735
736
len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
737
len += scnprintf(buf + len, size - len, "==================\n");
738
739
spin_lock_bh(&ab->base_lock);
740
for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
741
bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
742
743
if (!bp_stats->count)
744
continue;
745
746
len += scnprintf(buf + len, size - len, "Ring: %s\n",
747
htt_bp_umac_ring[i]);
748
len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
749
stats_rxd = true;
750
}
751
752
for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
753
for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
754
bp_stats =
755
&ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
756
757
if (!bp_stats->count)
758
continue;
759
760
len += scnprintf(buf + len, size - len, "Ring: %s\n",
761
htt_bp_lmac_ring[i]);
762
len += scnprintf(buf + len, size - len, "pdev: %d\n",
763
pdev_idx);
764
len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
765
stats_rxd = true;
766
}
767
}
768
spin_unlock_bh(&ab->base_lock);
769
770
if (!stats_rxd)
771
len += scnprintf(buf + len, size - len,
772
"No Ring Backpressure stats received\n\n");
773
774
return len;
775
}
776
777
static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
778
char __user *user_buf,
779
size_t count, loff_t *ppos)
780
{
781
struct ath11k_base *ab = file->private_data;
782
struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
783
int len = 0, i, retval;
784
const int size = 4096;
785
static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
786
"Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
787
"Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
788
"AMSDU parse", "SA timeout", "DA timeout",
789
"Flow timeout", "Flush req"};
790
static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
791
"Desc addr zero", "Desc inval", "AMPDU in non BA",
792
"Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
793
"Frame OOR", "BAR OOR", "No BA session",
794
"Frame SN equal SSN", "PN check fail", "2k err",
795
"PN err", "Desc blocked"};
796
797
char *buf;
798
799
buf = kzalloc(size, GFP_KERNEL);
800
if (!buf)
801
return -ENOMEM;
802
803
len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
804
len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
805
soc_stats->err_ring_pkts);
806
len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
807
soc_stats->invalid_rbm);
808
len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
809
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
810
len += scnprintf(buf + len, size - len, "%s: %u\n",
811
rxdma_err[i], soc_stats->rxdma_error[i]);
812
813
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
814
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
815
len += scnprintf(buf + len, size - len, "%s: %u\n",
816
reo_err[i], soc_stats->reo_error[i]);
817
818
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
819
len += scnprintf(buf + len, size - len,
820
"ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
821
soc_stats->hal_reo_error[0],
822
soc_stats->hal_reo_error[1],
823
soc_stats->hal_reo_error[2],
824
soc_stats->hal_reo_error[3]);
825
826
len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
827
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
828
829
for (i = 0; i < ab->hw_params.max_tx_ring; i++)
830
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
831
i, soc_stats->tx_err.desc_na[i]);
832
833
len += scnprintf(buf + len, size - len,
834
"\nMisc Transmit Failures: %d\n",
835
atomic_read(&soc_stats->tx_err.misc_fail));
836
837
len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
838
839
if (len > size)
840
len = size;
841
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
842
kfree(buf);
843
844
return retval;
845
}
846
847
static const struct file_operations fops_soc_dp_stats = {
848
.read = ath11k_debugfs_dump_soc_dp_stats,
849
.open = simple_open,
850
.owner = THIS_MODULE,
851
.llseek = default_llseek,
852
};
853
854
static ssize_t ath11k_write_fw_dbglog(struct file *file,
855
const char __user *user_buf,
856
size_t count, loff_t *ppos)
857
{
858
struct ath11k *ar = file->private_data;
859
char buf[128] = {0};
860
struct ath11k_fw_dbglog dbglog;
861
unsigned int param, mod_id_index, is_end;
862
u64 value;
863
int ret, num;
864
865
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
866
user_buf, count);
867
if (ret <= 0)
868
return ret;
869
870
num = sscanf(buf, "%u %llx %u %u", &param, &value, &mod_id_index, &is_end);
871
872
if (num < 2)
873
return -EINVAL;
874
875
mutex_lock(&ar->conf_mutex);
876
if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
877
param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
878
if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
879
ret = -EINVAL;
880
goto out;
881
}
882
ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
883
if (!is_end) {
884
ret = count;
885
goto out;
886
}
887
} else {
888
if (num != 2) {
889
ret = -EINVAL;
890
goto out;
891
}
892
}
893
894
dbglog.param = param;
895
dbglog.value = lower_32_bits(value);
896
ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
897
if (ret) {
898
ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
899
ret);
900
goto out;
901
}
902
903
ret = count;
904
905
out:
906
mutex_unlock(&ar->conf_mutex);
907
return ret;
908
}
909
910
static const struct file_operations fops_fw_dbglog = {
911
.write = ath11k_write_fw_dbglog,
912
.open = simple_open,
913
.owner = THIS_MODULE,
914
.llseek = default_llseek,
915
};
916
917
static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
918
{
919
struct ath11k_base *ab = inode->i_private;
920
u8 *buf;
921
u32 start, end;
922
int ret;
923
924
start = ab->hw_params.sram_dump.start;
925
end = ab->hw_params.sram_dump.end;
926
927
buf = vmalloc(end - start + 1);
928
if (!buf)
929
return -ENOMEM;
930
931
ret = ath11k_hif_read(ab, buf, start, end);
932
if (ret) {
933
ath11k_warn(ab, "failed to dump sram: %d\n", ret);
934
vfree(buf);
935
return ret;
936
}
937
938
file->private_data = buf;
939
return 0;
940
}
941
942
static ssize_t ath11k_read_sram_dump(struct file *file,
943
char __user *user_buf,
944
size_t count, loff_t *ppos)
945
{
946
struct ath11k_base *ab = file->f_inode->i_private;
947
const char *buf = file->private_data;
948
int len;
949
u32 start, end;
950
951
start = ab->hw_params.sram_dump.start;
952
end = ab->hw_params.sram_dump.end;
953
len = end - start + 1;
954
955
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
956
}
957
958
static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
959
{
960
vfree(file->private_data);
961
file->private_data = NULL;
962
963
return 0;
964
}
965
966
static const struct file_operations fops_sram_dump = {
967
.open = ath11k_open_sram_dump,
968
.read = ath11k_read_sram_dump,
969
.release = ath11k_release_sram_dump,
970
.owner = THIS_MODULE,
971
.llseek = default_llseek,
972
};
973
974
int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
975
{
976
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
977
return 0;
978
979
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
980
&fops_simulate_fw_crash);
981
982
debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
983
&fops_soc_dp_stats);
984
985
if (ab->hw_params.sram_dump.start != 0)
986
debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
987
&fops_sram_dump);
988
989
return 0;
990
}
991
992
void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
993
{
994
debugfs_remove_recursive(ab->debugfs_soc);
995
ab->debugfs_soc = NULL;
996
}
997
998
int ath11k_debugfs_soc_create(struct ath11k_base *ab)
999
{
1000
struct dentry *root;
1001
bool dput_needed;
1002
char name[64];
1003
int ret;
1004
1005
root = debugfs_lookup("ath11k", NULL);
1006
if (!root) {
1007
root = debugfs_create_dir("ath11k", NULL);
1008
if (IS_ERR_OR_NULL(root))
1009
return PTR_ERR(root);
1010
1011
dput_needed = false;
1012
} else {
1013
/* a dentry from lookup() needs dput() after we don't use it */
1014
dput_needed = true;
1015
}
1016
1017
scnprintf(name, sizeof(name), "%s-%s", ath11k_bus_str(ab->hif.bus),
1018
dev_name(ab->dev));
1019
1020
ab->debugfs_soc = debugfs_create_dir(name, root);
1021
if (IS_ERR_OR_NULL(ab->debugfs_soc)) {
1022
ret = PTR_ERR(ab->debugfs_soc);
1023
goto out;
1024
}
1025
1026
ret = 0;
1027
1028
out:
1029
if (dput_needed)
1030
dput(root);
1031
1032
return ret;
1033
}
1034
1035
void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
1036
{
1037
debugfs_remove_recursive(ab->debugfs_soc);
1038
ab->debugfs_soc = NULL;
1039
1040
/* We are not removing ath11k directory on purpose, even if it
1041
* would be empty. This simplifies the directory handling and it's
1042
* a minor cosmetic issue to leave an empty ath11k directory to
1043
* debugfs.
1044
*/
1045
}
1046
EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
1047
1048
void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
1049
{
1050
struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1051
ar->debug.debugfs_pdev);
1052
1053
ar->fw_stats.debugfs_fwstats = fwstats_dir;
1054
1055
/* all stats debugfs files created are under "fw_stats" directory
1056
* created per PDEV
1057
*/
1058
debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1059
&fops_pdev_stats);
1060
debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1061
&fops_vdev_stats);
1062
debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1063
&fops_bcn_stats);
1064
}
1065
1066
static ssize_t ath11k_write_pktlog_filter(struct file *file,
1067
const char __user *ubuf,
1068
size_t count, loff_t *ppos)
1069
{
1070
struct ath11k *ar = file->private_data;
1071
struct ath11k_base *ab = ar->ab;
1072
struct htt_rx_ring_tlv_filter tlv_filter = {0};
1073
u32 rx_filter = 0, ring_id, filter, mode;
1074
u8 buf[128] = {0};
1075
int i, ret, rx_buf_sz = 0;
1076
ssize_t rc;
1077
1078
mutex_lock(&ar->conf_mutex);
1079
if (ar->state != ATH11K_STATE_ON) {
1080
ret = -ENETDOWN;
1081
goto out;
1082
}
1083
1084
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1085
if (rc < 0) {
1086
ret = rc;
1087
goto out;
1088
}
1089
buf[rc] = '\0';
1090
1091
ret = sscanf(buf, "0x%x %u", &filter, &mode);
1092
if (ret != 2) {
1093
ret = -EINVAL;
1094
goto out;
1095
}
1096
1097
if (filter) {
1098
ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
1099
if (ret) {
1100
ath11k_warn(ar->ab,
1101
"failed to enable pktlog filter %x: %d\n",
1102
ar->debug.pktlog_filter, ret);
1103
goto out;
1104
}
1105
} else {
1106
ret = ath11k_wmi_pdev_pktlog_disable(ar);
1107
if (ret) {
1108
ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
1109
goto out;
1110
}
1111
}
1112
1113
/* Clear rx filter set for monitor mode and rx status */
1114
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1115
ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1116
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
1117
HAL_RXDMA_MONITOR_STATUS,
1118
rx_buf_sz, &tlv_filter);
1119
if (ret) {
1120
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1121
goto out;
1122
}
1123
}
1124
#define HTT_RX_FILTER_TLV_LITE_MODE \
1125
(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
1126
HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
1127
HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
1128
HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
1129
HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
1130
HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
1131
1132
if (mode == ATH11K_PKTLOG_MODE_FULL) {
1133
rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
1134
HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
1135
HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
1136
HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
1137
HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
1138
HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
1139
rx_buf_sz = DP_RX_BUFFER_SIZE;
1140
} else if (mode == ATH11K_PKTLOG_MODE_LITE) {
1141
ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1142
HTT_PPDU_STATS_TAG_PKTLOG);
1143
if (ret) {
1144
ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1145
goto out;
1146
}
1147
1148
rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1149
rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
1150
} else {
1151
rx_buf_sz = DP_RX_BUFFER_SIZE;
1152
tlv_filter = ath11k_mac_mon_status_filter_default;
1153
rx_filter = tlv_filter.rx_filter;
1154
1155
ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1156
HTT_PPDU_STATS_TAG_DEFAULT);
1157
if (ret) {
1158
ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1159
ret);
1160
goto out;
1161
}
1162
}
1163
1164
tlv_filter.rx_filter = rx_filter;
1165
if (rx_filter) {
1166
tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1167
tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1168
tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1169
tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1170
HTT_RX_FP_DATA_FILTER_FLASG3;
1171
}
1172
1173
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1174
ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1175
ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1176
ar->dp.mac_id + i,
1177
HAL_RXDMA_MONITOR_STATUS,
1178
rx_buf_sz, &tlv_filter);
1179
1180
if (ret) {
1181
ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1182
goto out;
1183
}
1184
}
1185
1186
ath11k_info(ab, "pktlog mode %s\n",
1187
((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1188
1189
ar->debug.pktlog_filter = filter;
1190
ar->debug.pktlog_mode = mode;
1191
ret = count;
1192
1193
out:
1194
mutex_unlock(&ar->conf_mutex);
1195
return ret;
1196
}
1197
1198
static ssize_t ath11k_read_pktlog_filter(struct file *file,
1199
char __user *ubuf,
1200
size_t count, loff_t *ppos)
1201
1202
{
1203
char buf[32] = {0};
1204
struct ath11k *ar = file->private_data;
1205
int len = 0;
1206
1207
mutex_lock(&ar->conf_mutex);
1208
len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1209
ar->debug.pktlog_filter,
1210
ar->debug.pktlog_mode);
1211
mutex_unlock(&ar->conf_mutex);
1212
1213
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1214
}
1215
1216
static const struct file_operations fops_pktlog_filter = {
1217
.read = ath11k_read_pktlog_filter,
1218
.write = ath11k_write_pktlog_filter,
1219
.open = simple_open
1220
};
1221
1222
static ssize_t ath11k_write_simulate_radar(struct file *file,
1223
const char __user *user_buf,
1224
size_t count, loff_t *ppos)
1225
{
1226
struct ath11k *ar = file->private_data;
1227
int ret;
1228
1229
ret = ath11k_wmi_simulate_radar(ar);
1230
if (ret)
1231
return ret;
1232
1233
return count;
1234
}
1235
1236
static const struct file_operations fops_simulate_radar = {
1237
.write = ath11k_write_simulate_radar,
1238
.open = simple_open
1239
};
1240
1241
static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
1242
char __user *user_buf,
1243
size_t count, loff_t *ppos)
1244
{
1245
struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
1246
static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
1247
int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
1248
char *buf;
1249
int i, ret;
1250
int len = 0;
1251
1252
buf = kzalloc(size, GFP_KERNEL);
1253
if (!buf)
1254
return -ENOMEM;
1255
1256
len += scnprintf(buf + len, size - len,
1257
"-----------------------------------------\n");
1258
len += scnprintf(buf + len, size - len,
1259
"| idx | hp | tp | timestamp | event |\n");
1260
len += scnprintf(buf + len, size - len,
1261
"-----------------------------------------\n");
1262
1263
spin_lock_bh(&dbr_dbg_data->lock);
1264
1265
for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
1266
len += scnprintf(buf + len, size - len,
1267
"|%4u|%8u|%8u|%11llu|%8s|\n", i,
1268
dbr_dbg_data->entries[i].hp,
1269
dbr_dbg_data->entries[i].tp,
1270
dbr_dbg_data->entries[i].timestamp,
1271
event_id_to_string[dbr_dbg_data->entries[i].event]);
1272
}
1273
1274
spin_unlock_bh(&dbr_dbg_data->lock);
1275
1276
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1277
kfree(buf);
1278
1279
return ret;
1280
}
1281
1282
static const struct file_operations fops_debug_dump_dbr_entries = {
1283
.read = ath11k_debug_dump_dbr_entries,
1284
.open = simple_open,
1285
.owner = THIS_MODULE,
1286
.llseek = default_llseek,
1287
};
1288
1289
static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
1290
{
1291
struct ath11k_debug_dbr *dbr_debug;
1292
struct ath11k_dbg_dbr_data *dbr_dbg_data;
1293
1294
if (!ar->debug.dbr_debug[dbr_id])
1295
return;
1296
1297
dbr_debug = ar->debug.dbr_debug[dbr_id];
1298
dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1299
1300
debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1301
kfree(dbr_dbg_data->entries);
1302
kfree(dbr_debug);
1303
ar->debug.dbr_debug[dbr_id] = NULL;
1304
}
1305
1306
static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
1307
{
1308
struct ath11k_debug_dbr *dbr_debug;
1309
struct ath11k_dbg_dbr_data *dbr_dbg_data;
1310
static const char * const dbr_id_to_str[] = {"spectral", "CFR"};
1311
1312
if (ar->debug.dbr_debug[dbr_id])
1313
return 0;
1314
1315
ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
1316
GFP_KERNEL);
1317
1318
if (!ar->debug.dbr_debug[dbr_id])
1319
return -ENOMEM;
1320
1321
dbr_debug = ar->debug.dbr_debug[dbr_id];
1322
dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1323
1324
if (dbr_debug->dbr_debugfs)
1325
return 0;
1326
1327
dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
1328
ar->debug.debugfs_pdev);
1329
if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
1330
if (IS_ERR(dbr_debug->dbr_debugfs))
1331
return PTR_ERR(dbr_debug->dbr_debugfs);
1332
return -ENOMEM;
1333
}
1334
1335
dbr_debug->dbr_debug_enabled = true;
1336
dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
1337
dbr_dbg_data->dbr_debug_idx = 0;
1338
dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
1339
sizeof(struct ath11k_dbg_dbr_entry),
1340
GFP_KERNEL);
1341
if (!dbr_dbg_data->entries)
1342
return -ENOMEM;
1343
1344
spin_lock_init(&dbr_dbg_data->lock);
1345
1346
debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
1347
dbr_dbg_data, &fops_debug_dump_dbr_entries);
1348
1349
return 0;
1350
}
1351
1352
static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
1353
const char __user *ubuf,
1354
size_t count, loff_t *ppos)
1355
{
1356
struct ath11k *ar = file->private_data;
1357
char buf[32] = {0};
1358
u32 dbr_id, enable;
1359
int ret;
1360
1361
mutex_lock(&ar->conf_mutex);
1362
1363
if (ar->state != ATH11K_STATE_ON) {
1364
ret = -ENETDOWN;
1365
goto out;
1366
}
1367
1368
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1369
if (ret < 0)
1370
goto out;
1371
1372
buf[ret] = '\0';
1373
ret = sscanf(buf, "%u %u", &dbr_id, &enable);
1374
if (ret != 2 || dbr_id > 1 || enable > 1) {
1375
ret = -EINVAL;
1376
ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
1377
goto out;
1378
}
1379
1380
if (enable) {
1381
ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
1382
if (ret) {
1383
ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
1384
ret);
1385
goto out;
1386
}
1387
} else {
1388
ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
1389
}
1390
1391
ret = count;
1392
out:
1393
mutex_unlock(&ar->conf_mutex);
1394
return ret;
1395
}
1396
1397
static const struct file_operations fops_dbr_debug = {
1398
.write = ath11k_debugfs_write_enable_dbr_dbg,
1399
.open = simple_open,
1400
.owner = THIS_MODULE,
1401
.llseek = default_llseek,
1402
};
1403
1404
static ssize_t ath11k_write_ps_timekeeper_enable(struct file *file,
1405
const char __user *user_buf,
1406
size_t count, loff_t *ppos)
1407
{
1408
struct ath11k *ar = file->private_data;
1409
ssize_t ret;
1410
u8 ps_timekeeper_enable;
1411
1412
if (kstrtou8_from_user(user_buf, count, 0, &ps_timekeeper_enable))
1413
return -EINVAL;
1414
1415
mutex_lock(&ar->conf_mutex);
1416
1417
if (ar->state != ATH11K_STATE_ON) {
1418
ret = -ENETDOWN;
1419
goto exit;
1420
}
1421
1422
if (!ar->ps_state_enable) {
1423
ret = -EINVAL;
1424
goto exit;
1425
}
1426
1427
ar->ps_timekeeper_enable = !!ps_timekeeper_enable;
1428
ret = count;
1429
exit:
1430
mutex_unlock(&ar->conf_mutex);
1431
1432
return ret;
1433
}
1434
1435
static ssize_t ath11k_read_ps_timekeeper_enable(struct file *file,
1436
char __user *user_buf,
1437
size_t count, loff_t *ppos)
1438
{
1439
struct ath11k *ar = file->private_data;
1440
char buf[32];
1441
int len;
1442
1443
mutex_lock(&ar->conf_mutex);
1444
len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_timekeeper_enable);
1445
mutex_unlock(&ar->conf_mutex);
1446
1447
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1448
}
1449
1450
static const struct file_operations fops_ps_timekeeper_enable = {
1451
.read = ath11k_read_ps_timekeeper_enable,
1452
.write = ath11k_write_ps_timekeeper_enable,
1453
.open = simple_open,
1454
.owner = THIS_MODULE,
1455
.llseek = default_llseek,
1456
};
1457
1458
static void ath11k_reset_peer_ps_duration(void *data,
1459
struct ieee80211_sta *sta)
1460
{
1461
struct ath11k *ar = data;
1462
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
1463
1464
spin_lock_bh(&ar->data_lock);
1465
arsta->ps_total_duration = 0;
1466
spin_unlock_bh(&ar->data_lock);
1467
}
1468
1469
static ssize_t ath11k_write_reset_ps_duration(struct file *file,
1470
const char __user *user_buf,
1471
size_t count, loff_t *ppos)
1472
{
1473
struct ath11k *ar = file->private_data;
1474
int ret;
1475
u8 reset_ps_duration;
1476
1477
if (kstrtou8_from_user(user_buf, count, 0, &reset_ps_duration))
1478
return -EINVAL;
1479
1480
mutex_lock(&ar->conf_mutex);
1481
1482
if (ar->state != ATH11K_STATE_ON) {
1483
ret = -ENETDOWN;
1484
goto exit;
1485
}
1486
1487
if (!ar->ps_state_enable) {
1488
ret = -EINVAL;
1489
goto exit;
1490
}
1491
1492
ieee80211_iterate_stations_atomic(ar->hw,
1493
ath11k_reset_peer_ps_duration,
1494
ar);
1495
1496
ret = count;
1497
exit:
1498
mutex_unlock(&ar->conf_mutex);
1499
return ret;
1500
}
1501
1502
static const struct file_operations fops_reset_ps_duration = {
1503
.write = ath11k_write_reset_ps_duration,
1504
.open = simple_open,
1505
.owner = THIS_MODULE,
1506
.llseek = default_llseek,
1507
};
1508
1509
static void ath11k_peer_ps_state_disable(void *data,
1510
struct ieee80211_sta *sta)
1511
{
1512
struct ath11k *ar = data;
1513
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
1514
1515
spin_lock_bh(&ar->data_lock);
1516
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
1517
arsta->ps_start_time = 0;
1518
arsta->ps_total_duration = 0;
1519
spin_unlock_bh(&ar->data_lock);
1520
}
1521
1522
static ssize_t ath11k_write_ps_state_enable(struct file *file,
1523
const char __user *user_buf,
1524
size_t count, loff_t *ppos)
1525
{
1526
struct ath11k *ar = file->private_data;
1527
struct ath11k_pdev *pdev = ar->pdev;
1528
int ret;
1529
u32 param;
1530
u8 ps_state_enable;
1531
1532
if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
1533
return -EINVAL;
1534
1535
mutex_lock(&ar->conf_mutex);
1536
1537
ps_state_enable = !!ps_state_enable;
1538
1539
if (ar->ps_state_enable == ps_state_enable) {
1540
ret = count;
1541
goto exit;
1542
}
1543
1544
param = WMI_PDEV_PEER_STA_PS_STATECHG_ENABLE;
1545
ret = ath11k_wmi_pdev_set_param(ar, param, ps_state_enable, pdev->pdev_id);
1546
if (ret) {
1547
ath11k_warn(ar->ab, "failed to enable ps_state_enable: %d\n",
1548
ret);
1549
goto exit;
1550
}
1551
ar->ps_state_enable = ps_state_enable;
1552
1553
if (!ar->ps_state_enable) {
1554
ar->ps_timekeeper_enable = false;
1555
ieee80211_iterate_stations_atomic(ar->hw,
1556
ath11k_peer_ps_state_disable,
1557
ar);
1558
}
1559
1560
ret = count;
1561
1562
exit:
1563
mutex_unlock(&ar->conf_mutex);
1564
1565
return ret;
1566
}
1567
1568
static ssize_t ath11k_read_ps_state_enable(struct file *file,
1569
char __user *user_buf,
1570
size_t count, loff_t *ppos)
1571
{
1572
struct ath11k *ar = file->private_data;
1573
char buf[32];
1574
int len;
1575
1576
mutex_lock(&ar->conf_mutex);
1577
len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_state_enable);
1578
mutex_unlock(&ar->conf_mutex);
1579
1580
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1581
}
1582
1583
static const struct file_operations fops_ps_state_enable = {
1584
.read = ath11k_read_ps_state_enable,
1585
.write = ath11k_write_ps_state_enable,
1586
.open = simple_open,
1587
.owner = THIS_MODULE,
1588
.llseek = default_llseek,
1589
};
1590
1591
int ath11k_debugfs_register(struct ath11k *ar)
1592
{
1593
struct ath11k_base *ab = ar->ab;
1594
char pdev_name[5];
1595
char buf[100] = {0};
1596
1597
snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1598
1599
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1600
if (IS_ERR(ar->debug.debugfs_pdev))
1601
return PTR_ERR(ar->debug.debugfs_pdev);
1602
1603
/* Create a symlink under ieee80211/phy* */
1604
snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1605
debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1606
1607
ath11k_debugfs_htt_stats_init(ar);
1608
1609
ath11k_debugfs_fw_stats_init(ar);
1610
1611
debugfs_create_file("ext_tx_stats", 0644,
1612
ar->debug.debugfs_pdev, ar,
1613
&fops_extd_tx_stats);
1614
debugfs_create_file("ext_rx_stats", 0644,
1615
ar->debug.debugfs_pdev, ar,
1616
&fops_extd_rx_stats);
1617
debugfs_create_file("pktlog_filter", 0644,
1618
ar->debug.debugfs_pdev, ar,
1619
&fops_pktlog_filter);
1620
debugfs_create_file("fw_dbglog_config", 0600,
1621
ar->debug.debugfs_pdev, ar,
1622
&fops_fw_dbglog);
1623
1624
if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1625
debugfs_create_file("dfs_simulate_radar", 0200,
1626
ar->debug.debugfs_pdev, ar,
1627
&fops_simulate_radar);
1628
debugfs_create_bool("dfs_block_radar_events", 0200,
1629
ar->debug.debugfs_pdev,
1630
&ar->dfs_block_radar_events);
1631
}
1632
1633
if (ab->hw_params.dbr_debug_support)
1634
debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
1635
ar, &fops_dbr_debug);
1636
1637
debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_pdev, ar,
1638
&fops_ps_state_enable);
1639
1640
if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
1641
ar->ab->wmi_ab.svc_map)) {
1642
debugfs_create_file("ps_timekeeper_enable", 0600,
1643
ar->debug.debugfs_pdev, ar,
1644
&fops_ps_timekeeper_enable);
1645
1646
debugfs_create_file("reset_ps_duration", 0200,
1647
ar->debug.debugfs_pdev, ar,
1648
&fops_reset_ps_duration);
1649
}
1650
1651
return 0;
1652
}
1653
1654
void ath11k_debugfs_unregister(struct ath11k *ar)
1655
{
1656
struct ath11k_debug_dbr *dbr_debug;
1657
struct ath11k_dbg_dbr_data *dbr_dbg_data;
1658
int i;
1659
1660
for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
1661
dbr_debug = ar->debug.dbr_debug[i];
1662
if (!dbr_debug)
1663
continue;
1664
1665
dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1666
kfree(dbr_dbg_data->entries);
1667
debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1668
kfree(dbr_debug);
1669
ar->debug.dbr_debug[i] = NULL;
1670
}
1671
}
1672
1673
static ssize_t ath11k_write_twt_add_dialog(struct file *file,
1674
const char __user *ubuf,
1675
size_t count, loff_t *ppos)
1676
{
1677
struct ath11k_vif *arvif = file->private_data;
1678
struct wmi_twt_add_dialog_params params = { 0 };
1679
struct wmi_twt_enable_params twt_params = {0};
1680
struct ath11k *ar = arvif->ar;
1681
u8 buf[128] = {0};
1682
int ret;
1683
1684
if (ar->twt_enabled == 0) {
1685
ath11k_err(ar->ab, "twt support is not enabled\n");
1686
return -EOPNOTSUPP;
1687
}
1688
1689
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1690
if (ret < 0)
1691
return ret;
1692
1693
buf[ret] = '\0';
1694
ret = sscanf(buf,
1695
"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
1696
&params.peer_macaddr[0],
1697
&params.peer_macaddr[1],
1698
&params.peer_macaddr[2],
1699
&params.peer_macaddr[3],
1700
&params.peer_macaddr[4],
1701
&params.peer_macaddr[5],
1702
&params.dialog_id,
1703
&params.wake_intvl_us,
1704
&params.wake_intvl_mantis,
1705
&params.wake_dura_us,
1706
&params.sp_offset_us,
1707
&params.twt_cmd,
1708
&params.flag_bcast,
1709
&params.flag_trigger,
1710
&params.flag_flow_type,
1711
&params.flag_protection);
1712
if (ret != 16)
1713
return -EINVAL;
1714
1715
/* In the case of station vif, TWT is entirely handled by
1716
* the firmware based on the input parameters in the TWT enable
1717
* WMI command that is sent to the target during assoc.
1718
* For manually testing the TWT feature, we need to first disable
1719
* TWT and send enable command again with TWT input parameter
1720
* sta_cong_timer_ms set to 0.
1721
*/
1722
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1723
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1724
1725
ath11k_wmi_fill_default_twt_params(&twt_params);
1726
twt_params.sta_cong_timer_ms = 0;
1727
1728
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1729
}
1730
1731
params.vdev_id = arvif->vdev_id;
1732
1733
ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, &params);
1734
if (ret)
1735
goto err_twt_add_dialog;
1736
1737
return count;
1738
1739
err_twt_add_dialog:
1740
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1741
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1742
ath11k_wmi_fill_default_twt_params(&twt_params);
1743
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1744
}
1745
1746
return ret;
1747
}
1748
1749
static ssize_t ath11k_write_twt_del_dialog(struct file *file,
1750
const char __user *ubuf,
1751
size_t count, loff_t *ppos)
1752
{
1753
struct ath11k_vif *arvif = file->private_data;
1754
struct wmi_twt_del_dialog_params params = { 0 };
1755
struct wmi_twt_enable_params twt_params = {0};
1756
struct ath11k *ar = arvif->ar;
1757
u8 buf[64] = {0};
1758
int ret;
1759
1760
if (ar->twt_enabled == 0) {
1761
ath11k_err(ar->ab, "twt support is not enabled\n");
1762
return -EOPNOTSUPP;
1763
}
1764
1765
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1766
if (ret < 0)
1767
return ret;
1768
1769
buf[ret] = '\0';
1770
ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1771
&params.peer_macaddr[0],
1772
&params.peer_macaddr[1],
1773
&params.peer_macaddr[2],
1774
&params.peer_macaddr[3],
1775
&params.peer_macaddr[4],
1776
&params.peer_macaddr[5],
1777
&params.dialog_id);
1778
if (ret != 7)
1779
return -EINVAL;
1780
1781
params.vdev_id = arvif->vdev_id;
1782
1783
ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, &params);
1784
if (ret)
1785
return ret;
1786
1787
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1788
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1789
ath11k_wmi_fill_default_twt_params(&twt_params);
1790
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1791
}
1792
1793
return count;
1794
}
1795
1796
static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
1797
const char __user *ubuf,
1798
size_t count, loff_t *ppos)
1799
{
1800
struct ath11k_vif *arvif = file->private_data;
1801
struct wmi_twt_pause_dialog_params params = { 0 };
1802
u8 buf[64] = {0};
1803
int ret;
1804
1805
if (arvif->ar->twt_enabled == 0) {
1806
ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1807
return -EOPNOTSUPP;
1808
}
1809
1810
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1811
if (ret < 0)
1812
return ret;
1813
1814
buf[ret] = '\0';
1815
ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1816
&params.peer_macaddr[0],
1817
&params.peer_macaddr[1],
1818
&params.peer_macaddr[2],
1819
&params.peer_macaddr[3],
1820
&params.peer_macaddr[4],
1821
&params.peer_macaddr[5],
1822
&params.dialog_id);
1823
if (ret != 7)
1824
return -EINVAL;
1825
1826
params.vdev_id = arvif->vdev_id;
1827
1828
ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, &params);
1829
if (ret)
1830
return ret;
1831
1832
return count;
1833
}
1834
1835
static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
1836
const char __user *ubuf,
1837
size_t count, loff_t *ppos)
1838
{
1839
struct ath11k_vif *arvif = file->private_data;
1840
struct wmi_twt_resume_dialog_params params = { 0 };
1841
u8 buf[64] = {0};
1842
int ret;
1843
1844
if (arvif->ar->twt_enabled == 0) {
1845
ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1846
return -EOPNOTSUPP;
1847
}
1848
1849
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1850
if (ret < 0)
1851
return ret;
1852
1853
buf[ret] = '\0';
1854
ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
1855
&params.peer_macaddr[0],
1856
&params.peer_macaddr[1],
1857
&params.peer_macaddr[2],
1858
&params.peer_macaddr[3],
1859
&params.peer_macaddr[4],
1860
&params.peer_macaddr[5],
1861
&params.dialog_id,
1862
&params.sp_offset_us,
1863
&params.next_twt_size);
1864
if (ret != 9)
1865
return -EINVAL;
1866
1867
params.vdev_id = arvif->vdev_id;
1868
1869
ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, &params);
1870
if (ret)
1871
return ret;
1872
1873
return count;
1874
}
1875
1876
static const struct file_operations ath11k_fops_twt_add_dialog = {
1877
.write = ath11k_write_twt_add_dialog,
1878
.open = simple_open
1879
};
1880
1881
static const struct file_operations ath11k_fops_twt_del_dialog = {
1882
.write = ath11k_write_twt_del_dialog,
1883
.open = simple_open
1884
};
1885
1886
static const struct file_operations ath11k_fops_twt_pause_dialog = {
1887
.write = ath11k_write_twt_pause_dialog,
1888
.open = simple_open
1889
};
1890
1891
static const struct file_operations ath11k_fops_twt_resume_dialog = {
1892
.write = ath11k_write_twt_resume_dialog,
1893
.open = simple_open
1894
};
1895
1896
void ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
1897
{
1898
struct ath11k_base *ab = arvif->ar->ab;
1899
1900
if (arvif->vif->type != NL80211_IFTYPE_AP &&
1901
!(arvif->vif->type == NL80211_IFTYPE_STATION &&
1902
test_bit(WMI_TLV_SERVICE_STA_TWT, ab->wmi_ab.svc_map)))
1903
return;
1904
1905
arvif->debugfs_twt = debugfs_create_dir("twt",
1906
arvif->vif->debugfs_dir);
1907
debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
1908
arvif, &ath11k_fops_twt_add_dialog);
1909
1910
debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
1911
arvif, &ath11k_fops_twt_del_dialog);
1912
1913
debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
1914
arvif, &ath11k_fops_twt_pause_dialog);
1915
1916
debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
1917
arvif, &ath11k_fops_twt_resume_dialog);
1918
}
1919
1920
void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
1921
{
1922
if (!arvif->debugfs_twt)
1923
return;
1924
1925
debugfs_remove_recursive(arvif->debugfs_twt);
1926
arvif->debugfs_twt = NULL;
1927
}
1928
1929