1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
6 #include <linux/vmalloc.h>
15 #include "debugfs_htt_stats.h"
18 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
31 "WBM2SW0_RELEASE_RING",
32 "WBM2SW1_RELEASE_RING",
33 "WBM2SW2_RELEASE_RING",
34 "WBM2SW3_RELEASE_RING",
39 static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
41 "FW2RXDMA_STATUS_RING",
44 "WBM2RXDMA_LINK_RING",
49 "MONITOR_STATUS_RING",
55 void 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)
60 struct ath11k_debug_dbr *dbr_debug;
61 struct ath11k_dbg_dbr_data *dbr_data;
62 struct ath11k_dbg_dbr_entry *entry;
64 if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
67 dbr_debug = ar->debug.dbr_debug[id];
71 if (!dbr_debug->dbr_debug_enabled)
74 dbr_data = &dbr_debug->dbr_dbg_data;
76 spin_lock_bh(&dbr_data->lock);
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;
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;
91 spin_unlock_bh(&dbr_data->lock);
94 static void ath11k_fw_stats_pdevs_free(struct list_head *head)
96 struct ath11k_fw_stats_pdev *i, *tmp;
98 list_for_each_entry_safe(i, tmp, head, list) {
104 static void ath11k_fw_stats_vdevs_free(struct list_head *head)
106 struct ath11k_fw_stats_vdev *i, *tmp;
108 list_for_each_entry_safe(i, tmp, head, list) {
114 static void ath11k_fw_stats_bcn_free(struct list_head *head)
116 struct ath11k_fw_stats_bcn *i, *tmp;
118 list_for_each_entry_safe(i, tmp, head, list) {
124 static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
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);
133 void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
135 struct ath11k_fw_stats stats = {};
137 struct ath11k_pdev *pdev;
139 static unsigned int num_vdev, num_bcn;
140 size_t total_vdevs_started = 0;
143 INIT_LIST_HEAD(&stats.pdevs);
144 INIT_LIST_HEAD(&stats.vdevs);
145 INIT_LIST_HEAD(&stats.bcn);
147 ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
149 ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
154 ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
157 ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
162 spin_lock_bh(&ar->data_lock);
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;
170 if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
171 ar->debug.fw_stats_done = true;
175 if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
176 if (list_empty(&stats.vdevs)) {
177 ath11k_warn(ab, "empty vdev stats");
180 /* FW sends all the active VDEV stats irrespective of PDEV,
181 * hence limit until the count of all VDEVs started
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;
189 is_end = ((++num_vdev) == total_vdevs_started);
191 list_splice_tail_init(&stats.vdevs,
192 &ar->debug.fw_stats.vdevs);
195 ar->debug.fw_stats_done = true;
201 if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
202 if (list_empty(&stats.bcn)) {
203 ath11k_warn(ab, "empty bcn stats");
206 /* Mark end until we reached the count of all started VDEVs
209 is_end = ((++num_bcn) == ar->num_started_vdevs);
211 list_splice_tail_init(&stats.bcn,
212 &ar->debug.fw_stats.bcn);
215 ar->debug.fw_stats_done = true;
220 complete(&ar->debug.fw_stats_complete);
222 spin_unlock_bh(&ar->data_lock);
225 ath11k_fw_stats_pdevs_free(&stats.pdevs);
226 ath11k_fw_stats_vdevs_free(&stats.vdevs);
227 ath11k_fw_stats_bcn_free(&stats.bcn);
230 static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
231 struct stats_request_params *req_param)
233 struct ath11k_base *ab = ar->ab;
234 unsigned long timeout, time_left;
237 lockdep_assert_held(&ar->conf_mutex);
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
244 timeout = jiffies + msecs_to_jiffies(3 * 1000);
246 ath11k_debugfs_fw_stats_reset(ar);
248 reinit_completion(&ar->debug.fw_stats_complete);
250 ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
253 ath11k_warn(ab, "could not request fw stats (%d)\n",
259 wait_for_completion_timeout(&ar->debug.fw_stats_complete,
265 if (time_after(jiffies, timeout))
268 spin_lock_bh(&ar->data_lock);
269 if (ar->debug.fw_stats_done) {
270 spin_unlock_bh(&ar->data_lock);
273 spin_unlock_bh(&ar->data_lock);
278 int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
279 u32 vdev_id, u32 stats_id)
281 struct ath11k_base *ab = ar->ab;
282 struct stats_request_params req_param;
285 mutex_lock(&ar->conf_mutex);
287 if (ar->state != ATH11K_STATE_ON) {
292 req_param.pdev_id = pdev_id;
293 req_param.vdev_id = vdev_id;
294 req_param.stats_id = stats_id;
296 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
298 ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
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);
305 mutex_unlock(&ar->conf_mutex);
310 static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
312 struct ath11k *ar = inode->i_private;
313 struct ath11k_base *ab = ar->ab;
314 struct stats_request_params req_param;
318 mutex_lock(&ar->conf_mutex);
320 if (ar->state != ATH11K_STATE_ON) {
325 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
331 req_param.pdev_id = ar->pdev->pdev_id;
332 req_param.vdev_id = 0;
333 req_param.stats_id = WMI_REQUEST_PDEV_STAT;
335 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
337 ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
341 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
344 file->private_data = buf;
346 mutex_unlock(&ar->conf_mutex);
353 mutex_unlock(&ar->conf_mutex);
357 static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
359 vfree(file->private_data);
364 static ssize_t ath11k_read_pdev_stats(struct file *file,
365 char __user *user_buf,
366 size_t count, loff_t *ppos)
368 const char *buf = file->private_data;
369 size_t len = strlen(buf);
371 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
374 static 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,
382 static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
384 struct ath11k *ar = inode->i_private;
385 struct stats_request_params req_param;
389 mutex_lock(&ar->conf_mutex);
391 if (ar->state != ATH11K_STATE_ON) {
396 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
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;
407 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
409 ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
413 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
416 file->private_data = buf;
418 mutex_unlock(&ar->conf_mutex);
425 mutex_unlock(&ar->conf_mutex);
429 static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
431 vfree(file->private_data);
436 static ssize_t ath11k_read_vdev_stats(struct file *file,
437 char __user *user_buf,
438 size_t count, loff_t *ppos)
440 const char *buf = file->private_data;
441 size_t len = strlen(buf);
443 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
446 static 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,
454 static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
456 struct ath11k *ar = inode->i_private;
457 struct ath11k_vif *arvif;
458 struct stats_request_params req_param;
462 mutex_lock(&ar->conf_mutex);
464 if (ar->state != ATH11K_STATE_ON) {
469 buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
475 req_param.stats_id = WMI_REQUEST_BCN_STAT;
476 req_param.pdev_id = ar->pdev->pdev_id;
478 /* loop all active VDEVs for bcn stats */
479 list_for_each_entry(arvif, &ar->arvifs, list) {
483 req_param.vdev_id = arvif->vdev_id;
484 ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
486 ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
491 ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
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
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);
501 file->private_data = buf;
503 mutex_unlock(&ar->conf_mutex);
510 mutex_unlock(&ar->conf_mutex);
514 static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
516 vfree(file->private_data);
521 static ssize_t ath11k_read_bcn_stats(struct file *file,
522 char __user *user_buf,
523 size_t count, loff_t *ppos)
525 const char *buf = file->private_data;
526 size_t len = strlen(buf);
528 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
531 static 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,
539 static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
540 char __user *user_buf,
541 size_t count, loff_t *ppos)
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";
548 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
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
558 static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
559 const char __user *user_buf,
560 size_t count, loff_t *ppos)
562 struct ath11k_base *ab = file->private_data;
563 struct ath11k_pdev *pdev;
564 struct ath11k *ar = ab->pdevs[0].ar;
567 int i, ret, radioup = 0;
569 for (i = 0; i < ab->num_radios; i++) {
570 pdev = &ab->pdevs[i];
572 if (ar && ar->state == ATH11K_STATE_ON) {
577 /* filter partial writes and invalid commands */
578 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
581 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
585 /* drop the possible '\n' from the end */
586 if (buf[*ppos - 1] == '\n')
587 buf[*ppos - 1] = '\0';
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 if (!strcmp(buf, "hw-restart")) {
600 ath11k_info(ab, "user requested hw restart\n");
601 queue_work(ab->workqueue_aux, &ab->reset_work);
609 ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
619 static const struct file_operations fops_simulate_fw_crash = {
620 .read = ath11k_read_simulate_fw_crash,
621 .write = ath11k_write_simulate_fw_crash,
623 .owner = THIS_MODULE,
624 .llseek = default_llseek,
627 static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
628 const char __user *ubuf,
629 size_t count, loff_t *ppos)
631 struct ath11k *ar = file->private_data;
635 if (kstrtouint_from_user(ubuf, count, 0, &filter))
638 mutex_lock(&ar->conf_mutex);
640 if (ar->state != ATH11K_STATE_ON) {
645 if (filter == ar->debug.extd_tx_stats) {
650 ar->debug.extd_tx_stats = filter;
654 mutex_unlock(&ar->conf_mutex);
658 static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
660 size_t count, loff_t *ppos)
664 struct ath11k *ar = file->private_data;
667 mutex_lock(&ar->conf_mutex);
668 len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
669 ar->debug.extd_tx_stats);
670 mutex_unlock(&ar->conf_mutex);
672 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
675 static const struct file_operations fops_extd_tx_stats = {
676 .read = ath11k_read_enable_extd_tx_stats,
677 .write = ath11k_write_enable_extd_tx_stats,
681 static ssize_t ath11k_write_extd_rx_stats(struct file *file,
682 const char __user *ubuf,
683 size_t count, loff_t *ppos)
685 struct ath11k *ar = file->private_data;
686 struct ath11k_base *ab = ar->ab;
687 struct htt_rx_ring_tlv_filter tlv_filter = {0};
688 u32 enable, rx_filter = 0, ring_id;
692 if (kstrtouint_from_user(ubuf, count, 0, &enable))
695 mutex_lock(&ar->conf_mutex);
697 if (ar->state != ATH11K_STATE_ON) {
707 if (enable == ar->debug.extd_rx_stats) {
712 if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
713 ar->debug.extd_rx_stats = enable;
719 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
720 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
721 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
722 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
723 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
724 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
726 tlv_filter.rx_filter = rx_filter;
727 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
728 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
729 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
730 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
731 HTT_RX_FP_DATA_FILTER_FLASG3;
733 tlv_filter = ath11k_mac_mon_status_filter_default;
736 ar->debug.rx_filter = tlv_filter.rx_filter;
738 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
739 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
740 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
741 HAL_RXDMA_MONITOR_STATUS,
742 DP_RX_BUFFER_SIZE, &tlv_filter);
745 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
750 ar->debug.extd_rx_stats = enable;
753 mutex_unlock(&ar->conf_mutex);
757 static ssize_t ath11k_read_extd_rx_stats(struct file *file,
759 size_t count, loff_t *ppos)
761 struct ath11k *ar = file->private_data;
765 mutex_lock(&ar->conf_mutex);
766 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
767 ar->debug.extd_rx_stats);
768 mutex_unlock(&ar->conf_mutex);
770 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
773 static const struct file_operations fops_extd_rx_stats = {
774 .read = ath11k_read_extd_rx_stats,
775 .write = ath11k_write_extd_rx_stats,
779 static int ath11k_fill_bp_stats(struct ath11k_base *ab,
780 struct ath11k_bp_stats *bp_stats,
781 char *buf, int len, int size)
783 lockdep_assert_held(&ab->base_lock);
785 len += scnprintf(buf + len, size - len, "count: %u\n",
787 len += scnprintf(buf + len, size - len, "hp: %u\n",
789 len += scnprintf(buf + len, size - len, "tp: %u\n",
791 len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
792 jiffies_to_msecs(jiffies - bp_stats->jiffies));
796 static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
799 struct ath11k_bp_stats *bp_stats;
800 bool stats_rxd = false;
804 len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
805 len += scnprintf(buf + len, size - len, "==================\n");
807 spin_lock_bh(&ab->base_lock);
808 for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
809 bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
811 if (!bp_stats->count)
814 len += scnprintf(buf + len, size - len, "Ring: %s\n",
815 htt_bp_umac_ring[i]);
816 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
820 for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
821 for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
823 &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
825 if (!bp_stats->count)
828 len += scnprintf(buf + len, size - len, "Ring: %s\n",
829 htt_bp_lmac_ring[i]);
830 len += scnprintf(buf + len, size - len, "pdev: %d\n",
832 len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
836 spin_unlock_bh(&ab->base_lock);
839 len += scnprintf(buf + len, size - len,
840 "No Ring Backpressure stats received\n\n");
845 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
846 char __user *user_buf,
847 size_t count, loff_t *ppos)
849 struct ath11k_base *ab = file->private_data;
850 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
851 int len = 0, i, retval;
852 const int size = 4096;
853 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
854 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
855 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
856 "AMSDU parse", "SA timeout", "DA timeout",
857 "Flow timeout", "Flush req"};
858 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
859 "Desc addr zero", "Desc inval", "AMPDU in non BA",
860 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
861 "Frame OOR", "BAR OOR", "No BA session",
862 "Frame SN equal SSN", "PN check fail", "2k err",
863 "PN err", "Desc blocked"};
867 buf = kzalloc(size, GFP_KERNEL);
871 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
872 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
873 soc_stats->err_ring_pkts);
874 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
875 soc_stats->invalid_rbm);
876 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
877 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
878 len += scnprintf(buf + len, size - len, "%s: %u\n",
879 rxdma_err[i], soc_stats->rxdma_error[i]);
881 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
882 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
883 len += scnprintf(buf + len, size - len, "%s: %u\n",
884 reo_err[i], soc_stats->reo_error[i]);
886 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
887 len += scnprintf(buf + len, size - len,
888 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
889 soc_stats->hal_reo_error[0],
890 soc_stats->hal_reo_error[1],
891 soc_stats->hal_reo_error[2],
892 soc_stats->hal_reo_error[3]);
894 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
895 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
897 for (i = 0; i < ab->hw_params.max_tx_ring; i++)
898 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
899 i, soc_stats->tx_err.desc_na[i]);
901 len += scnprintf(buf + len, size - len,
902 "\nMisc Transmit Failures: %d\n",
903 atomic_read(&soc_stats->tx_err.misc_fail));
905 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
909 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
915 static const struct file_operations fops_soc_dp_stats = {
916 .read = ath11k_debugfs_dump_soc_dp_stats,
918 .owner = THIS_MODULE,
919 .llseek = default_llseek,
922 static ssize_t ath11k_write_fw_dbglog(struct file *file,
923 const char __user *user_buf,
924 size_t count, loff_t *ppos)
926 struct ath11k *ar = file->private_data;
928 struct ath11k_fw_dbglog dbglog;
929 unsigned int param, mod_id_index, is_end;
933 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
938 num = sscanf(buf, "%u %llx %u %u", ¶m, &value, &mod_id_index, &is_end);
943 mutex_lock(&ar->conf_mutex);
944 if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
945 param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
946 if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
950 ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
962 dbglog.param = param;
963 dbglog.value = lower_32_bits(value);
964 ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
966 ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
974 mutex_unlock(&ar->conf_mutex);
978 static const struct file_operations fops_fw_dbglog = {
979 .write = ath11k_write_fw_dbglog,
981 .owner = THIS_MODULE,
982 .llseek = default_llseek,
985 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
987 if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
990 ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
991 if (IS_ERR(ab->debugfs_soc))
992 return PTR_ERR(ab->debugfs_soc);
994 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
995 &fops_simulate_fw_crash);
997 debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
1003 void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
1005 debugfs_remove_recursive(ab->debugfs_soc);
1006 ab->debugfs_soc = NULL;
1009 int ath11k_debugfs_soc_create(struct ath11k_base *ab)
1011 ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
1013 return PTR_ERR_OR_ZERO(ab->debugfs_ath11k);
1016 void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
1018 debugfs_remove_recursive(ab->debugfs_ath11k);
1019 ab->debugfs_ath11k = NULL;
1021 EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
1023 void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
1025 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1026 ar->debug.debugfs_pdev);
1028 ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
1030 /* all stats debugfs files created are under "fw_stats" directory
1033 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1035 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1037 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1040 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
1041 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
1042 INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
1044 init_completion(&ar->debug.fw_stats_complete);
1047 static ssize_t ath11k_write_pktlog_filter(struct file *file,
1048 const char __user *ubuf,
1049 size_t count, loff_t *ppos)
1051 struct ath11k *ar = file->private_data;
1052 struct ath11k_base *ab = ar->ab;
1053 struct htt_rx_ring_tlv_filter tlv_filter = {0};
1054 u32 rx_filter = 0, ring_id, filter, mode;
1056 int i, ret, rx_buf_sz = 0;
1059 mutex_lock(&ar->conf_mutex);
1060 if (ar->state != ATH11K_STATE_ON) {
1065 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1072 ret = sscanf(buf, "0x%x %u", &filter, &mode);
1079 ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
1082 "failed to enable pktlog filter %x: %d\n",
1083 ar->debug.pktlog_filter, ret);
1087 ret = ath11k_wmi_pdev_pktlog_disable(ar);
1089 ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
1094 /* Clear rx filter set for monitor mode and rx status */
1095 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1096 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1097 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
1098 HAL_RXDMA_MONITOR_STATUS,
1099 rx_buf_sz, &tlv_filter);
1101 ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1105 #define HTT_RX_FILTER_TLV_LITE_MODE \
1106 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
1107 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
1108 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
1109 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
1110 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
1111 HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
1113 if (mode == ATH11K_PKTLOG_MODE_FULL) {
1114 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
1115 HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
1116 HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
1117 HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
1118 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
1119 HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
1120 rx_buf_sz = DP_RX_BUFFER_SIZE;
1121 } else if (mode == ATH11K_PKTLOG_MODE_LITE) {
1122 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1123 HTT_PPDU_STATS_TAG_PKTLOG);
1125 ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1129 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1130 rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
1132 rx_buf_sz = DP_RX_BUFFER_SIZE;
1133 tlv_filter = ath11k_mac_mon_status_filter_default;
1134 rx_filter = tlv_filter.rx_filter;
1136 ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1137 HTT_PPDU_STATS_TAG_DEFAULT);
1139 ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1145 tlv_filter.rx_filter = rx_filter;
1147 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1148 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1149 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1150 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1151 HTT_RX_FP_DATA_FILTER_FLASG3;
1154 for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
1155 ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1156 ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1158 HAL_RXDMA_MONITOR_STATUS,
1159 rx_buf_sz, &tlv_filter);
1162 ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1167 ath11k_info(ab, "pktlog mode %s\n",
1168 ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1170 ar->debug.pktlog_filter = filter;
1171 ar->debug.pktlog_mode = mode;
1175 mutex_unlock(&ar->conf_mutex);
1179 static ssize_t ath11k_read_pktlog_filter(struct file *file,
1181 size_t count, loff_t *ppos)
1185 struct ath11k *ar = file->private_data;
1188 mutex_lock(&ar->conf_mutex);
1189 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1190 ar->debug.pktlog_filter,
1191 ar->debug.pktlog_mode);
1192 mutex_unlock(&ar->conf_mutex);
1194 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1197 static const struct file_operations fops_pktlog_filter = {
1198 .read = ath11k_read_pktlog_filter,
1199 .write = ath11k_write_pktlog_filter,
1203 static ssize_t ath11k_write_simulate_radar(struct file *file,
1204 const char __user *user_buf,
1205 size_t count, loff_t *ppos)
1207 struct ath11k *ar = file->private_data;
1210 ret = ath11k_wmi_simulate_radar(ar);
1217 static const struct file_operations fops_simulate_radar = {
1218 .write = ath11k_write_simulate_radar,
1222 static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
1223 char __user *user_buf,
1224 size_t count, loff_t *ppos)
1226 struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
1227 static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
1228 int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
1233 buf = kzalloc(size, GFP_KERNEL);
1237 len += scnprintf(buf + len, size - len,
1238 "-----------------------------------------\n");
1239 len += scnprintf(buf + len, size - len,
1240 "| idx | hp | tp | timestamp | event |\n");
1241 len += scnprintf(buf + len, size - len,
1242 "-----------------------------------------\n");
1244 spin_lock_bh(&dbr_dbg_data->lock);
1246 for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
1247 len += scnprintf(buf + len, size - len,
1248 "|%4u|%8u|%8u|%11llu|%8s|\n", i,
1249 dbr_dbg_data->entries[i].hp,
1250 dbr_dbg_data->entries[i].tp,
1251 dbr_dbg_data->entries[i].timestamp,
1252 event_id_to_string[dbr_dbg_data->entries[i].event]);
1255 spin_unlock_bh(&dbr_dbg_data->lock);
1257 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1263 static const struct file_operations fops_debug_dump_dbr_entries = {
1264 .read = ath11k_debug_dump_dbr_entries,
1265 .open = simple_open,
1266 .owner = THIS_MODULE,
1267 .llseek = default_llseek,
1270 static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
1272 struct ath11k_debug_dbr *dbr_debug;
1273 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1275 if (!ar->debug.dbr_debug[dbr_id])
1278 dbr_debug = ar->debug.dbr_debug[dbr_id];
1279 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1281 debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1282 kfree(dbr_dbg_data->entries);
1284 ar->debug.dbr_debug[dbr_id] = NULL;
1287 static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
1289 struct ath11k_debug_dbr *dbr_debug;
1290 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1291 static const char * const dbr_id_to_str[] = {"spectral", "CFR"};
1293 if (ar->debug.dbr_debug[dbr_id])
1296 ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
1299 if (!ar->debug.dbr_debug[dbr_id])
1302 dbr_debug = ar->debug.dbr_debug[dbr_id];
1303 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1305 if (dbr_debug->dbr_debugfs)
1308 dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
1309 ar->debug.debugfs_pdev);
1310 if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
1311 if (IS_ERR(dbr_debug->dbr_debugfs))
1312 return PTR_ERR(dbr_debug->dbr_debugfs);
1316 dbr_debug->dbr_debug_enabled = true;
1317 dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
1318 dbr_dbg_data->dbr_debug_idx = 0;
1319 dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
1320 sizeof(struct ath11k_dbg_dbr_entry),
1322 if (!dbr_dbg_data->entries)
1325 spin_lock_init(&dbr_dbg_data->lock);
1327 debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
1328 dbr_dbg_data, &fops_debug_dump_dbr_entries);
1333 static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
1334 const char __user *ubuf,
1335 size_t count, loff_t *ppos)
1337 struct ath11k *ar = file->private_data;
1342 mutex_lock(&ar->conf_mutex);
1344 if (ar->state != ATH11K_STATE_ON) {
1349 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1354 ret = sscanf(buf, "%u %u", &dbr_id, &enable);
1355 if (ret != 2 || dbr_id > 1 || enable > 1) {
1357 ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
1362 ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
1364 ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
1369 ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
1374 mutex_unlock(&ar->conf_mutex);
1378 static const struct file_operations fops_dbr_debug = {
1379 .write = ath11k_debugfs_write_enable_dbr_dbg,
1380 .open = simple_open,
1381 .owner = THIS_MODULE,
1382 .llseek = default_llseek,
1385 int ath11k_debugfs_register(struct ath11k *ar)
1387 struct ath11k_base *ab = ar->ab;
1389 char buf[100] = {0};
1391 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1393 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1394 if (IS_ERR(ar->debug.debugfs_pdev))
1395 return PTR_ERR(ar->debug.debugfs_pdev);
1397 /* Create a symlink under ieee80211/phy* */
1398 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1399 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1401 ath11k_debugfs_htt_stats_init(ar);
1403 ath11k_debugfs_fw_stats_init(ar);
1405 debugfs_create_file("ext_tx_stats", 0644,
1406 ar->debug.debugfs_pdev, ar,
1407 &fops_extd_tx_stats);
1408 debugfs_create_file("ext_rx_stats", 0644,
1409 ar->debug.debugfs_pdev, ar,
1410 &fops_extd_rx_stats);
1411 debugfs_create_file("pktlog_filter", 0644,
1412 ar->debug.debugfs_pdev, ar,
1413 &fops_pktlog_filter);
1414 debugfs_create_file("fw_dbglog_config", 0600,
1415 ar->debug.debugfs_pdev, ar,
1418 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1419 debugfs_create_file("dfs_simulate_radar", 0200,
1420 ar->debug.debugfs_pdev, ar,
1421 &fops_simulate_radar);
1422 debugfs_create_bool("dfs_block_radar_events", 0200,
1423 ar->debug.debugfs_pdev,
1424 &ar->dfs_block_radar_events);
1427 if (ab->hw_params.dbr_debug_support)
1428 debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
1429 ar, &fops_dbr_debug);
1434 void ath11k_debugfs_unregister(struct ath11k *ar)
1436 struct ath11k_debug_dbr *dbr_debug;
1437 struct ath11k_dbg_dbr_data *dbr_dbg_data;
1440 for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
1441 dbr_debug = ar->debug.dbr_debug[i];
1445 dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1446 kfree(dbr_dbg_data->entries);
1447 debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1449 ar->debug.dbr_debug[i] = NULL;
1453 static ssize_t ath11k_write_twt_add_dialog(struct file *file,
1454 const char __user *ubuf,
1455 size_t count, loff_t *ppos)
1457 struct ath11k_vif *arvif = file->private_data;
1458 struct wmi_twt_add_dialog_params params = { 0 };
1462 if (arvif->ar->twt_enabled == 0) {
1463 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1467 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1473 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
1474 ¶ms.peer_macaddr[0],
1475 ¶ms.peer_macaddr[1],
1476 ¶ms.peer_macaddr[2],
1477 ¶ms.peer_macaddr[3],
1478 ¶ms.peer_macaddr[4],
1479 ¶ms.peer_macaddr[5],
1481 ¶ms.wake_intvl_us,
1482 ¶ms.wake_intvl_mantis,
1483 ¶ms.wake_dura_us,
1484 ¶ms.sp_offset_us,
1487 ¶ms.flag_trigger,
1488 ¶ms.flag_flow_type,
1489 ¶ms.flag_protection);
1493 params.vdev_id = arvif->vdev_id;
1495 ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, ¶ms);
1502 static ssize_t ath11k_write_twt_del_dialog(struct file *file,
1503 const char __user *ubuf,
1504 size_t count, loff_t *ppos)
1506 struct ath11k_vif *arvif = file->private_data;
1507 struct wmi_twt_del_dialog_params params = { 0 };
1511 if (arvif->ar->twt_enabled == 0) {
1512 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1516 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1521 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1522 ¶ms.peer_macaddr[0],
1523 ¶ms.peer_macaddr[1],
1524 ¶ms.peer_macaddr[2],
1525 ¶ms.peer_macaddr[3],
1526 ¶ms.peer_macaddr[4],
1527 ¶ms.peer_macaddr[5],
1532 params.vdev_id = arvif->vdev_id;
1534 ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, ¶ms);
1541 static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
1542 const char __user *ubuf,
1543 size_t count, loff_t *ppos)
1545 struct ath11k_vif *arvif = file->private_data;
1546 struct wmi_twt_pause_dialog_params params = { 0 };
1550 if (arvif->ar->twt_enabled == 0) {
1551 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1555 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1560 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1561 ¶ms.peer_macaddr[0],
1562 ¶ms.peer_macaddr[1],
1563 ¶ms.peer_macaddr[2],
1564 ¶ms.peer_macaddr[3],
1565 ¶ms.peer_macaddr[4],
1566 ¶ms.peer_macaddr[5],
1571 params.vdev_id = arvif->vdev_id;
1573 ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, ¶ms);
1580 static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
1581 const char __user *ubuf,
1582 size_t count, loff_t *ppos)
1584 struct ath11k_vif *arvif = file->private_data;
1585 struct wmi_twt_resume_dialog_params params = { 0 };
1589 if (arvif->ar->twt_enabled == 0) {
1590 ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1594 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1599 ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
1600 ¶ms.peer_macaddr[0],
1601 ¶ms.peer_macaddr[1],
1602 ¶ms.peer_macaddr[2],
1603 ¶ms.peer_macaddr[3],
1604 ¶ms.peer_macaddr[4],
1605 ¶ms.peer_macaddr[5],
1607 ¶ms.sp_offset_us,
1608 ¶ms.next_twt_size);
1612 params.vdev_id = arvif->vdev_id;
1614 ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, ¶ms);
1621 static const struct file_operations ath11k_fops_twt_add_dialog = {
1622 .write = ath11k_write_twt_add_dialog,
1626 static const struct file_operations ath11k_fops_twt_del_dialog = {
1627 .write = ath11k_write_twt_del_dialog,
1631 static const struct file_operations ath11k_fops_twt_pause_dialog = {
1632 .write = ath11k_write_twt_pause_dialog,
1636 static const struct file_operations ath11k_fops_twt_resume_dialog = {
1637 .write = ath11k_write_twt_resume_dialog,
1641 int ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
1643 if (arvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) {
1644 arvif->debugfs_twt = debugfs_create_dir("twt",
1645 arvif->vif->debugfs_dir);
1646 if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) {
1647 ath11k_warn(arvif->ar->ab,
1648 "failed to create directory %p\n",
1649 arvif->debugfs_twt);
1650 arvif->debugfs_twt = NULL;
1654 debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
1655 arvif, &ath11k_fops_twt_add_dialog);
1657 debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
1658 arvif, &ath11k_fops_twt_del_dialog);
1660 debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
1661 arvif, &ath11k_fops_twt_pause_dialog);
1663 debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
1664 arvif, &ath11k_fops_twt_resume_dialog);
1669 void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
1671 debugfs_remove_recursive(arvif->debugfs_twt);
1672 arvif->debugfs_twt = NULL;