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 ? true : false); 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 ? true : false); 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; 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 ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id; 702 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, 703 HAL_RXDMA_MONITOR_STATUS, 704 DP_RX_BUFFER_SIZE, &tlv_filter); 705 706 if (ret) { 707 ath11k_warn(ar->ab, "failed to set rx filter for moniter status ring\n"); 708 goto exit; 709 } 710 711 ar->debug.extd_rx_stats = enable; 712 ret = count; 713 exit: 714 mutex_unlock(&ar->conf_mutex); 715 return ret; 716 } 717 718 static ssize_t ath11k_read_extd_rx_stats(struct file *file, 719 char __user *ubuf, 720 size_t count, loff_t *ppos) 721 { 722 struct ath11k *ar = file->private_data; 723 char buf[32]; 724 int len = 0; 725 726 mutex_lock(&ar->conf_mutex); 727 len = scnprintf(buf, sizeof(buf) - len, "%d\n", 728 ar->debug.extd_rx_stats); 729 mutex_unlock(&ar->conf_mutex); 730 731 return simple_read_from_buffer(ubuf, count, ppos, buf, len); 732 } 733 734 static const struct file_operations fops_extd_rx_stats = { 735 .read = ath11k_read_extd_rx_stats, 736 .write = ath11k_write_extd_rx_stats, 737 .open = simple_open, 738 }; 739 740 static ssize_t ath11k_debug_dump_soc_rx_stats(struct file *file, 741 char __user *user_buf, 742 size_t count, loff_t *ppos) 743 { 744 struct ath11k_base *ab = file->private_data; 745 struct ath11k_soc_dp_rx_stats *soc_stats = &ab->soc_stats; 746 int len = 0, i, retval; 747 const int size = 4096; 748 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = { 749 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC", 750 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse", 751 "AMSDU parse", "SA timeout", "DA timeout", 752 "Flow timeout", "Flush req"}; 753 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = { 754 "Desc addr zero", "Desc inval", "AMPDU in non BA", 755 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump", 756 "Frame OOR", "BAR OOR", "No BA session", 757 "Frame SN equal SSN", "PN check fail", "2k err", 758 "PN err", "Desc blocked"}; 759 760 char *buf; 761 762 buf = kzalloc(size, GFP_KERNEL); 763 if (!buf) 764 return -ENOMEM; 765 766 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n"); 767 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n", 768 soc_stats->err_ring_pkts); 769 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n", 770 soc_stats->invalid_rbm); 771 len += scnprintf(buf + len, size - len, "RXDMA errors:\n"); 772 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++) 773 len += scnprintf(buf + len, size - len, "%s: %u\n", 774 rxdma_err[i], soc_stats->rxdma_error[i]); 775 776 len += scnprintf(buf + len, size - len, "\nREO errors:\n"); 777 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++) 778 len += scnprintf(buf + len, size - len, "%s: %u\n", 779 reo_err[i], soc_stats->reo_error[i]); 780 781 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n"); 782 len += scnprintf(buf + len, size - len, 783 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n", 784 soc_stats->hal_reo_error[0], 785 soc_stats->hal_reo_error[1], 786 soc_stats->hal_reo_error[2], 787 soc_stats->hal_reo_error[3]); 788 789 if (len > size) 790 len = size; 791 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 792 kfree(buf); 793 794 return retval; 795 } 796 797 static const struct file_operations fops_soc_rx_stats = { 798 .read = ath11k_debug_dump_soc_rx_stats, 799 .open = simple_open, 800 .owner = THIS_MODULE, 801 .llseek = default_llseek, 802 }; 803 804 int ath11k_debug_pdev_create(struct ath11k_base *ab) 805 { 806 ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k); 807 808 if (IS_ERR_OR_NULL(ab->debugfs_soc)) { 809 if (IS_ERR(ab->debugfs_soc)) 810 return PTR_ERR(ab->debugfs_soc); 811 return -ENOMEM; 812 } 813 814 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab, 815 &fops_simulate_fw_crash); 816 817 debugfs_create_file("soc_rx_stats", 0600, ab->debugfs_soc, ab, 818 &fops_soc_rx_stats); 819 820 return 0; 821 } 822 823 void ath11k_debug_pdev_destroy(struct ath11k_base *ab) 824 { 825 debugfs_remove_recursive(ab->debugfs_ath11k); 826 ab->debugfs_ath11k = NULL; 827 } 828 829 int ath11k_debug_soc_create(struct ath11k_base *ab) 830 { 831 ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL); 832 833 if (IS_ERR_OR_NULL(ab->debugfs_ath11k)) { 834 if (IS_ERR(ab->debugfs_ath11k)) 835 return PTR_ERR(ab->debugfs_ath11k); 836 return -ENOMEM; 837 } 838 839 return 0; 840 } 841 842 void ath11k_debug_soc_destroy(struct ath11k_base *ab) 843 { 844 debugfs_remove_recursive(ab->debugfs_soc); 845 ab->debugfs_soc = NULL; 846 } 847 848 void ath11k_debug_fw_stats_init(struct ath11k *ar) 849 { 850 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats", 851 ar->debug.debugfs_pdev); 852 853 ar->debug.fw_stats.debugfs_fwstats = fwstats_dir; 854 855 /* all stats debugfs files created are under "fw_stats" directory 856 * created per PDEV 857 */ 858 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar, 859 &fops_pdev_stats); 860 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar, 861 &fops_vdev_stats); 862 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar, 863 &fops_bcn_stats); 864 865 INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); 866 INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs); 867 INIT_LIST_HEAD(&ar->debug.fw_stats.bcn); 868 869 init_completion(&ar->debug.fw_stats_complete); 870 } 871 872 static ssize_t ath11k_write_pktlog_filter(struct file *file, 873 const char __user *ubuf, 874 size_t count, loff_t *ppos) 875 { 876 struct ath11k *ar = file->private_data; 877 struct htt_rx_ring_tlv_filter tlv_filter = {0}; 878 u32 rx_filter = 0, ring_id, filter, mode; 879 u8 buf[128] = {0}; 880 int ret; 881 ssize_t rc; 882 883 mutex_lock(&ar->conf_mutex); 884 if (ar->state != ATH11K_STATE_ON) { 885 ret = -ENETDOWN; 886 goto out; 887 } 888 889 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); 890 if (rc < 0) { 891 ret = rc; 892 goto out; 893 } 894 buf[rc] = '\0'; 895 896 ret = sscanf(buf, "0x%x %u", &filter, &mode); 897 if (ret != 2) { 898 ret = -EINVAL; 899 goto out; 900 } 901 902 if (filter) { 903 ret = ath11k_wmi_pdev_pktlog_enable(ar, filter); 904 if (ret) { 905 ath11k_warn(ar->ab, 906 "failed to enable pktlog filter %x: %d\n", 907 ar->debug.pktlog_filter, ret); 908 goto out; 909 } 910 } else { 911 ret = ath11k_wmi_pdev_pktlog_disable(ar); 912 if (ret) { 913 ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret); 914 goto out; 915 } 916 } 917 918 #define HTT_RX_FILTER_TLV_LITE_MODE \ 919 (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \ 920 HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \ 921 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \ 922 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \ 923 HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \ 924 HTT_RX_FILTER_TLV_FLAGS_MPDU_START) 925 926 if (mode == ATH11K_PKTLOG_MODE_FULL) { 927 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE | 928 HTT_RX_FILTER_TLV_FLAGS_MSDU_START | 929 HTT_RX_FILTER_TLV_FLAGS_MSDU_END | 930 HTT_RX_FILTER_TLV_FLAGS_MPDU_END | 931 HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | 932 HTT_RX_FILTER_TLV_FLAGS_ATTENTION; 933 } else if (mode == ATH11K_PKTLOG_MODE_LITE) { 934 rx_filter = HTT_RX_FILTER_TLV_LITE_MODE; 935 } 936 937 tlv_filter.rx_filter = rx_filter; 938 if (rx_filter) { 939 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; 940 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1; 941 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2; 942 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 | 943 HTT_RX_FP_DATA_FILTER_FLASG3; 944 } 945 946 ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id; 947 ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, 948 HAL_RXDMA_MONITOR_STATUS, 949 DP_RX_BUFFER_SIZE, &tlv_filter); 950 if (ret) { 951 ath11k_warn(ar->ab, "failed to set rx filter for moniter status ring\n"); 952 goto out; 953 } 954 955 ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n", 956 filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite")); 957 958 ar->debug.pktlog_filter = filter; 959 ar->debug.pktlog_mode = mode; 960 ret = count; 961 962 out: 963 mutex_unlock(&ar->conf_mutex); 964 return ret; 965 } 966 967 static ssize_t ath11k_read_pktlog_filter(struct file *file, 968 char __user *ubuf, 969 size_t count, loff_t *ppos) 970 971 { 972 char buf[32] = {0}; 973 struct ath11k *ar = file->private_data; 974 int len = 0; 975 976 mutex_lock(&ar->conf_mutex); 977 len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n", 978 ar->debug.pktlog_filter, 979 ar->debug.pktlog_mode); 980 mutex_unlock(&ar->conf_mutex); 981 982 return simple_read_from_buffer(ubuf, count, ppos, buf, len); 983 } 984 985 static const struct file_operations fops_pktlog_filter = { 986 .read = ath11k_read_pktlog_filter, 987 .write = ath11k_write_pktlog_filter, 988 .open = simple_open 989 }; 990 991 static ssize_t ath11k_write_simulate_radar(struct file *file, 992 const char __user *user_buf, 993 size_t count, loff_t *ppos) 994 { 995 struct ath11k *ar = file->private_data; 996 int ret; 997 998 ret = ath11k_wmi_simulate_radar(ar); 999 if (ret) 1000 return ret; 1001 1002 return count; 1003 } 1004 1005 static const struct file_operations fops_simulate_radar = { 1006 .write = ath11k_write_simulate_radar, 1007 .open = simple_open 1008 }; 1009 1010 int ath11k_debug_register(struct ath11k *ar) 1011 { 1012 struct ath11k_base *ab = ar->ab; 1013 char pdev_name[5]; 1014 char buf[100] = {0}; 1015 1016 snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx); 1017 1018 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc); 1019 1020 if (IS_ERR_OR_NULL(ar->debug.debugfs_pdev)) { 1021 if (IS_ERR(ar->debug.debugfs_pdev)) 1022 return PTR_ERR(ar->debug.debugfs_pdev); 1023 1024 return -ENOMEM; 1025 } 1026 1027 /* Create a symlink under ieee80211/phy* */ 1028 snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev); 1029 debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf); 1030 1031 ath11k_debug_htt_stats_init(ar); 1032 1033 ath11k_debug_fw_stats_init(ar); 1034 1035 debugfs_create_file("ext_tx_stats", 0644, 1036 ar->debug.debugfs_pdev, ar, 1037 &fops_extd_tx_stats); 1038 debugfs_create_file("ext_rx_stats", 0644, 1039 ar->debug.debugfs_pdev, ar, 1040 &fops_extd_rx_stats); 1041 debugfs_create_file("pktlog_filter", 0644, 1042 ar->debug.debugfs_pdev, ar, 1043 &fops_pktlog_filter); 1044 1045 if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) { 1046 debugfs_create_file("dfs_simulate_radar", 0200, 1047 ar->debug.debugfs_pdev, ar, 1048 &fops_simulate_radar); 1049 debugfs_create_bool("dfs_block_radar_events", 0200, 1050 ar->debug.debugfs_pdev, 1051 &ar->dfs_block_radar_events); 1052 } 1053 1054 return 0; 1055 } 1056 1057 void ath11k_debug_unregister(struct ath11k *ar) 1058 { 1059 } 1060 #endif /* CONFIG_ATH11K_DEBUGFS */ 1061