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