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