WIP FPC-III support
[linux/fpc-iii.git] / drivers / net / wireless / ath / ath11k / debugfs.c
blob554feaf1ed5cd0ace684467e0c64ba9c7e1737af
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
4 */
6 #include "debugfs.h"
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"
16 static 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",
37 static 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",
53 static void ath11k_fw_stats_pdevs_free(struct list_head *head)
55 struct ath11k_fw_stats_pdev *i, *tmp;
57 list_for_each_entry_safe(i, tmp, head, list) {
58 list_del(&i->list);
59 kfree(i);
63 static void ath11k_fw_stats_vdevs_free(struct list_head *head)
65 struct ath11k_fw_stats_vdev *i, *tmp;
67 list_for_each_entry_safe(i, tmp, head, list) {
68 list_del(&i->list);
69 kfree(i);
73 static void ath11k_fw_stats_bcn_free(struct list_head *head)
75 struct ath11k_fw_stats_bcn *i, *tmp;
77 list_for_each_entry_safe(i, tmp, head, list) {
78 list_del(&i->list);
79 kfree(i);
83 static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
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);
92 void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
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;
102 INIT_LIST_HEAD(&stats.pdevs);
103 INIT_LIST_HEAD(&stats.vdevs);
104 INIT_LIST_HEAD(&stats.bcn);
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;
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;
121 spin_lock_bh(&ar->data_lock);
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;
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;
134 /* FW sends all the active VDEV stats irrespective of PDEV,
135 * hence limit until the count of all VDEVs started
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;
143 is_end = ((++num_vdev) == total_vdevs_started);
145 list_splice_tail_init(&stats.vdevs,
146 &ar->debug.fw_stats.vdevs);
148 if (is_end) {
149 ar->debug.fw_stats_done = true;
150 num_vdev = 0;
152 goto complete;
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;
160 /* Mark end until we reached the count of all started VDEVs
161 * within the PDEV
163 is_end = ((++num_bcn) == ar->num_started_vdevs);
165 list_splice_tail_init(&stats.bcn,
166 &ar->debug.fw_stats.bcn);
168 if (is_end) {
169 ar->debug.fw_stats_done = true;
170 num_bcn = 0;
173 complete:
174 complete(&ar->debug.fw_stats_complete);
175 rcu_read_unlock();
176 spin_unlock_bh(&ar->data_lock);
178 free:
179 ath11k_fw_stats_pdevs_free(&stats.pdevs);
180 ath11k_fw_stats_vdevs_free(&stats.vdevs);
181 ath11k_fw_stats_bcn_free(&stats.bcn);
184 static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
185 struct stats_request_params *req_param)
187 struct ath11k_base *ab = ar->ab;
188 unsigned long timeout, time_left;
189 int ret;
191 lockdep_assert_held(&ar->conf_mutex);
193 /* FW stats can get split when exceeding the stats data buffer limit.
194 * In that case, since there is no end marking for the back-to-back
195 * received 'update stats' event, we keep a 3 seconds timeout in case,
196 * fw_stats_done is not marked yet
198 timeout = jiffies + msecs_to_jiffies(3 * HZ);
200 ath11k_debugfs_fw_stats_reset(ar);
202 reinit_completion(&ar->debug.fw_stats_complete);
204 ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
206 if (ret) {
207 ath11k_warn(ab, "could not request fw stats (%d)\n",
208 ret);
209 return ret;
212 time_left =
213 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
214 1 * HZ);
215 if (!time_left)
216 return -ETIMEDOUT;
218 for (;;) {
219 if (time_after(jiffies, timeout))
220 break;
222 spin_lock_bh(&ar->data_lock);
223 if (ar->debug.fw_stats_done) {
224 spin_unlock_bh(&ar->data_lock);
225 break;
227 spin_unlock_bh(&ar->data_lock);
229 return 0;
232 static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
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;
240 mutex_lock(&ar->conf_mutex);
242 if (ar->state != ATH11K_STATE_ON) {
243 ret = -ENETDOWN;
244 goto err_unlock;
247 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
248 if (!buf) {
249 ret = -ENOMEM;
250 goto err_unlock;
253 req_param.pdev_id = ar->pdev->pdev_id;
254 req_param.vdev_id = 0;
255 req_param.stats_id = WMI_REQUEST_PDEV_STAT;
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;
263 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
264 buf);
266 file->private_data = buf;
268 mutex_unlock(&ar->conf_mutex);
269 return 0;
271 err_free:
272 vfree(buf);
274 err_unlock:
275 mutex_unlock(&ar->conf_mutex);
276 return ret;
279 static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
281 vfree(file->private_data);
283 return 0;
286 static ssize_t ath11k_read_pdev_stats(struct file *file,
287 char __user *user_buf,
288 size_t count, loff_t *ppos)
290 const char *buf = file->private_data;
291 size_t len = strlen(buf);
293 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
296 static 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,
304 static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
306 struct ath11k *ar = inode->i_private;
307 struct stats_request_params req_param;
308 void *buf = NULL;
309 int ret;
311 mutex_lock(&ar->conf_mutex);
313 if (ar->state != ATH11K_STATE_ON) {
314 ret = -ENETDOWN;
315 goto err_unlock;
318 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
319 if (!buf) {
320 ret = -ENOMEM;
321 goto err_unlock;
324 req_param.pdev_id = ar->pdev->pdev_id;
325 /* VDEV stats is always sent for all active VDEVs from FW */
326 req_param.vdev_id = 0;
327 req_param.stats_id = WMI_REQUEST_VDEV_STAT;
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;
335 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
336 buf);
338 file->private_data = buf;
340 mutex_unlock(&ar->conf_mutex);
341 return 0;
343 err_free:
344 vfree(buf);
346 err_unlock:
347 mutex_unlock(&ar->conf_mutex);
348 return ret;
351 static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
353 vfree(file->private_data);
355 return 0;
358 static ssize_t ath11k_read_vdev_stats(struct file *file,
359 char __user *user_buf,
360 size_t count, loff_t *ppos)
362 const char *buf = file->private_data;
363 size_t len = strlen(buf);
365 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
368 static 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,
376 static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
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;
384 mutex_lock(&ar->conf_mutex);
386 if (ar->state != ATH11K_STATE_ON) {
387 ret = -ENETDOWN;
388 goto err_unlock;
391 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
392 if (!buf) {
393 ret = -ENOMEM;
394 goto err_unlock;
397 req_param.stats_id = WMI_REQUEST_BCN_STAT;
398 req_param.pdev_id = ar->pdev->pdev_id;
400 /* loop all active VDEVs for bcn stats */
401 list_for_each_entry(arvif, &ar->arvifs, list) {
402 if (!arvif->is_up)
403 continue;
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;
413 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
414 buf);
416 /* since beacon stats request is looped for all active VDEVs, saved fw
417 * stats is not freed for each request until done for all active VDEVs
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);
423 file->private_data = buf;
425 mutex_unlock(&ar->conf_mutex);
426 return 0;
428 err_free:
429 vfree(buf);
431 err_unlock:
432 mutex_unlock(&ar->conf_mutex);
433 return ret;
436 static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
438 vfree(file->private_data);
440 return 0;
443 static ssize_t ath11k_read_bcn_stats(struct file *file,
444 char __user *user_buf,
445 size_t count, loff_t *ppos)
447 const char *buf = file->private_data;
448 size_t len = strlen(buf);
450 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
453 static 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,
461 static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
462 char __user *user_buf,
463 size_t count, loff_t *ppos)
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";
470 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
473 /* Simulate firmware crash:
474 * 'soft': Call wmi command causing firmware hang. This firmware hang is
475 * recoverable by warm firmware reset.
476 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
477 * vdev id. This is hard firmware crash because it is recoverable only by cold
478 * firmware reset.
480 static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
481 const char __user *user_buf,
482 size_t count, loff_t *ppos)
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;
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;
499 /* filter partial writes and invalid commands */
500 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
501 return -EINVAL;
503 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
504 if (rc < 0)
505 return rc;
507 /* drop the possible '\n' from the end */
508 if (buf[*ppos - 1] == '\n')
509 buf[*ppos - 1] = '\0';
511 if (radioup == 0) {
512 ret = -ENETDOWN;
513 goto exit;
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;
526 if (ret) {
527 ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
528 goto exit;
531 ret = count;
533 exit:
534 return ret;
537 static 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,
545 static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
546 const char __user *ubuf,
547 size_t count, loff_t *ppos)
549 struct ath11k *ar = file->private_data;
550 u32 filter;
551 int ret;
553 if (kstrtouint_from_user(ubuf, count, 0, &filter))
554 return -EINVAL;
556 mutex_lock(&ar->conf_mutex);
558 if (ar->state != ATH11K_STATE_ON) {
559 ret = -ENETDOWN;
560 goto out;
563 if (filter == ar->debug.extd_tx_stats) {
564 ret = count;
565 goto out;
568 ar->debug.extd_tx_stats = filter;
569 ret = count;
571 out:
572 mutex_unlock(&ar->conf_mutex);
573 return ret;
576 static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
577 char __user *ubuf,
578 size_t count, loff_t *ppos)
581 char buf[32] = {0};
582 struct ath11k *ar = file->private_data;
583 int len = 0;
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);
590 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
593 static 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
599 static ssize_t ath11k_write_extd_rx_stats(struct file *file,
600 const char __user *ubuf,
601 size_t count, loff_t *ppos)
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;
610 if (kstrtouint_from_user(ubuf, count, 0, &enable))
611 return -EINVAL;
613 mutex_lock(&ar->conf_mutex);
615 if (ar->state != ATH11K_STATE_ON) {
616 ret = -ENETDOWN;
617 goto exit;
620 if (enable > 1) {
621 ret = -EINVAL;
622 goto exit;
625 if (enable == ar->debug.extd_rx_stats) {
626 ret = count;
627 goto exit;
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;
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;
648 ar->debug.rx_filter = tlv_filter.rx_filter;
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);
656 if (ret) {
657 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
658 goto exit;
662 ar->debug.extd_rx_stats = enable;
663 ret = count;
664 exit:
665 mutex_unlock(&ar->conf_mutex);
666 return ret;
669 static ssize_t ath11k_read_extd_rx_stats(struct file *file,
670 char __user *ubuf,
671 size_t count, loff_t *ppos)
673 struct ath11k *ar = file->private_data;
674 char buf[32];
675 int len = 0;
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);
682 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
685 static 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,
691 static int ath11k_fill_bp_stats(struct ath11k_base *ab,
692 struct ath11k_bp_stats *bp_stats,
693 char *buf, int len, int size)
695 lockdep_assert_held(&ab->base_lock);
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;
708 static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
709 char *buf, int size)
711 struct ath11k_bp_stats *bp_stats;
712 bool stats_rxd = false;
713 u8 i, pdev_idx;
714 int len = 0;
716 len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
717 len += scnprintf(buf + len, size - len, "==================\n");
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];
723 if (!bp_stats->count)
724 continue;
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;
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];
737 if (!bp_stats->count)
738 continue;
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;
748 spin_unlock_bh(&ab->base_lock);
750 if (!stats_rxd)
751 len += scnprintf(buf + len, size - len,
752 "No Ring Backpressure stats received\n\n");
754 return len;
757 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
758 char __user *user_buf,
759 size_t count, loff_t *ppos)
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"};
777 char *buf;
779 buf = kzalloc(size, GFP_KERNEL);
780 if (!buf)
781 return -ENOMEM;
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]);
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]);
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]);
806 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
807 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
809 for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
810 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
811 i, soc_stats->tx_err.desc_na[i]);
813 len += scnprintf(buf + len, size - len,
814 "\nMisc Transmit Failures: %d\n",
815 atomic_read(&soc_stats->tx_err.misc_fail));
817 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
819 if (len > size)
820 len = size;
821 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
822 kfree(buf);
824 return retval;
827 static 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,
834 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
836 if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
837 return 0;
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);
843 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
844 &fops_simulate_fw_crash);
846 debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
847 &fops_soc_dp_stats);
849 return 0;
852 void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
854 debugfs_remove_recursive(ab->debugfs_soc);
855 ab->debugfs_soc = NULL;
858 int ath11k_debugfs_soc_create(struct ath11k_base *ab)
860 ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
862 return PTR_ERR_OR_ZERO(ab->debugfs_ath11k);
865 void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
867 debugfs_remove_recursive(ab->debugfs_ath11k);
868 ab->debugfs_ath11k = NULL;
870 EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
872 void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
874 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
875 ar->debug.debugfs_pdev);
877 ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
879 /* all stats debugfs files created are under "fw_stats" directory
880 * created per PDEV
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);
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);
893 init_completion(&ar->debug.fw_stats_complete);
896 static ssize_t ath11k_write_pktlog_filter(struct file *file,
897 const char __user *ubuf,
898 size_t count, loff_t *ppos)
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;
906 ssize_t rc;
908 mutex_lock(&ar->conf_mutex);
909 if (ar->state != ATH11K_STATE_ON) {
910 ret = -ENETDOWN;
911 goto out;
914 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
915 if (rc < 0) {
916 ret = rc;
917 goto out;
919 buf[rc] = '\0';
921 ret = sscanf(buf, "0x%x %u", &filter, &mode);
922 if (ret != 2) {
923 ret = -EINVAL;
924 goto out;
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;
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;
943 #define HTT_RX_FILTER_TLV_LITE_MODE \
944 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
945 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
946 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
947 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
948 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
949 HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
951 if (mode == ATH11K_PKTLOG_MODE_FULL) {
952 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
953 HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
954 HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
955 HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
956 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
957 HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
958 } else if (mode == ATH11K_PKTLOG_MODE_LITE) {
959 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
960 HTT_PPDU_STATS_TAG_PKTLOG);
961 if (ret) {
962 ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
963 goto out;
966 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
967 } else {
968 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
969 HTT_PPDU_STATS_TAG_DEFAULT);
970 if (ret) {
971 ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
972 ret);
973 goto out;
977 tlv_filter.rx_filter = rx_filter;
978 if (rx_filter) {
979 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
980 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
981 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
982 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
983 HTT_RX_FP_DATA_FILTER_FLASG3;
986 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
987 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
988 ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
989 ar->dp.mac_id + i,
990 HAL_RXDMA_MONITOR_STATUS,
991 DP_RX_BUFFER_SIZE, &tlv_filter);
993 if (ret) {
994 ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
995 goto out;
999 ath11k_dbg(ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n",
1000 filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1002 ar->debug.pktlog_filter = filter;
1003 ar->debug.pktlog_mode = mode;
1004 ret = count;
1006 out:
1007 mutex_unlock(&ar->conf_mutex);
1008 return ret;
1011 static ssize_t ath11k_read_pktlog_filter(struct file *file,
1012 char __user *ubuf,
1013 size_t count, loff_t *ppos)
1016 char buf[32] = {0};
1017 struct ath11k *ar = file->private_data;
1018 int len = 0;
1020 mutex_lock(&ar->conf_mutex);
1021 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1022 ar->debug.pktlog_filter,
1023 ar->debug.pktlog_mode);
1024 mutex_unlock(&ar->conf_mutex);
1026 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1029 static const struct file_operations fops_pktlog_filter = {
1030 .read = ath11k_read_pktlog_filter,
1031 .write = ath11k_write_pktlog_filter,
1032 .open = simple_open
1035 static ssize_t ath11k_write_simulate_radar(struct file *file,
1036 const char __user *user_buf,
1037 size_t count, loff_t *ppos)
1039 struct ath11k *ar = file->private_data;
1040 int ret;
1042 ret = ath11k_wmi_simulate_radar(ar);
1043 if (ret)
1044 return ret;
1046 return count;
1049 static const struct file_operations fops_simulate_radar = {
1050 .write = ath11k_write_simulate_radar,
1051 .open = simple_open
1054 int ath11k_debugfs_register(struct ath11k *ar)
1056 struct ath11k_base *ab = ar->ab;
1057 char pdev_name[5];
1058 char buf[100] = {0};
1060 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1062 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1063 if (IS_ERR(ar->debug.debugfs_pdev))
1064 return PTR_ERR(ar->debug.debugfs_pdev);
1066 /* Create a symlink under ieee80211/phy* */
1067 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1068 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1070 ath11k_debugfs_htt_stats_init(ar);
1072 ath11k_debugfs_fw_stats_init(ar);
1074 debugfs_create_file("ext_tx_stats", 0644,
1075 ar->debug.debugfs_pdev, ar,
1076 &fops_extd_tx_stats);
1077 debugfs_create_file("ext_rx_stats", 0644,
1078 ar->debug.debugfs_pdev, ar,
1079 &fops_extd_rx_stats);
1080 debugfs_create_file("pktlog_filter", 0644,
1081 ar->debug.debugfs_pdev, ar,
1082 &fops_pktlog_filter);
1084 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1085 debugfs_create_file("dfs_simulate_radar", 0200,
1086 ar->debug.debugfs_pdev, ar,
1087 &fops_simulate_radar);
1088 debugfs_create_bool("dfs_block_radar_events", 0200,
1089 ar->debug.debugfs_pdev,
1090 &ar->dfs_block_radar_events);
1093 return 0;
1096 void ath11k_debugfs_unregister(struct ath11k *ar)