Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause-Clear
0002 /*
0003  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/vmalloc.h>
0007 
0008 #include "debugfs.h"
0009 
0010 #include "core.h"
0011 #include "debug.h"
0012 #include "wmi.h"
0013 #include "hal_rx.h"
0014 #include "dp_tx.h"
0015 #include "debugfs_htt_stats.h"
0016 #include "peer.h"
0017 
0018 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
0019     "REO2SW1_RING",
0020     "REO2SW2_RING",
0021     "REO2SW3_RING",
0022     "REO2SW4_RING",
0023     "WBM2REO_LINK_RING",
0024     "REO2TCL_RING",
0025     "REO2FW_RING",
0026     "RELEASE_RING",
0027     "PPE_RELEASE_RING",
0028     "TCL2TQM_RING",
0029     "TQM_RELEASE_RING",
0030     "REO_RELEASE_RING",
0031     "WBM2SW0_RELEASE_RING",
0032     "WBM2SW1_RELEASE_RING",
0033     "WBM2SW2_RELEASE_RING",
0034     "WBM2SW3_RELEASE_RING",
0035     "REO_CMD_RING",
0036     "REO_STATUS_RING",
0037 };
0038 
0039 static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
0040     "FW2RXDMA_BUF_RING",
0041     "FW2RXDMA_STATUS_RING",
0042     "FW2RXDMA_LINK_RING",
0043     "SW2RXDMA_BUF_RING",
0044     "WBM2RXDMA_LINK_RING",
0045     "RXDMA2FW_RING",
0046     "RXDMA2SW_RING",
0047     "RXDMA2RELEASE_RING",
0048     "RXDMA2REO_RING",
0049     "MONITOR_STATUS_RING",
0050     "MONITOR_BUF_RING",
0051     "MONITOR_DESC_RING",
0052     "MONITOR_DEST_RING",
0053 };
0054 
0055 void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
0056                      enum wmi_direct_buffer_module id,
0057                      enum ath11k_dbg_dbr_event event,
0058                      struct hal_srng *srng)
0059 {
0060     struct ath11k_debug_dbr *dbr_debug;
0061     struct ath11k_dbg_dbr_data *dbr_data;
0062     struct ath11k_dbg_dbr_entry *entry;
0063 
0064     if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
0065         return;
0066 
0067     dbr_debug = ar->debug.dbr_debug[id];
0068     if (!dbr_debug)
0069         return;
0070 
0071     if (!dbr_debug->dbr_debug_enabled)
0072         return;
0073 
0074     dbr_data = &dbr_debug->dbr_dbg_data;
0075 
0076     spin_lock_bh(&dbr_data->lock);
0077 
0078     if (dbr_data->entries) {
0079         entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
0080         entry->hp = srng->u.src_ring.hp;
0081         entry->tp = *srng->u.src_ring.tp_addr;
0082         entry->timestamp = jiffies;
0083         entry->event = event;
0084 
0085         dbr_data->dbr_debug_idx++;
0086         if (dbr_data->dbr_debug_idx ==
0087             dbr_data->num_ring_debug_entries)
0088             dbr_data->dbr_debug_idx = 0;
0089     }
0090 
0091     spin_unlock_bh(&dbr_data->lock);
0092 }
0093 
0094 static void ath11k_fw_stats_pdevs_free(struct list_head *head)
0095 {
0096     struct ath11k_fw_stats_pdev *i, *tmp;
0097 
0098     list_for_each_entry_safe(i, tmp, head, list) {
0099         list_del(&i->list);
0100         kfree(i);
0101     }
0102 }
0103 
0104 static void ath11k_fw_stats_vdevs_free(struct list_head *head)
0105 {
0106     struct ath11k_fw_stats_vdev *i, *tmp;
0107 
0108     list_for_each_entry_safe(i, tmp, head, list) {
0109         list_del(&i->list);
0110         kfree(i);
0111     }
0112 }
0113 
0114 static void ath11k_fw_stats_bcn_free(struct list_head *head)
0115 {
0116     struct ath11k_fw_stats_bcn *i, *tmp;
0117 
0118     list_for_each_entry_safe(i, tmp, head, list) {
0119         list_del(&i->list);
0120         kfree(i);
0121     }
0122 }
0123 
0124 static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
0125 {
0126     spin_lock_bh(&ar->data_lock);
0127     ar->debug.fw_stats_done = false;
0128     ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
0129     ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
0130     spin_unlock_bh(&ar->data_lock);
0131 }
0132 
0133 void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
0134 {
0135     struct ath11k_fw_stats stats = {};
0136     struct ath11k *ar;
0137     struct ath11k_pdev *pdev;
0138     bool is_end;
0139     static unsigned int num_vdev, num_bcn;
0140     size_t total_vdevs_started = 0;
0141     int i, ret;
0142 
0143     INIT_LIST_HEAD(&stats.pdevs);
0144     INIT_LIST_HEAD(&stats.vdevs);
0145     INIT_LIST_HEAD(&stats.bcn);
0146 
0147     ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
0148     if (ret) {
0149         ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
0150         goto free;
0151     }
0152 
0153     rcu_read_lock();
0154     ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
0155     if (!ar) {
0156         rcu_read_unlock();
0157         ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
0158                 stats.pdev_id, ret);
0159         goto free;
0160     }
0161 
0162     spin_lock_bh(&ar->data_lock);
0163 
0164     if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
0165         list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
0166         ar->debug.fw_stats_done = true;
0167         goto complete;
0168     }
0169 
0170     if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
0171         ar->debug.fw_stats_done = true;
0172         goto complete;
0173     }
0174 
0175     if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
0176         if (list_empty(&stats.vdevs)) {
0177             ath11k_warn(ab, "empty vdev stats");
0178             goto complete;
0179         }
0180         /* FW sends all the active VDEV stats irrespective of PDEV,
0181          * hence limit until the count of all VDEVs started
0182          */
0183         for (i = 0; i < ab->num_radios; i++) {
0184             pdev = rcu_dereference(ab->pdevs_active[i]);
0185             if (pdev && pdev->ar)
0186                 total_vdevs_started += ar->num_started_vdevs;
0187         }
0188 
0189         is_end = ((++num_vdev) == total_vdevs_started);
0190 
0191         list_splice_tail_init(&stats.vdevs,
0192                       &ar->debug.fw_stats.vdevs);
0193 
0194         if (is_end) {
0195             ar->debug.fw_stats_done = true;
0196             num_vdev = 0;
0197         }
0198         goto complete;
0199     }
0200 
0201     if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
0202         if (list_empty(&stats.bcn)) {
0203             ath11k_warn(ab, "empty bcn stats");
0204             goto complete;
0205         }
0206         /* Mark end until we reached the count of all started VDEVs
0207          * within the PDEV
0208          */
0209         is_end = ((++num_bcn) == ar->num_started_vdevs);
0210 
0211         list_splice_tail_init(&stats.bcn,
0212                       &ar->debug.fw_stats.bcn);
0213 
0214         if (is_end) {
0215             ar->debug.fw_stats_done = true;
0216             num_bcn = 0;
0217         }
0218     }
0219 complete:
0220     complete(&ar->debug.fw_stats_complete);
0221     rcu_read_unlock();
0222     spin_unlock_bh(&ar->data_lock);
0223 
0224 free:
0225     ath11k_fw_stats_pdevs_free(&stats.pdevs);
0226     ath11k_fw_stats_vdevs_free(&stats.vdevs);
0227     ath11k_fw_stats_bcn_free(&stats.bcn);
0228 }
0229 
0230 static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
0231                        struct stats_request_params *req_param)
0232 {
0233     struct ath11k_base *ab = ar->ab;
0234     unsigned long timeout, time_left;
0235     int ret;
0236 
0237     lockdep_assert_held(&ar->conf_mutex);
0238 
0239     /* FW stats can get split when exceeding the stats data buffer limit.
0240      * In that case, since there is no end marking for the back-to-back
0241      * received 'update stats' event, we keep a 3 seconds timeout in case,
0242      * fw_stats_done is not marked yet
0243      */
0244     timeout = jiffies + msecs_to_jiffies(3 * 1000);
0245 
0246     ath11k_debugfs_fw_stats_reset(ar);
0247 
0248     reinit_completion(&ar->debug.fw_stats_complete);
0249 
0250     ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
0251 
0252     if (ret) {
0253         ath11k_warn(ab, "could not request fw stats (%d)\n",
0254                 ret);
0255         return ret;
0256     }
0257 
0258     time_left =
0259     wait_for_completion_timeout(&ar->debug.fw_stats_complete,
0260                     1 * HZ);
0261     if (!time_left)
0262         return -ETIMEDOUT;
0263 
0264     for (;;) {
0265         if (time_after(jiffies, timeout))
0266             break;
0267 
0268         spin_lock_bh(&ar->data_lock);
0269         if (ar->debug.fw_stats_done) {
0270             spin_unlock_bh(&ar->data_lock);
0271             break;
0272         }
0273         spin_unlock_bh(&ar->data_lock);
0274     }
0275     return 0;
0276 }
0277 
0278 int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
0279                 u32 vdev_id, u32 stats_id)
0280 {
0281     struct ath11k_base *ab = ar->ab;
0282     struct stats_request_params req_param;
0283     int ret;
0284 
0285     mutex_lock(&ar->conf_mutex);
0286 
0287     if (ar->state != ATH11K_STATE_ON) {
0288         ret = -ENETDOWN;
0289         goto err_unlock;
0290     }
0291 
0292     req_param.pdev_id = pdev_id;
0293     req_param.vdev_id = vdev_id;
0294     req_param.stats_id = stats_id;
0295 
0296     ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
0297     if (ret)
0298         ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
0299 
0300     ath11k_dbg(ab, ATH11K_DBG_WMI,
0301            "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
0302            pdev_id, vdev_id, stats_id);
0303 
0304 err_unlock:
0305     mutex_unlock(&ar->conf_mutex);
0306 
0307     return ret;
0308 }
0309 
0310 static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
0311 {
0312     struct ath11k *ar = inode->i_private;
0313     struct ath11k_base *ab = ar->ab;
0314     struct stats_request_params req_param;
0315     void *buf = NULL;
0316     int ret;
0317 
0318     mutex_lock(&ar->conf_mutex);
0319 
0320     if (ar->state != ATH11K_STATE_ON) {
0321         ret = -ENETDOWN;
0322         goto err_unlock;
0323     }
0324 
0325     buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
0326     if (!buf) {
0327         ret = -ENOMEM;
0328         goto err_unlock;
0329     }
0330 
0331     req_param.pdev_id = ar->pdev->pdev_id;
0332     req_param.vdev_id = 0;
0333     req_param.stats_id = WMI_REQUEST_PDEV_STAT;
0334 
0335     ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
0336     if (ret) {
0337         ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
0338         goto err_free;
0339     }
0340 
0341     ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
0342                  buf);
0343 
0344     file->private_data = buf;
0345 
0346     mutex_unlock(&ar->conf_mutex);
0347     return 0;
0348 
0349 err_free:
0350     vfree(buf);
0351 
0352 err_unlock:
0353     mutex_unlock(&ar->conf_mutex);
0354     return ret;
0355 }
0356 
0357 static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
0358 {
0359     vfree(file->private_data);
0360 
0361     return 0;
0362 }
0363 
0364 static ssize_t ath11k_read_pdev_stats(struct file *file,
0365                       char __user *user_buf,
0366                       size_t count, loff_t *ppos)
0367 {
0368     const char *buf = file->private_data;
0369     size_t len = strlen(buf);
0370 
0371     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0372 }
0373 
0374 static const struct file_operations fops_pdev_stats = {
0375     .open = ath11k_open_pdev_stats,
0376     .release = ath11k_release_pdev_stats,
0377     .read = ath11k_read_pdev_stats,
0378     .owner = THIS_MODULE,
0379     .llseek = default_llseek,
0380 };
0381 
0382 static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
0383 {
0384     struct ath11k *ar = inode->i_private;
0385     struct stats_request_params req_param;
0386     void *buf = NULL;
0387     int ret;
0388 
0389     mutex_lock(&ar->conf_mutex);
0390 
0391     if (ar->state != ATH11K_STATE_ON) {
0392         ret = -ENETDOWN;
0393         goto err_unlock;
0394     }
0395 
0396     buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
0397     if (!buf) {
0398         ret = -ENOMEM;
0399         goto err_unlock;
0400     }
0401 
0402     req_param.pdev_id = ar->pdev->pdev_id;
0403     /* VDEV stats is always sent for all active VDEVs from FW */
0404     req_param.vdev_id = 0;
0405     req_param.stats_id = WMI_REQUEST_VDEV_STAT;
0406 
0407     ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
0408     if (ret) {
0409         ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
0410         goto err_free;
0411     }
0412 
0413     ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
0414                  buf);
0415 
0416     file->private_data = buf;
0417 
0418     mutex_unlock(&ar->conf_mutex);
0419     return 0;
0420 
0421 err_free:
0422     vfree(buf);
0423 
0424 err_unlock:
0425     mutex_unlock(&ar->conf_mutex);
0426     return ret;
0427 }
0428 
0429 static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
0430 {
0431     vfree(file->private_data);
0432 
0433     return 0;
0434 }
0435 
0436 static ssize_t ath11k_read_vdev_stats(struct file *file,
0437                       char __user *user_buf,
0438                       size_t count, loff_t *ppos)
0439 {
0440     const char *buf = file->private_data;
0441     size_t len = strlen(buf);
0442 
0443     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0444 }
0445 
0446 static const struct file_operations fops_vdev_stats = {
0447     .open = ath11k_open_vdev_stats,
0448     .release = ath11k_release_vdev_stats,
0449     .read = ath11k_read_vdev_stats,
0450     .owner = THIS_MODULE,
0451     .llseek = default_llseek,
0452 };
0453 
0454 static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
0455 {
0456     struct ath11k *ar = inode->i_private;
0457     struct ath11k_vif *arvif;
0458     struct stats_request_params req_param;
0459     void *buf = NULL;
0460     int ret;
0461 
0462     mutex_lock(&ar->conf_mutex);
0463 
0464     if (ar->state != ATH11K_STATE_ON) {
0465         ret = -ENETDOWN;
0466         goto err_unlock;
0467     }
0468 
0469     buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
0470     if (!buf) {
0471         ret = -ENOMEM;
0472         goto err_unlock;
0473     }
0474 
0475     req_param.stats_id = WMI_REQUEST_BCN_STAT;
0476     req_param.pdev_id = ar->pdev->pdev_id;
0477 
0478     /* loop all active VDEVs for bcn stats */
0479     list_for_each_entry(arvif, &ar->arvifs, list) {
0480         if (!arvif->is_up)
0481             continue;
0482 
0483         req_param.vdev_id = arvif->vdev_id;
0484         ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
0485         if (ret) {
0486             ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
0487             goto err_free;
0488         }
0489     }
0490 
0491     ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
0492                  buf);
0493 
0494     /* since beacon stats request is looped for all active VDEVs, saved fw
0495      * stats is not freed for each request until done for all active VDEVs
0496      */
0497     spin_lock_bh(&ar->data_lock);
0498     ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
0499     spin_unlock_bh(&ar->data_lock);
0500 
0501     file->private_data = buf;
0502 
0503     mutex_unlock(&ar->conf_mutex);
0504     return 0;
0505 
0506 err_free:
0507     vfree(buf);
0508 
0509 err_unlock:
0510     mutex_unlock(&ar->conf_mutex);
0511     return ret;
0512 }
0513 
0514 static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
0515 {
0516     vfree(file->private_data);
0517 
0518     return 0;
0519 }
0520 
0521 static ssize_t ath11k_read_bcn_stats(struct file *file,
0522                      char __user *user_buf,
0523                      size_t count, loff_t *ppos)
0524 {
0525     const char *buf = file->private_data;
0526     size_t len = strlen(buf);
0527 
0528     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0529 }
0530 
0531 static const struct file_operations fops_bcn_stats = {
0532     .open = ath11k_open_bcn_stats,
0533     .release = ath11k_release_bcn_stats,
0534     .read = ath11k_read_bcn_stats,
0535     .owner = THIS_MODULE,
0536     .llseek = default_llseek,
0537 };
0538 
0539 static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
0540                          char __user *user_buf,
0541                          size_t count, loff_t *ppos)
0542 {
0543     const char buf[] =
0544         "To simulate firmware crash write one of the keywords to this file:\n"
0545         "`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
0546         "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
0547 
0548     return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
0549 }
0550 
0551 /* Simulate firmware crash:
0552  * 'soft': Call wmi command causing firmware hang. This firmware hang is
0553  * recoverable by warm firmware reset.
0554  * 'hard': Force firmware crash by setting any vdev parameter for not allowed
0555  * vdev id. This is hard firmware crash because it is recoverable only by cold
0556  * firmware reset.
0557  */
0558 static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
0559                           const char __user *user_buf,
0560                           size_t count, loff_t *ppos)
0561 {
0562     struct ath11k_base *ab = file->private_data;
0563     struct ath11k_pdev *pdev;
0564     struct ath11k *ar = ab->pdevs[0].ar;
0565     char buf[32] = {0};
0566     ssize_t rc;
0567     int i, ret, radioup = 0;
0568 
0569     for (i = 0; i < ab->num_radios; i++) {
0570         pdev = &ab->pdevs[i];
0571         ar = pdev->ar;
0572         if (ar && ar->state == ATH11K_STATE_ON) {
0573             radioup = 1;
0574             break;
0575         }
0576     }
0577     /* filter partial writes and invalid commands */
0578     if (*ppos != 0 || count >= sizeof(buf) || count == 0)
0579         return -EINVAL;
0580 
0581     rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
0582     if (rc < 0)
0583         return rc;
0584 
0585     /* drop the possible '\n' from the end */
0586     if (buf[*ppos - 1] == '\n')
0587         buf[*ppos - 1] = '\0';
0588 
0589     if (radioup == 0) {
0590         ret = -ENETDOWN;
0591         goto exit;
0592     }
0593 
0594     if (!strcmp(buf, "assert")) {
0595         ath11k_info(ab, "simulating firmware assert crash\n");
0596         ret = ath11k_wmi_force_fw_hang_cmd(ar,
0597                            ATH11K_WMI_FW_HANG_ASSERT_TYPE,
0598                            ATH11K_WMI_FW_HANG_DELAY);
0599     } else if (!strcmp(buf, "hw-restart")) {
0600         ath11k_info(ab, "user requested hw restart\n");
0601         queue_work(ab->workqueue_aux, &ab->reset_work);
0602         ret = 0;
0603     } else {
0604         ret = -EINVAL;
0605         goto exit;
0606     }
0607 
0608     if (ret) {
0609         ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
0610         goto exit;
0611     }
0612 
0613     ret = count;
0614 
0615 exit:
0616     return ret;
0617 }
0618 
0619 static const struct file_operations fops_simulate_fw_crash = {
0620     .read = ath11k_read_simulate_fw_crash,
0621     .write = ath11k_write_simulate_fw_crash,
0622     .open = simple_open,
0623     .owner = THIS_MODULE,
0624     .llseek = default_llseek,
0625 };
0626 
0627 static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
0628                          const char __user *ubuf,
0629                          size_t count, loff_t *ppos)
0630 {
0631     struct ath11k *ar = file->private_data;
0632     u32 filter;
0633     int ret;
0634 
0635     if (kstrtouint_from_user(ubuf, count, 0, &filter))
0636         return -EINVAL;
0637 
0638     mutex_lock(&ar->conf_mutex);
0639 
0640     if (ar->state != ATH11K_STATE_ON) {
0641         ret = -ENETDOWN;
0642         goto out;
0643     }
0644 
0645     if (filter == ar->debug.extd_tx_stats) {
0646         ret = count;
0647         goto out;
0648     }
0649 
0650     ar->debug.extd_tx_stats = filter;
0651     ret = count;
0652 
0653 out:
0654     mutex_unlock(&ar->conf_mutex);
0655     return ret;
0656 }
0657 
0658 static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
0659                         char __user *ubuf,
0660                         size_t count, loff_t *ppos)
0661 
0662 {
0663     char buf[32] = {0};
0664     struct ath11k *ar = file->private_data;
0665     int len = 0;
0666 
0667     mutex_lock(&ar->conf_mutex);
0668     len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
0669             ar->debug.extd_tx_stats);
0670     mutex_unlock(&ar->conf_mutex);
0671 
0672     return simple_read_from_buffer(ubuf, count, ppos, buf, len);
0673 }
0674 
0675 static const struct file_operations fops_extd_tx_stats = {
0676     .read = ath11k_read_enable_extd_tx_stats,
0677     .write = ath11k_write_enable_extd_tx_stats,
0678     .open = simple_open
0679 };
0680 
0681 static ssize_t ath11k_write_extd_rx_stats(struct file *file,
0682                       const char __user *ubuf,
0683                       size_t count, loff_t *ppos)
0684 {
0685     struct ath11k *ar = file->private_data;
0686     struct ath11k_base *ab = ar->ab;
0687     struct htt_rx_ring_tlv_filter tlv_filter = {0};
0688     u32 enable, rx_filter = 0, ring_id;
0689     int i;
0690     int ret;
0691 
0692     if (kstrtouint_from_user(ubuf, count, 0, &enable))
0693         return -EINVAL;
0694 
0695     mutex_lock(&ar->conf_mutex);
0696 
0697     if (ar->state != ATH11K_STATE_ON) {
0698         ret = -ENETDOWN;
0699         goto exit;
0700     }
0701 
0702     if (enable > 1) {
0703         ret = -EINVAL;
0704         goto exit;
0705     }
0706 
0707     if (enable == ar->debug.extd_rx_stats) {
0708         ret = count;
0709         goto exit;
0710     }
0711 
0712     if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
0713         ar->debug.extd_rx_stats = enable;
0714         ret = count;
0715         goto exit;
0716     }
0717 
0718     if (enable) {
0719         rx_filter =  HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
0720         rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
0721         rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
0722         rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
0723         rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
0724         rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
0725 
0726         tlv_filter.rx_filter = rx_filter;
0727         tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
0728         tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
0729         tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
0730         tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
0731             HTT_RX_FP_DATA_FILTER_FLASG3;
0732     } else {
0733         tlv_filter = ath11k_mac_mon_status_filter_default;
0734     }
0735 
0736     ar->debug.rx_filter = tlv_filter.rx_filter;
0737 
0738     for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
0739         ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
0740         ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
0741                                HAL_RXDMA_MONITOR_STATUS,
0742                                DP_RX_BUFFER_SIZE, &tlv_filter);
0743 
0744         if (ret) {
0745             ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
0746             goto exit;
0747         }
0748     }
0749 
0750     ar->debug.extd_rx_stats = enable;
0751     ret = count;
0752 exit:
0753     mutex_unlock(&ar->conf_mutex);
0754     return ret;
0755 }
0756 
0757 static ssize_t ath11k_read_extd_rx_stats(struct file *file,
0758                      char __user *ubuf,
0759                      size_t count, loff_t *ppos)
0760 {
0761     struct ath11k *ar = file->private_data;
0762     char buf[32];
0763     int len = 0;
0764 
0765     mutex_lock(&ar->conf_mutex);
0766     len = scnprintf(buf, sizeof(buf) - len, "%d\n",
0767             ar->debug.extd_rx_stats);
0768     mutex_unlock(&ar->conf_mutex);
0769 
0770     return simple_read_from_buffer(ubuf, count, ppos, buf, len);
0771 }
0772 
0773 static const struct file_operations fops_extd_rx_stats = {
0774     .read = ath11k_read_extd_rx_stats,
0775     .write = ath11k_write_extd_rx_stats,
0776     .open = simple_open,
0777 };
0778 
0779 static int ath11k_fill_bp_stats(struct ath11k_base *ab,
0780                 struct ath11k_bp_stats *bp_stats,
0781                 char *buf, int len, int size)
0782 {
0783     lockdep_assert_held(&ab->base_lock);
0784 
0785     len += scnprintf(buf + len, size - len, "count: %u\n",
0786              bp_stats->count);
0787     len += scnprintf(buf + len, size - len, "hp: %u\n",
0788              bp_stats->hp);
0789     len += scnprintf(buf + len, size - len, "tp: %u\n",
0790              bp_stats->tp);
0791     len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
0792              jiffies_to_msecs(jiffies - bp_stats->jiffies));
0793     return len;
0794 }
0795 
0796 static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
0797                              char *buf, int size)
0798 {
0799     struct ath11k_bp_stats *bp_stats;
0800     bool stats_rxd = false;
0801     u8 i, pdev_idx;
0802     int len = 0;
0803 
0804     len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
0805     len += scnprintf(buf + len, size - len, "==================\n");
0806 
0807     spin_lock_bh(&ab->base_lock);
0808     for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
0809         bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
0810 
0811         if (!bp_stats->count)
0812             continue;
0813 
0814         len += scnprintf(buf + len, size - len, "Ring: %s\n",
0815                  htt_bp_umac_ring[i]);
0816         len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
0817         stats_rxd = true;
0818     }
0819 
0820     for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
0821         for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
0822             bp_stats =
0823                 &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
0824 
0825             if (!bp_stats->count)
0826                 continue;
0827 
0828             len += scnprintf(buf + len, size - len, "Ring: %s\n",
0829                      htt_bp_lmac_ring[i]);
0830             len += scnprintf(buf + len, size - len, "pdev: %d\n",
0831                      pdev_idx);
0832             len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
0833             stats_rxd = true;
0834         }
0835     }
0836     spin_unlock_bh(&ab->base_lock);
0837 
0838     if (!stats_rxd)
0839         len += scnprintf(buf + len, size - len,
0840                  "No Ring Backpressure stats received\n\n");
0841 
0842     return len;
0843 }
0844 
0845 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
0846                         char __user *user_buf,
0847                         size_t count, loff_t *ppos)
0848 {
0849     struct ath11k_base *ab = file->private_data;
0850     struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
0851     int len = 0, i, retval;
0852     const int size = 4096;
0853     static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
0854             "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
0855             "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
0856             "AMSDU parse", "SA timeout", "DA timeout",
0857             "Flow timeout", "Flush req"};
0858     static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
0859             "Desc addr zero", "Desc inval", "AMPDU in non BA",
0860             "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
0861             "Frame OOR", "BAR OOR", "No BA session",
0862             "Frame SN equal SSN", "PN check fail", "2k err",
0863             "PN err", "Desc blocked"};
0864 
0865     char *buf;
0866 
0867     buf = kzalloc(size, GFP_KERNEL);
0868     if (!buf)
0869         return -ENOMEM;
0870 
0871     len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
0872     len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
0873              soc_stats->err_ring_pkts);
0874     len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
0875              soc_stats->invalid_rbm);
0876     len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
0877     for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
0878         len += scnprintf(buf + len, size - len, "%s: %u\n",
0879                  rxdma_err[i], soc_stats->rxdma_error[i]);
0880 
0881     len += scnprintf(buf + len, size - len, "\nREO errors:\n");
0882     for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
0883         len += scnprintf(buf + len, size - len, "%s: %u\n",
0884                  reo_err[i], soc_stats->reo_error[i]);
0885 
0886     len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
0887     len += scnprintf(buf + len, size - len,
0888              "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
0889              soc_stats->hal_reo_error[0],
0890              soc_stats->hal_reo_error[1],
0891              soc_stats->hal_reo_error[2],
0892              soc_stats->hal_reo_error[3]);
0893 
0894     len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
0895     len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
0896 
0897     for (i = 0; i < ab->hw_params.max_tx_ring; i++)
0898         len += scnprintf(buf + len, size - len, "ring%d: %u\n",
0899                  i, soc_stats->tx_err.desc_na[i]);
0900 
0901     len += scnprintf(buf + len, size - len,
0902              "\nMisc Transmit Failures: %d\n",
0903              atomic_read(&soc_stats->tx_err.misc_fail));
0904 
0905     len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
0906 
0907     if (len > size)
0908         len = size;
0909     retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0910     kfree(buf);
0911 
0912     return retval;
0913 }
0914 
0915 static const struct file_operations fops_soc_dp_stats = {
0916     .read = ath11k_debugfs_dump_soc_dp_stats,
0917     .open = simple_open,
0918     .owner = THIS_MODULE,
0919     .llseek = default_llseek,
0920 };
0921 
0922 static ssize_t ath11k_write_fw_dbglog(struct file *file,
0923                       const char __user *user_buf,
0924                       size_t count, loff_t *ppos)
0925 {
0926     struct ath11k *ar = file->private_data;
0927     char buf[128] = {0};
0928     struct ath11k_fw_dbglog dbglog;
0929     unsigned int param, mod_id_index, is_end;
0930     u64 value;
0931     int ret, num;
0932 
0933     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0934                      user_buf, count);
0935     if (ret <= 0)
0936         return ret;
0937 
0938     num = sscanf(buf, "%u %llx %u %u", &param, &value, &mod_id_index, &is_end);
0939 
0940     if (num < 2)
0941         return -EINVAL;
0942 
0943     mutex_lock(&ar->conf_mutex);
0944     if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
0945         param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
0946         if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
0947             ret = -EINVAL;
0948             goto out;
0949         }
0950         ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
0951         if (!is_end) {
0952             ret = count;
0953             goto out;
0954         }
0955     } else {
0956         if (num != 2) {
0957             ret = -EINVAL;
0958             goto out;
0959         }
0960     }
0961 
0962     dbglog.param = param;
0963     dbglog.value = lower_32_bits(value);
0964     ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
0965     if (ret) {
0966         ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
0967                 ret);
0968         goto out;
0969     }
0970 
0971     ret = count;
0972 
0973 out:
0974     mutex_unlock(&ar->conf_mutex);
0975     return ret;
0976 }
0977 
0978 static const struct file_operations fops_fw_dbglog = {
0979     .write = ath11k_write_fw_dbglog,
0980     .open = simple_open,
0981     .owner = THIS_MODULE,
0982     .llseek = default_llseek,
0983 };
0984 
0985 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
0986 {
0987     if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
0988         return 0;
0989 
0990     ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
0991     if (IS_ERR(ab->debugfs_soc))
0992         return PTR_ERR(ab->debugfs_soc);
0993 
0994     debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
0995                 &fops_simulate_fw_crash);
0996 
0997     debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
0998                 &fops_soc_dp_stats);
0999 
1000     return 0;
1001 }
1002 
1003 void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
1004 {
1005     debugfs_remove_recursive(ab->debugfs_soc);
1006     ab->debugfs_soc = NULL;
1007 }
1008 
1009 int ath11k_debugfs_soc_create(struct ath11k_base *ab)
1010 {
1011     ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
1012 
1013     return PTR_ERR_OR_ZERO(ab->debugfs_ath11k);
1014 }
1015 
1016 void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
1017 {
1018     debugfs_remove_recursive(ab->debugfs_ath11k);
1019     ab->debugfs_ath11k = NULL;
1020 }
1021 EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
1022 
1023 void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
1024 {
1025     struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1026                             ar->debug.debugfs_pdev);
1027 
1028     ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
1029 
1030     /* all stats debugfs files created are under "fw_stats" directory
1031      * created per PDEV
1032      */
1033     debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1034                 &fops_pdev_stats);
1035     debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1036                 &fops_vdev_stats);
1037     debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1038                 &fops_bcn_stats);
1039 
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);
1043 
1044     init_completion(&ar->debug.fw_stats_complete);
1045 }
1046 
1047 static ssize_t ath11k_write_pktlog_filter(struct file *file,
1048                       const char __user *ubuf,
1049                       size_t count, loff_t *ppos)
1050 {
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;
1055     u8 buf[128] = {0};
1056     int i, ret, rx_buf_sz = 0;
1057     ssize_t rc;
1058 
1059     mutex_lock(&ar->conf_mutex);
1060     if (ar->state != ATH11K_STATE_ON) {
1061         ret = -ENETDOWN;
1062         goto out;
1063     }
1064 
1065     rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1066     if (rc < 0) {
1067         ret = rc;
1068         goto out;
1069     }
1070     buf[rc] = '\0';
1071 
1072     ret = sscanf(buf, "0x%x %u", &filter, &mode);
1073     if (ret != 2) {
1074         ret = -EINVAL;
1075         goto out;
1076     }
1077 
1078     if (filter) {
1079         ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
1080         if (ret) {
1081             ath11k_warn(ar->ab,
1082                     "failed to enable pktlog filter %x: %d\n",
1083                     ar->debug.pktlog_filter, ret);
1084             goto out;
1085         }
1086     } else {
1087         ret = ath11k_wmi_pdev_pktlog_disable(ar);
1088         if (ret) {
1089             ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
1090             goto out;
1091         }
1092     }
1093 
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);
1100         if (ret) {
1101             ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1102             goto out;
1103         }
1104     }
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)
1112 
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);
1124         if (ret) {
1125             ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1126             goto out;
1127         }
1128 
1129         rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1130         rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
1131     } else {
1132         rx_buf_sz = DP_RX_BUFFER_SIZE;
1133         tlv_filter = ath11k_mac_mon_status_filter_default;
1134         rx_filter = tlv_filter.rx_filter;
1135 
1136         ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1137                               HTT_PPDU_STATS_TAG_DEFAULT);
1138         if (ret) {
1139             ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1140                    ret);
1141             goto out;
1142         }
1143     }
1144 
1145     tlv_filter.rx_filter = rx_filter;
1146     if (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;
1152     }
1153 
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,
1157                                ar->dp.mac_id + i,
1158                                HAL_RXDMA_MONITOR_STATUS,
1159                                rx_buf_sz, &tlv_filter);
1160 
1161         if (ret) {
1162             ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1163             goto out;
1164         }
1165     }
1166 
1167     ath11k_info(ab, "pktlog mode %s\n",
1168             ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1169 
1170     ar->debug.pktlog_filter = filter;
1171     ar->debug.pktlog_mode = mode;
1172     ret = count;
1173 
1174 out:
1175     mutex_unlock(&ar->conf_mutex);
1176     return ret;
1177 }
1178 
1179 static ssize_t ath11k_read_pktlog_filter(struct file *file,
1180                      char __user *ubuf,
1181                      size_t count, loff_t *ppos)
1182 
1183 {
1184     char buf[32] = {0};
1185     struct ath11k *ar = file->private_data;
1186     int len = 0;
1187 
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);
1193 
1194     return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1195 }
1196 
1197 static const struct file_operations fops_pktlog_filter = {
1198     .read = ath11k_read_pktlog_filter,
1199     .write = ath11k_write_pktlog_filter,
1200     .open = simple_open
1201 };
1202 
1203 static ssize_t ath11k_write_simulate_radar(struct file *file,
1204                        const char __user *user_buf,
1205                        size_t count, loff_t *ppos)
1206 {
1207     struct ath11k *ar = file->private_data;
1208     int ret;
1209 
1210     ret = ath11k_wmi_simulate_radar(ar);
1211     if (ret)
1212         return ret;
1213 
1214     return count;
1215 }
1216 
1217 static const struct file_operations fops_simulate_radar = {
1218     .write = ath11k_write_simulate_radar,
1219     .open = simple_open
1220 };
1221 
1222 static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
1223                          char __user *user_buf,
1224                          size_t count, loff_t *ppos)
1225 {
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;
1229     char *buf;
1230     int i, ret;
1231     int len = 0;
1232 
1233     buf = kzalloc(size, GFP_KERNEL);
1234     if (!buf)
1235         return -ENOMEM;
1236 
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");
1243 
1244     spin_lock_bh(&dbr_dbg_data->lock);
1245 
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]);
1253     }
1254 
1255     spin_unlock_bh(&dbr_dbg_data->lock);
1256 
1257     ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1258     kfree(buf);
1259 
1260     return ret;
1261 }
1262 
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,
1268 };
1269 
1270 static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
1271 {
1272     struct ath11k_debug_dbr *dbr_debug;
1273     struct ath11k_dbg_dbr_data *dbr_dbg_data;
1274 
1275     if (!ar->debug.dbr_debug[dbr_id])
1276         return;
1277 
1278     dbr_debug = ar->debug.dbr_debug[dbr_id];
1279     dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1280 
1281     debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1282     kfree(dbr_dbg_data->entries);
1283     kfree(dbr_debug);
1284     ar->debug.dbr_debug[dbr_id] = NULL;
1285 }
1286 
1287 static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
1288 {
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"};
1292 
1293     if (ar->debug.dbr_debug[dbr_id])
1294         return 0;
1295 
1296     ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
1297                           GFP_KERNEL);
1298 
1299     if (!ar->debug.dbr_debug[dbr_id])
1300         return -ENOMEM;
1301 
1302     dbr_debug = ar->debug.dbr_debug[dbr_id];
1303     dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1304 
1305     if (dbr_debug->dbr_debugfs)
1306         return 0;
1307 
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);
1313         return -ENOMEM;
1314     }
1315 
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),
1321                     GFP_KERNEL);
1322     if (!dbr_dbg_data->entries)
1323         return -ENOMEM;
1324 
1325     spin_lock_init(&dbr_dbg_data->lock);
1326 
1327     debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
1328                 dbr_dbg_data, &fops_debug_dump_dbr_entries);
1329 
1330     return 0;
1331 }
1332 
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)
1336 {
1337     struct ath11k *ar = file->private_data;
1338     char buf[32] = {0};
1339     u32 dbr_id, enable;
1340     int ret;
1341 
1342     mutex_lock(&ar->conf_mutex);
1343 
1344     if (ar->state != ATH11K_STATE_ON) {
1345         ret = -ENETDOWN;
1346         goto out;
1347     }
1348 
1349     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1350     if (ret < 0)
1351         goto out;
1352 
1353     buf[ret] = '\0';
1354     ret = sscanf(buf, "%u %u", &dbr_id, &enable);
1355     if (ret != 2 || dbr_id > 1 || enable > 1) {
1356         ret = -EINVAL;
1357         ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
1358         goto out;
1359     }
1360 
1361     if (enable) {
1362         ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
1363         if (ret) {
1364             ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
1365                     ret);
1366             goto out;
1367         }
1368     } else {
1369         ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
1370     }
1371 
1372     ret = count;
1373 out:
1374     mutex_unlock(&ar->conf_mutex);
1375     return ret;
1376 }
1377 
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,
1383 };
1384 
1385 int ath11k_debugfs_register(struct ath11k *ar)
1386 {
1387     struct ath11k_base *ab = ar->ab;
1388     char pdev_name[5];
1389     char buf[100] = {0};
1390 
1391     snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1392 
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);
1396 
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);
1400 
1401     ath11k_debugfs_htt_stats_init(ar);
1402 
1403     ath11k_debugfs_fw_stats_init(ar);
1404 
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,
1416                 &fops_fw_dbglog);
1417 
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);
1425     }
1426 
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);
1430 
1431     return 0;
1432 }
1433 
1434 void ath11k_debugfs_unregister(struct ath11k *ar)
1435 {
1436     struct ath11k_debug_dbr *dbr_debug;
1437     struct ath11k_dbg_dbr_data *dbr_dbg_data;
1438     int i;
1439 
1440     for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
1441         dbr_debug = ar->debug.dbr_debug[i];
1442         if (!dbr_debug)
1443             continue;
1444 
1445         dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1446         kfree(dbr_dbg_data->entries);
1447         debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1448         kfree(dbr_debug);
1449         ar->debug.dbr_debug[i] = NULL;
1450     }
1451 }
1452 
1453 static ssize_t ath11k_write_twt_add_dialog(struct file *file,
1454                        const char __user *ubuf,
1455                        size_t count, loff_t *ppos)
1456 {
1457     struct ath11k_vif *arvif = file->private_data;
1458     struct wmi_twt_add_dialog_params params = { 0 };
1459     u8 buf[128] = {0};
1460     int ret;
1461 
1462     if (arvif->ar->twt_enabled == 0) {
1463         ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1464         return -EOPNOTSUPP;
1465     }
1466 
1467     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1468     if (ret < 0)
1469         return ret;
1470 
1471     buf[ret] = '\0';
1472     ret = sscanf(buf,
1473              "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
1474              &params.peer_macaddr[0],
1475              &params.peer_macaddr[1],
1476              &params.peer_macaddr[2],
1477              &params.peer_macaddr[3],
1478              &params.peer_macaddr[4],
1479              &params.peer_macaddr[5],
1480              &params.dialog_id,
1481              &params.wake_intvl_us,
1482              &params.wake_intvl_mantis,
1483              &params.wake_dura_us,
1484              &params.sp_offset_us,
1485              &params.twt_cmd,
1486              &params.flag_bcast,
1487              &params.flag_trigger,
1488              &params.flag_flow_type,
1489              &params.flag_protection);
1490     if (ret != 16)
1491         return -EINVAL;
1492 
1493     params.vdev_id = arvif->vdev_id;
1494 
1495     ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, &params);
1496     if (ret)
1497         return ret;
1498 
1499     return count;
1500 }
1501 
1502 static ssize_t ath11k_write_twt_del_dialog(struct file *file,
1503                        const char __user *ubuf,
1504                        size_t count, loff_t *ppos)
1505 {
1506     struct ath11k_vif *arvif = file->private_data;
1507     struct wmi_twt_del_dialog_params params = { 0 };
1508     u8 buf[64] = {0};
1509     int ret;
1510 
1511     if (arvif->ar->twt_enabled == 0) {
1512         ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1513         return -EOPNOTSUPP;
1514     }
1515 
1516     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1517     if (ret < 0)
1518         return ret;
1519 
1520     buf[ret] = '\0';
1521     ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1522              &params.peer_macaddr[0],
1523              &params.peer_macaddr[1],
1524              &params.peer_macaddr[2],
1525              &params.peer_macaddr[3],
1526              &params.peer_macaddr[4],
1527              &params.peer_macaddr[5],
1528              &params.dialog_id);
1529     if (ret != 7)
1530         return -EINVAL;
1531 
1532     params.vdev_id = arvif->vdev_id;
1533 
1534     ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, &params);
1535     if (ret)
1536         return ret;
1537 
1538     return count;
1539 }
1540 
1541 static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
1542                          const char __user *ubuf,
1543                          size_t count, loff_t *ppos)
1544 {
1545     struct ath11k_vif *arvif = file->private_data;
1546     struct wmi_twt_pause_dialog_params params = { 0 };
1547     u8 buf[64] = {0};
1548     int ret;
1549 
1550     if (arvif->ar->twt_enabled == 0) {
1551         ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1552         return -EOPNOTSUPP;
1553     }
1554 
1555     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1556     if (ret < 0)
1557         return ret;
1558 
1559     buf[ret] = '\0';
1560     ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1561              &params.peer_macaddr[0],
1562              &params.peer_macaddr[1],
1563              &params.peer_macaddr[2],
1564              &params.peer_macaddr[3],
1565              &params.peer_macaddr[4],
1566              &params.peer_macaddr[5],
1567              &params.dialog_id);
1568     if (ret != 7)
1569         return -EINVAL;
1570 
1571     params.vdev_id = arvif->vdev_id;
1572 
1573     ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, &params);
1574     if (ret)
1575         return ret;
1576 
1577     return count;
1578 }
1579 
1580 static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
1581                           const char __user *ubuf,
1582                           size_t count, loff_t *ppos)
1583 {
1584     struct ath11k_vif *arvif = file->private_data;
1585     struct wmi_twt_resume_dialog_params params = { 0 };
1586     u8 buf[64] = {0};
1587     int ret;
1588 
1589     if (arvif->ar->twt_enabled == 0) {
1590         ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1591         return -EOPNOTSUPP;
1592     }
1593 
1594     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1595     if (ret < 0)
1596         return ret;
1597 
1598     buf[ret] = '\0';
1599     ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
1600              &params.peer_macaddr[0],
1601              &params.peer_macaddr[1],
1602              &params.peer_macaddr[2],
1603              &params.peer_macaddr[3],
1604              &params.peer_macaddr[4],
1605              &params.peer_macaddr[5],
1606              &params.dialog_id,
1607              &params.sp_offset_us,
1608              &params.next_twt_size);
1609     if (ret != 9)
1610         return -EINVAL;
1611 
1612     params.vdev_id = arvif->vdev_id;
1613 
1614     ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, &params);
1615     if (ret)
1616         return ret;
1617 
1618     return count;
1619 }
1620 
1621 static const struct file_operations ath11k_fops_twt_add_dialog = {
1622     .write = ath11k_write_twt_add_dialog,
1623     .open = simple_open
1624 };
1625 
1626 static const struct file_operations ath11k_fops_twt_del_dialog = {
1627     .write = ath11k_write_twt_del_dialog,
1628     .open = simple_open
1629 };
1630 
1631 static const struct file_operations ath11k_fops_twt_pause_dialog = {
1632     .write = ath11k_write_twt_pause_dialog,
1633     .open = simple_open
1634 };
1635 
1636 static const struct file_operations ath11k_fops_twt_resume_dialog = {
1637     .write = ath11k_write_twt_resume_dialog,
1638     .open = simple_open
1639 };
1640 
1641 int ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
1642 {
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;
1651             return -1;
1652         }
1653 
1654         debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
1655                     arvif, &ath11k_fops_twt_add_dialog);
1656 
1657         debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
1658                     arvif, &ath11k_fops_twt_del_dialog);
1659 
1660         debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
1661                     arvif, &ath11k_fops_twt_pause_dialog);
1662 
1663         debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
1664                     arvif, &ath11k_fops_twt_resume_dialog);
1665     }
1666     return 0;
1667 }
1668 
1669 void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
1670 {
1671     debugfs_remove_recursive(arvif->debugfs_twt);
1672     arvif->debugfs_twt = NULL;
1673 }