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