1
2
3
4
5
6#include "debugfs.h"
7
8#include "core.h"
9#include "debug.h"
10#include "wmi.h"
11#include "hal_rx.h"
12#include "dp_tx.h"
13#include "debugfs_htt_stats.h"
14#include "peer.h"
15
16static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
17 "REO2SW1_RING",
18 "REO2SW2_RING",
19 "REO2SW3_RING",
20 "REO2SW4_RING",
21 "WBM2REO_LINK_RING",
22 "REO2TCL_RING",
23 "REO2FW_RING",
24 "RELEASE_RING",
25 "PPE_RELEASE_RING",
26 "TCL2TQM_RING",
27 "TQM_RELEASE_RING",
28 "REO_RELEASE_RING",
29 "WBM2SW0_RELEASE_RING",
30 "WBM2SW1_RELEASE_RING",
31 "WBM2SW2_RELEASE_RING",
32 "WBM2SW3_RELEASE_RING",
33 "REO_CMD_RING",
34 "REO_STATUS_RING",
35};
36
37static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
38 "FW2RXDMA_BUF_RING",
39 "FW2RXDMA_STATUS_RING",
40 "FW2RXDMA_LINK_RING",
41 "SW2RXDMA_BUF_RING",
42 "WBM2RXDMA_LINK_RING",
43 "RXDMA2FW_RING",
44 "RXDMA2SW_RING",
45 "RXDMA2RELEASE_RING",
46 "RXDMA2REO_RING",
47 "MONITOR_STATUS_RING",
48 "MONITOR_BUF_RING",
49 "MONITOR_DESC_RING",
50 "MONITOR_DEST_RING",
51};
52
53static void ath11k_fw_stats_pdevs_free(struct list_head *head)
54{
55 struct ath11k_fw_stats_pdev *i, *tmp;
56
57 list_for_each_entry_safe(i, tmp, head, list) {
58 list_del(&i->list);
59 kfree(i);
60 }
61}
62
63static void ath11k_fw_stats_vdevs_free(struct list_head *head)
64{
65 struct ath11k_fw_stats_vdev *i, *tmp;
66
67 list_for_each_entry_safe(i, tmp, head, list) {
68 list_del(&i->list);
69 kfree(i);
70 }
71}
72
73static void ath11k_fw_stats_bcn_free(struct list_head *head)
74{
75 struct ath11k_fw_stats_bcn *i, *tmp;
76
77 list_for_each_entry_safe(i, tmp, head, list) {
78 list_del(&i->list);
79 kfree(i);
80 }
81}
82
83static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
84{
85 spin_lock_bh(&ar->data_lock);
86 ar->debug.fw_stats_done = false;
87 ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
88 ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
89 spin_unlock_bh(&ar->data_lock);
90}
91
92void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
93{
94 struct ath11k_fw_stats stats = {};
95 struct ath11k *ar;
96 struct ath11k_pdev *pdev;
97 bool is_end;
98 static unsigned int num_vdev, num_bcn;
99 size_t total_vdevs_started = 0;
100 int i, ret;
101
102 INIT_LIST_HEAD(&stats.pdevs);
103 INIT_LIST_HEAD(&stats.vdevs);
104 INIT_LIST_HEAD(&stats.bcn);
105
106 ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
107 if (ret) {
108 ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
109 goto free;
110 }
111
112 rcu_read_lock();
113 ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
114 if (!ar) {
115 rcu_read_unlock();
116 ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
117 stats.pdev_id, ret);
118 goto free;
119 }
120
121 spin_lock_bh(&ar->data_lock);
122
123 if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
124 list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
125 ar->debug.fw_stats_done = true;
126 goto complete;
127 }
128
129 if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
130 if (list_empty(&stats.vdevs)) {
131 ath11k_warn(ab, "empty vdev stats");
132 goto complete;
133 }
134
135
136
137 for (i = 0; i < ab->num_radios; i++) {
138 pdev = rcu_dereference(ab->pdevs_active[i]);
139 if (pdev && pdev->ar)
140 total_vdevs_started += ar->num_started_vdevs;
141 }
142
143 is_end = ((++num_vdev) == total_vdevs_started);
144
145 list_splice_tail_init(&stats.vdevs,
146 &ar->debug.fw_stats.vdevs);
147
148 if (is_end) {
149 ar->debug.fw_stats_done = true;
150 num_vdev = 0;
151 }
152 goto complete;
153 }
154
155 if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
156 if (list_empty(&stats.bcn)) {
157 ath11k_warn(ab, "empty bcn stats");
158 goto complete;
159 }
160
161
162
163 is_end = ((++num_bcn) == ar->num_started_vdevs);
164
165 list_splice_tail_init(&stats.bcn,
166 &ar->debug.fw_stats.bcn);
167
168 if (is_end) {
169 ar->debug.fw_stats_done = true;
170 num_bcn = 0;
171 }
172 }
173complete:
174 complete(&ar->debug.fw_stats_complete);
175 rcu_read_unlock();
176 spin_unlock_bh(&ar->data_lock);
177
178free:
179 ath11k_fw_stats_pdevs_free(&stats.pdevs);
180 ath11k_fw_stats_vdevs_free(&stats.vdevs);
181 ath11k_fw_stats_bcn_free(&stats.bcn);
182}
183
184static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
185 struct stats_request_params *req_param)
186{
187 struct ath11k_base *ab = ar->ab;
188 unsigned long timeout, time_left;
189 int ret;
190
191 lockdep_assert_held(&ar->conf_mutex);
192
193
194
195
196
197
198 timeout = jiffies + msecs_to_jiffies(3 * HZ);
199
200 ath11k_debugfs_fw_stats_reset(ar);
201
202 reinit_completion(&ar->debug.fw_stats_complete);
203
204 ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
205
206 if (ret) {
207 ath11k_warn(ab, "could not request fw stats (%d)\n",
208 ret);
209 return ret;
210 }
211
212 time_left =
213 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
214 1 * HZ);
215 if (!time_left)
216 return -ETIMEDOUT;
217
218 for (;;) {
219 if (time_after(jiffies, timeout))
220 break;
221
222 spin_lock_bh(&ar->data_lock);
223 if (ar->debug.fw_stats_done) {
224 spin_unlock_bh(&ar->data_lock);
225 break;
226 }
227 spin_unlock_bh(&ar->data_lock);
228 }
229 return 0;
230}
231
232static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
233{
234 struct ath11k *ar = inode->i_private;
235 struct ath11k_base *ab = ar->ab;
236 struct stats_request_params req_param;
237 void *buf = NULL;
238 int ret;
239
240 mutex_lock(&ar->conf_mutex);
241
242 if (ar->state != ATH11K_STATE_ON) {
243 ret = -ENETDOWN;
244 goto err_unlock;
245 }
246
247 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
248 if (!buf) {
249 ret = -ENOMEM;
250 goto err_unlock;
251 }
252
253 req_param.pdev_id = ar->pdev->pdev_id;
254 req_param.vdev_id = 0;
255 req_param.stats_id = WMI_REQUEST_PDEV_STAT;
256
257 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
258 if (ret) {
259 ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
260 goto err_free;
261 }
262
263 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
264 buf);
265
266 file->private_data = buf;
267
268 mutex_unlock(&ar->conf_mutex);
269 return 0;
270
271err_free:
272 vfree(buf);
273
274err_unlock:
275 mutex_unlock(&ar->conf_mutex);
276 return ret;
277}
278
279static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
280{
281 vfree(file->private_data);
282
283 return 0;
284}
285
286static ssize_t ath11k_read_pdev_stats(struct file *file,
287 char __user *user_buf,
288 size_t count, loff_t *ppos)
289{
290 const char *buf = file->private_data;
291 size_t len = strlen(buf);
292
293 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
294}
295
296static const struct file_operations fops_pdev_stats = {
297 .open = ath11k_open_pdev_stats,
298 .release = ath11k_release_pdev_stats,
299 .read = ath11k_read_pdev_stats,
300 .owner = THIS_MODULE,
301 .llseek = default_llseek,
302};
303
304static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
305{
306 struct ath11k *ar = inode->i_private;
307 struct stats_request_params req_param;
308 void *buf = NULL;
309 int ret;
310
311 mutex_lock(&ar->conf_mutex);
312
313 if (ar->state != ATH11K_STATE_ON) {
314 ret = -ENETDOWN;
315 goto err_unlock;
316 }
317
318 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
319 if (!buf) {
320 ret = -ENOMEM;
321 goto err_unlock;
322 }
323
324 req_param.pdev_id = ar->pdev->pdev_id;
325
326 req_param.vdev_id = 0;
327 req_param.stats_id = WMI_REQUEST_VDEV_STAT;
328
329 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
330 if (ret) {
331 ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
332 goto err_free;
333 }
334
335 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
336 buf);
337
338 file->private_data = buf;
339
340 mutex_unlock(&ar->conf_mutex);
341 return 0;
342
343err_free:
344 vfree(buf);
345
346err_unlock:
347 mutex_unlock(&ar->conf_mutex);
348 return ret;
349}
350
351static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
352{
353 vfree(file->private_data);
354
355 return 0;
356}
357
358static ssize_t ath11k_read_vdev_stats(struct file *file,
359 char __user *user_buf,
360 size_t count, loff_t *ppos)
361{
362 const char *buf = file->private_data;
363 size_t len = strlen(buf);
364
365 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
366}
367
368static const struct file_operations fops_vdev_stats = {
369 .open = ath11k_open_vdev_stats,
370 .release = ath11k_release_vdev_stats,
371 .read = ath11k_read_vdev_stats,
372 .owner = THIS_MODULE,
373 .llseek = default_llseek,
374};
375
376static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
377{
378 struct ath11k *ar = inode->i_private;
379 struct ath11k_vif *arvif;
380 struct stats_request_params req_param;
381 void *buf = NULL;
382 int ret;
383
384 mutex_lock(&ar->conf_mutex);
385
386 if (ar->state != ATH11K_STATE_ON) {
387 ret = -ENETDOWN;
388 goto err_unlock;
389 }
390
391 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
392 if (!buf) {
393 ret = -ENOMEM;
394 goto err_unlock;
395 }
396
397 req_param.stats_id = WMI_REQUEST_BCN_STAT;
398 req_param.pdev_id = ar->pdev->pdev_id;
399
400
401 list_for_each_entry(arvif, &ar->arvifs, list) {
402 if (!arvif->is_up)
403 continue;
404
405 req_param.vdev_id = arvif->vdev_id;
406 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
407 if (ret) {
408 ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
409 goto err_free;
410 }
411 }
412
413 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
414 buf);
415
416
417
418
419 spin_lock_bh(&ar->data_lock);
420 ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
421 spin_unlock_bh(&ar->data_lock);
422
423 file->private_data = buf;
424
425 mutex_unlock(&ar->conf_mutex);
426 return 0;
427
428err_free:
429 vfree(buf);
430
431err_unlock:
432 mutex_unlock(&ar->conf_mutex);
433 return ret;
434}
435
436static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
437{
438 vfree(file->private_data);
439
440 return 0;
441}
442
443static ssize_t ath11k_read_bcn_stats(struct file *file,
444 char __user *user_buf,
445 size_t count, loff_t *ppos)
446{
447 const char *buf = file->private_data;
448 size_t len = strlen(buf);
449
450 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
451}
452
453static const struct file_operations fops_bcn_stats = {
454 .open = ath11k_open_bcn_stats,
455 .release = ath11k_release_bcn_stats,
456 .read = ath11k_read_bcn_stats,
457 .owner = THIS_MODULE,
458 .llseek = default_llseek,
459};
460
461static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
462 char __user *user_buf,
463 size_t count, loff_t *ppos)
464{
465 const char buf[] =
466 "To simulate firmware crash write one of the keywords to this file:\n"
467 "`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
468 "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
469
470 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
471}
472
473
474
475
476
477
478
479
480static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
481 const char __user *user_buf,
482 size_t count, loff_t *ppos)
483{
484 struct ath11k_base *ab = file->private_data;
485 struct ath11k_pdev *pdev;
486 struct ath11k *ar = ab->pdevs[0].ar;
487 char buf[32] = {0};
488 ssize_t rc;
489 int i, ret, radioup = 0;
490
491 for (i = 0; i < ab->num_radios; i++) {
492 pdev = &ab->pdevs[i];
493 ar = pdev->ar;
494 if (ar && ar->state == ATH11K_STATE_ON) {
495 radioup = 1;
496 break;
497 }
498 }
499
500 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
501 return -EINVAL;
502
503 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
504 if (rc < 0)
505 return rc;
506
507
508 if (buf[*ppos - 1] == '\n')
509 buf[*ppos - 1] = '\0';
510
511 if (radioup == 0) {
512 ret = -ENETDOWN;
513 goto exit;
514 }
515
516 if (!strcmp(buf, "assert")) {
517 ath11k_info(ab, "simulating firmware assert crash\n");
518 ret = ath11k_wmi_force_fw_hang_cmd(ar,
519 ATH11K_WMI_FW_HANG_ASSERT_TYPE,
520 ATH11K_WMI_FW_HANG_DELAY);
521 } else {
522 ret = -EINVAL;
523 goto exit;
524 }
525
526 if (ret) {
527 ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
528 goto exit;
529 }
530
531 ret = count;
532
533exit:
534 return ret;
535}
536
537static const struct file_operations fops_simulate_fw_crash = {
538 .read = ath11k_read_simulate_fw_crash,
539 .write = ath11k_write_simulate_fw_crash,
540 .open = simple_open,
541 .owner = THIS_MODULE,
542 .llseek = default_llseek,
543};
544
545static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
546 const char __user *ubuf,
547 size_t count, loff_t *ppos)
548{
549 struct ath11k *ar = file->private_data;
550 u32 filter;
551 int ret;
552
553 if (kstrtouint_from_user(ubuf, count, 0, &filter))
554 return -EINVAL;
555
556 mutex_lock(&ar->conf_mutex);
557
558 if (ar->state != ATH11K_STATE_ON) {
559 ret = -ENETDOWN;
560 goto out;
561 }
562
563 if (filter == ar->debug.extd_tx_stats) {
564 ret = count;
565 goto out;
566 }
567
568 ar->debug.extd_tx_stats = filter;
569 ret = count;
570
571out:
572 mutex_unlock(&ar->conf_mutex);
573 return ret;
574}
575
576static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
577 char __user *ubuf,
578 size_t count, loff_t *ppos)
579
580{
581 char buf[32] = {0};
582 struct ath11k *ar = file->private_data;
583 int len = 0;
584
585 mutex_lock(&ar->conf_mutex);
586 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
587 ar->debug.extd_tx_stats);
588 mutex_unlock(&ar->conf_mutex);
589
590 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
591}
592
593static const struct file_operations fops_extd_tx_stats = {
594 .read = ath11k_read_enable_extd_tx_stats,
595 .write = ath11k_write_enable_extd_tx_stats,
596 .open = simple_open
597};
598
599static ssize_t ath11k_write_extd_rx_stats(struct file *file,
600 const char __user *ubuf,
601 size_t count, loff_t *ppos)
602{
603 struct ath11k *ar = file->private_data;
604 struct ath11k_base *ab = ar->ab;
605 struct htt_rx_ring_tlv_filter tlv_filter = {0};
606 u32 enable, rx_filter = 0, ring_id;
607 int i;
608 int ret;
609
610 if (kstrtouint_from_user(ubuf, count, 0, &enable))
611 return -EINVAL;
612
613 mutex_lock(&ar->conf_mutex);
614
615 if (ar->state != ATH11K_STATE_ON) {
616 ret = -ENETDOWN;
617 goto exit;
618 }
619
620 if (enable > 1) {
621 ret = -EINVAL;
622 goto exit;
623 }
624
625 if (enable == ar->debug.extd_rx_stats) {
626 ret = count;
627 goto exit;
628 }
629
630 if (enable) {
631 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
632 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
633 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
634 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
635 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
636 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
637
638 tlv_filter.rx_filter = rx_filter;
639 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
640 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
641 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
642 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
643 HTT_RX_FP_DATA_FILTER_FLASG3;
644 } else {
645 tlv_filter = ath11k_mac_mon_status_filter_default;
646 }
647
648 ar->debug.rx_filter = tlv_filter.rx_filter;
649
650 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
651 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
652 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
653 HAL_RXDMA_MONITOR_STATUS,
654 DP_RX_BUFFER_SIZE, &tlv_filter);
655
656 if (ret) {
657 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
658 goto exit;
659 }
660 }
661
662 ar->debug.extd_rx_stats = enable;
663 ret = count;
664exit:
665 mutex_unlock(&ar->conf_mutex);
666 return ret;
667}
668
669static ssize_t ath11k_read_extd_rx_stats(struct file *file,
670 char __user *ubuf,
671 size_t count, loff_t *ppos)
672{
673 struct ath11k *ar = file->private_data;
674 char buf[32];
675 int len = 0;
676
677 mutex_lock(&ar->conf_mutex);
678 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
679 ar->debug.extd_rx_stats);
680 mutex_unlock(&ar->conf_mutex);
681
682 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
683}
684
685static const struct file_operations fops_extd_rx_stats = {
686 .read = ath11k_read_extd_rx_stats,
687 .write = ath11k_write_extd_rx_stats,
688 .open = simple_open,
689};
690
691static int ath11k_fill_bp_stats(struct ath11k_base *ab,
692 struct ath11k_bp_stats *bp_stats,
693 char *buf, int len, int size)
694{
695 lockdep_assert_held(&ab->base_lock);
696
697 len += scnprintf(buf + len, size - len, "count: %u\n",
698 bp_stats->count);
699 len += scnprintf(buf + len, size - len, "hp: %u\n",
700 bp_stats->hp);
701 len += scnprintf(buf + len, size - len, "tp: %u\n",
702 bp_stats->tp);
703 len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
704 jiffies_to_msecs(jiffies - bp_stats->jiffies));
705 return len;
706}
707
708static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
709 char *buf, int size)
710{
711 struct ath11k_bp_stats *bp_stats;
712 bool stats_rxd = false;
713 u8 i, pdev_idx;
714 int len = 0;
715
716 len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
717 len += scnprintf(buf + len, size - len, "==================\n");
718
719 spin_lock_bh(&ab->base_lock);
720 for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
721 bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
722
723 if (!bp_stats->count)
724 continue;
725
726 len += scnprintf(buf + len, size - len, "Ring: %s\n",
727 htt_bp_umac_ring[i]);
728 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
729 stats_rxd = true;
730 }
731
732 for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
733 for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
734 bp_stats =
735 &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
736
737 if (!bp_stats->count)
738 continue;
739
740 len += scnprintf(buf + len, size - len, "Ring: %s\n",
741 htt_bp_lmac_ring[i]);
742 len += scnprintf(buf + len, size - len, "pdev: %d\n",
743 pdev_idx);
744 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
745 stats_rxd = true;
746 }
747 }
748 spin_unlock_bh(&ab->base_lock);
749
750 if (!stats_rxd)
751 len += scnprintf(buf + len, size - len,
752 "No Ring Backpressure stats received\n\n");
753
754 return len;
755}
756
757static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
758 char __user *user_buf,
759 size_t count, loff_t *ppos)
760{
761 struct ath11k_base *ab = file->private_data;
762 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
763 int len = 0, i, retval;
764 const int size = 4096;
765 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
766 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
767 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
768 "AMSDU parse", "SA timeout", "DA timeout",
769 "Flow timeout", "Flush req"};
770 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
771 "Desc addr zero", "Desc inval", "AMPDU in non BA",
772 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
773 "Frame OOR", "BAR OOR", "No BA session",
774 "Frame SN equal SSN", "PN check fail", "2k err",
775 "PN err", "Desc blocked"};
776
777 char *buf;
778
779 buf = kzalloc(size, GFP_KERNEL);
780 if (!buf)
781 return -ENOMEM;
782
783 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
784 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
785 soc_stats->err_ring_pkts);
786 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
787 soc_stats->invalid_rbm);
788 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
789 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
790 len += scnprintf(buf + len, size - len, "%s: %u\n",
791 rxdma_err[i], soc_stats->rxdma_error[i]);
792
793 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
794 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
795 len += scnprintf(buf + len, size - len, "%s: %u\n",
796 reo_err[i], soc_stats->reo_error[i]);
797
798 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
799 len += scnprintf(buf + len, size - len,
800 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
801 soc_stats->hal_reo_error[0],
802 soc_stats->hal_reo_error[1],
803 soc_stats->hal_reo_error[2],
804 soc_stats->hal_reo_error[3]);
805
806 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
807 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
808
809 for (i = 0; i < ab->hw_params.max_tx_ring; i++)
810 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
811 i, soc_stats->tx_err.desc_na[i]);
812
813 len += scnprintf(buf + len, size - len,
814 "\nMisc Transmit Failures: %d\n",
815 atomic_read(&soc_stats->tx_err.misc_fail));
816
817 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
818
819 if (len > size)
820 len = size;
821 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
822 kfree(buf);
823
824 return retval;
825}
826
827static const struct file_operations fops_soc_dp_stats = {
828 .read = ath11k_debugfs_dump_soc_dp_stats,
829 .open = simple_open,
830 .owner = THIS_MODULE,
831 .llseek = default_llseek,
832};
833
834int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
835{
836 if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
837 return 0;
838
839 ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
840 if (IS_ERR(ab->debugfs_soc))
841 return PTR_ERR(ab->debugfs_soc);
842
843 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
844 &fops_simulate_fw_crash);
845
846 debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
847 &fops_soc_dp_stats);
848
849 return 0;
850}
851
852void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
853{
854 debugfs_remove_recursive(ab->debugfs_soc);
855 ab->debugfs_soc = NULL;
856}
857
858int ath11k_debugfs_soc_create(struct ath11k_base *ab)
859{
860 ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
861
862 return PTR_ERR_OR_ZERO(ab->debugfs_ath11k);
863}
864
865void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
866{
867 debugfs_remove_recursive(ab->debugfs_ath11k);
868 ab->debugfs_ath11k = NULL;
869}
870EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
871
872void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
873{
874 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
875 ar->debug.debugfs_pdev);
876
877 ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
878
879
880
881
882 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
883 &fops_pdev_stats);
884 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
885 &fops_vdev_stats);
886 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
887 &fops_bcn_stats);
888
889 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
890 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
891 INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
892
893 init_completion(&ar->debug.fw_stats_complete);
894}
895
896static ssize_t ath11k_write_pktlog_filter(struct file *file,
897 const char __user *ubuf,
898 size_t count, loff_t *ppos)
899{
900 struct ath11k *ar = file->private_data;
901 struct ath11k_base *ab = ar->ab;
902 struct htt_rx_ring_tlv_filter tlv_filter = {0};
903 u32 rx_filter = 0, ring_id, filter, mode;
904 u8 buf[128] = {0};
905 int i, ret, rx_buf_sz = 0;
906 ssize_t rc;
907
908 mutex_lock(&ar->conf_mutex);
909 if (ar->state != ATH11K_STATE_ON) {
910 ret = -ENETDOWN;
911 goto out;
912 }
913
914 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
915 if (rc < 0) {
916 ret = rc;
917 goto out;
918 }
919 buf[rc] = '\0';
920
921 ret = sscanf(buf, "0x%x %u", &filter, &mode);
922 if (ret != 2) {
923 ret = -EINVAL;
924 goto out;
925 }
926
927 if (filter) {
928 ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
929 if (ret) {
930 ath11k_warn(ar->ab,
931 "failed to enable pktlog filter %x: %d\n",
932 ar->debug.pktlog_filter, ret);
933 goto out;
934 }
935 } else {
936 ret = ath11k_wmi_pdev_pktlog_disable(ar);
937 if (ret) {
938 ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
939 goto out;
940 }
941 }
942
943
944 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
945 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
946 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
947 HAL_RXDMA_MONITOR_STATUS,
948 rx_buf_sz, &tlv_filter);
949 if (ret) {
950 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
951 goto out;
952 }
953 }
954#define HTT_RX_FILTER_TLV_LITE_MODE \
955 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
956 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
957 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
958 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
959 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
960 HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
961
962 if (mode == ATH11K_PKTLOG_MODE_FULL) {
963 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
964 HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
965 HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
966 HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
967 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
968 HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
969 rx_buf_sz = DP_RX_BUFFER_SIZE;
970 } else if (mode == ATH11K_PKTLOG_MODE_LITE) {
971 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
972 HTT_PPDU_STATS_TAG_PKTLOG);
973 if (ret) {
974 ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
975 goto out;
976 }
977
978 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
979 rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
980 } else {
981 rx_buf_sz = DP_RX_BUFFER_SIZE;
982 tlv_filter = ath11k_mac_mon_status_filter_default;
983 rx_filter = tlv_filter.rx_filter;
984
985 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
986 HTT_PPDU_STATS_TAG_DEFAULT);
987 if (ret) {
988 ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
989 ret);
990 goto out;
991 }
992 }
993
994 tlv_filter.rx_filter = rx_filter;
995 if (rx_filter) {
996 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
997 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
998 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
999 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1000 HTT_RX_FP_DATA_FILTER_FLASG3;
1001 }
1002
1003 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1004 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1005 ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1006 ar->dp.mac_id + i,
1007 HAL_RXDMA_MONITOR_STATUS,
1008 rx_buf_sz, &tlv_filter);
1009
1010 if (ret) {
1011 ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1012 goto out;
1013 }
1014 }
1015
1016 ath11k_info(ab, "pktlog mode %s\n",
1017 ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1018
1019 ar->debug.pktlog_filter = filter;
1020 ar->debug.pktlog_mode = mode;
1021 ret = count;
1022
1023out:
1024 mutex_unlock(&ar->conf_mutex);
1025 return ret;
1026}
1027
1028static ssize_t ath11k_read_pktlog_filter(struct file *file,
1029 char __user *ubuf,
1030 size_t count, loff_t *ppos)
1031
1032{
1033 char buf[32] = {0};
1034 struct ath11k *ar = file->private_data;
1035 int len = 0;
1036
1037 mutex_lock(&ar->conf_mutex);
1038 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1039 ar->debug.pktlog_filter,
1040 ar->debug.pktlog_mode);
1041 mutex_unlock(&ar->conf_mutex);
1042
1043 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1044}
1045
1046static const struct file_operations fops_pktlog_filter = {
1047 .read = ath11k_read_pktlog_filter,
1048 .write = ath11k_write_pktlog_filter,
1049 .open = simple_open
1050};
1051
1052static ssize_t ath11k_write_simulate_radar(struct file *file,
1053 const char __user *user_buf,
1054 size_t count, loff_t *ppos)
1055{
1056 struct ath11k *ar = file->private_data;
1057 int ret;
1058
1059 ret = ath11k_wmi_simulate_radar(ar);
1060 if (ret)
1061 return ret;
1062
1063 return count;
1064}
1065
1066static const struct file_operations fops_simulate_radar = {
1067 .write = ath11k_write_simulate_radar,
1068 .open = simple_open
1069};
1070
1071int ath11k_debugfs_register(struct ath11k *ar)
1072{
1073 struct ath11k_base *ab = ar->ab;
1074 char pdev_name[5];
1075 char buf[100] = {0};
1076
1077 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1078
1079 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1080 if (IS_ERR(ar->debug.debugfs_pdev))
1081 return PTR_ERR(ar->debug.debugfs_pdev);
1082
1083
1084 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1085 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1086
1087 ath11k_debugfs_htt_stats_init(ar);
1088
1089 ath11k_debugfs_fw_stats_init(ar);
1090
1091 debugfs_create_file("ext_tx_stats", 0644,
1092 ar->debug.debugfs_pdev, ar,
1093 &fops_extd_tx_stats);
1094 debugfs_create_file("ext_rx_stats", 0644,
1095 ar->debug.debugfs_pdev, ar,
1096 &fops_extd_rx_stats);
1097 debugfs_create_file("pktlog_filter", 0644,
1098 ar->debug.debugfs_pdev, ar,
1099 &fops_pktlog_filter);
1100
1101 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1102 debugfs_create_file("dfs_simulate_radar", 0200,
1103 ar->debug.debugfs_pdev, ar,
1104 &fops_simulate_radar);
1105 debugfs_create_bool("dfs_block_radar_events", 0200,
1106 ar->debug.debugfs_pdev,
1107 &ar->dfs_block_radar_events);
1108 }
1109
1110 return 0;
1111}
1112
1113void ath11k_debugfs_unregister(struct ath11k *ar)
1114{
1115}
1116