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