1 /* 2 * Copyright (c) 2005-2011 Atheros Communications Inc. 3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <linux/module.h> 19 #include <linux/debugfs.h> 20 21 #include "core.h" 22 #include "debug.h" 23 24 /* ms */ 25 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 26 27 static int ath10k_printk(const char *level, const char *fmt, ...) 28 { 29 struct va_format vaf; 30 va_list args; 31 int rtn; 32 33 va_start(args, fmt); 34 35 vaf.fmt = fmt; 36 vaf.va = &args; 37 38 rtn = printk("%sath10k: %pV", level, &vaf); 39 40 va_end(args); 41 42 return rtn; 43 } 44 45 int ath10k_info(const char *fmt, ...) 46 { 47 struct va_format vaf = { 48 .fmt = fmt, 49 }; 50 va_list args; 51 int ret; 52 53 va_start(args, fmt); 54 vaf.va = &args; 55 ret = ath10k_printk(KERN_INFO, "%pV", &vaf); 56 trace_ath10k_log_info(&vaf); 57 va_end(args); 58 59 return ret; 60 } 61 EXPORT_SYMBOL(ath10k_info); 62 63 int ath10k_err(const char *fmt, ...) 64 { 65 struct va_format vaf = { 66 .fmt = fmt, 67 }; 68 va_list args; 69 int ret; 70 71 va_start(args, fmt); 72 vaf.va = &args; 73 ret = ath10k_printk(KERN_ERR, "%pV", &vaf); 74 trace_ath10k_log_err(&vaf); 75 va_end(args); 76 77 return ret; 78 } 79 EXPORT_SYMBOL(ath10k_err); 80 81 int ath10k_warn(const char *fmt, ...) 82 { 83 struct va_format vaf = { 84 .fmt = fmt, 85 }; 86 va_list args; 87 int ret = 0; 88 89 va_start(args, fmt); 90 vaf.va = &args; 91 92 if (net_ratelimit()) 93 ret = ath10k_printk(KERN_WARNING, "%pV", &vaf); 94 95 trace_ath10k_log_warn(&vaf); 96 97 va_end(args); 98 99 return ret; 100 } 101 EXPORT_SYMBOL(ath10k_warn); 102 103 #ifdef CONFIG_ATH10K_DEBUGFS 104 105 void ath10k_debug_read_service_map(struct ath10k *ar, 106 void *service_map, 107 size_t map_size) 108 { 109 memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); 110 } 111 112 static ssize_t ath10k_read_wmi_services(struct file *file, 113 char __user *user_buf, 114 size_t count, loff_t *ppos) 115 { 116 struct ath10k *ar = file->private_data; 117 char *buf; 118 unsigned int len = 0, buf_len = 1500; 119 const char *status; 120 ssize_t ret_cnt; 121 int i; 122 123 buf = kzalloc(buf_len, GFP_KERNEL); 124 if (!buf) 125 return -ENOMEM; 126 127 mutex_lock(&ar->conf_mutex); 128 129 if (len > buf_len) 130 len = buf_len; 131 132 for (i = 0; i < WMI_SERVICE_LAST; i++) { 133 if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i)) 134 status = "enabled"; 135 else 136 status = "disabled"; 137 138 len += scnprintf(buf + len, buf_len - len, 139 "0x%02x - %20s - %s\n", 140 i, wmi_service_name(i), status); 141 } 142 143 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 144 145 mutex_unlock(&ar->conf_mutex); 146 147 kfree(buf); 148 return ret_cnt; 149 } 150 151 static const struct file_operations fops_wmi_services = { 152 .read = ath10k_read_wmi_services, 153 .open = simple_open, 154 .owner = THIS_MODULE, 155 .llseek = default_llseek, 156 }; 157 158 void ath10k_debug_read_target_stats(struct ath10k *ar, 159 struct wmi_stats_event *ev) 160 { 161 u8 *tmp = ev->data; 162 struct ath10k_target_stats *stats; 163 int num_pdev_stats, num_vdev_stats, num_peer_stats; 164 struct wmi_pdev_stats *ps; 165 int i; 166 167 spin_lock_bh(&ar->data_lock); 168 169 stats = &ar->debug.target_stats; 170 171 num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */ 172 num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */ 173 num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */ 174 175 if (num_pdev_stats) { 176 ps = (struct wmi_pdev_stats *)tmp; 177 178 stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf); 179 stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count); 180 stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count); 181 stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count); 182 stats->cycle_count = __le32_to_cpu(ps->cycle_count); 183 stats->phy_err_count = __le32_to_cpu(ps->phy_err_count); 184 stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr); 185 186 stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued); 187 stats->comp_delivered = 188 __le32_to_cpu(ps->wal.tx.comp_delivered); 189 stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued); 190 stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued); 191 stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop); 192 stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued); 193 stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed); 194 stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued); 195 stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped); 196 stats->underrun = __le32_to_cpu(ps->wal.tx.underrun); 197 stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort); 198 stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed); 199 stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko); 200 stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc); 201 stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers); 202 stats->sw_retry_failure = 203 __le32_to_cpu(ps->wal.tx.sw_retry_failure); 204 stats->illgl_rate_phy_err = 205 __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err); 206 stats->pdev_cont_xretry = 207 __le32_to_cpu(ps->wal.tx.pdev_cont_xretry); 208 stats->pdev_tx_timeout = 209 __le32_to_cpu(ps->wal.tx.pdev_tx_timeout); 210 stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets); 211 stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun); 212 stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf); 213 214 stats->mid_ppdu_route_change = 215 __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change); 216 stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd); 217 stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags); 218 stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags); 219 stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags); 220 stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags); 221 stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus); 222 stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus); 223 stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus); 224 stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus); 225 stats->oversize_amsdu = 226 __le32_to_cpu(ps->wal.rx.oversize_amsdu); 227 stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs); 228 stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop); 229 stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs); 230 231 tmp += sizeof(struct wmi_pdev_stats); 232 } 233 234 /* 0 or max vdevs */ 235 /* Currently firmware does not support VDEV stats */ 236 if (num_vdev_stats) { 237 struct wmi_vdev_stats *vdev_stats; 238 239 for (i = 0; i < num_vdev_stats; i++) { 240 vdev_stats = (struct wmi_vdev_stats *)tmp; 241 tmp += sizeof(struct wmi_vdev_stats); 242 } 243 } 244 245 if (num_peer_stats) { 246 struct wmi_peer_stats *peer_stats; 247 struct ath10k_peer_stat *s; 248 249 stats->peers = num_peer_stats; 250 251 for (i = 0; i < num_peer_stats; i++) { 252 peer_stats = (struct wmi_peer_stats *)tmp; 253 s = &stats->peer_stat[i]; 254 255 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, 256 s->peer_macaddr); 257 s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi); 258 s->peer_tx_rate = 259 __le32_to_cpu(peer_stats->peer_tx_rate); 260 261 tmp += sizeof(struct wmi_peer_stats); 262 } 263 } 264 265 spin_unlock_bh(&ar->data_lock); 266 complete(&ar->debug.event_stats_compl); 267 } 268 269 static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, 270 size_t count, loff_t *ppos) 271 { 272 struct ath10k *ar = file->private_data; 273 struct ath10k_target_stats *fw_stats; 274 char *buf = NULL; 275 unsigned int len = 0, buf_len = 2500; 276 ssize_t ret_cnt = 0; 277 long left; 278 int i; 279 int ret; 280 281 fw_stats = &ar->debug.target_stats; 282 283 mutex_lock(&ar->conf_mutex); 284 285 if (ar->state != ATH10K_STATE_ON) 286 goto exit; 287 288 buf = kzalloc(buf_len, GFP_KERNEL); 289 if (!buf) 290 goto exit; 291 292 ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); 293 if (ret) { 294 ath10k_warn("could not request stats (%d)\n", ret); 295 goto exit; 296 } 297 298 left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ); 299 if (left <= 0) 300 goto exit; 301 302 spin_lock_bh(&ar->data_lock); 303 len += scnprintf(buf + len, buf_len - len, "\n"); 304 len += scnprintf(buf + len, buf_len - len, "%30s\n", 305 "ath10k PDEV stats"); 306 len += scnprintf(buf + len, buf_len - len, "%30s\n\n", 307 "================="); 308 309 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 310 "Channel noise floor", fw_stats->ch_noise_floor); 311 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 312 "Channel TX power", fw_stats->chan_tx_power); 313 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 314 "TX frame count", fw_stats->tx_frame_count); 315 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 316 "RX frame count", fw_stats->rx_frame_count); 317 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 318 "RX clear count", fw_stats->rx_clear_count); 319 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 320 "Cycle count", fw_stats->cycle_count); 321 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", 322 "PHY error count", fw_stats->phy_err_count); 323 324 len += scnprintf(buf + len, buf_len - len, "\n"); 325 len += scnprintf(buf + len, buf_len - len, "%30s\n", 326 "ath10k PDEV TX stats"); 327 len += scnprintf(buf + len, buf_len - len, "%30s\n\n", 328 "================="); 329 330 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 331 "HTT cookies queued", fw_stats->comp_queued); 332 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 333 "HTT cookies disp.", fw_stats->comp_delivered); 334 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 335 "MSDU queued", fw_stats->msdu_enqued); 336 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 337 "MPDU queued", fw_stats->mpdu_enqued); 338 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 339 "MSDUs dropped", fw_stats->wmm_drop); 340 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 341 "Local enqued", fw_stats->local_enqued); 342 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 343 "Local freed", fw_stats->local_freed); 344 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 345 "HW queued", fw_stats->hw_queued); 346 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 347 "PPDUs reaped", fw_stats->hw_reaped); 348 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 349 "Num underruns", fw_stats->underrun); 350 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 351 "PPDUs cleaned", fw_stats->tx_abort); 352 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 353 "MPDUs requed", fw_stats->mpdus_requed); 354 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 355 "Excessive retries", fw_stats->tx_ko); 356 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 357 "HW rate", fw_stats->data_rc); 358 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 359 "Sched self tiggers", fw_stats->self_triggers); 360 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 361 "Dropped due to SW retries", 362 fw_stats->sw_retry_failure); 363 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 364 "Illegal rate phy errors", 365 fw_stats->illgl_rate_phy_err); 366 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 367 "Pdev continous xretry", fw_stats->pdev_cont_xretry); 368 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 369 "TX timeout", fw_stats->pdev_tx_timeout); 370 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 371 "PDEV resets", fw_stats->pdev_resets); 372 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 373 "PHY underrun", fw_stats->phy_underrun); 374 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 375 "MPDU is more than txop limit", fw_stats->txop_ovf); 376 377 len += scnprintf(buf + len, buf_len - len, "\n"); 378 len += scnprintf(buf + len, buf_len - len, "%30s\n", 379 "ath10k PDEV RX stats"); 380 len += scnprintf(buf + len, buf_len - len, "%30s\n\n", 381 "================="); 382 383 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 384 "Mid PPDU route change", 385 fw_stats->mid_ppdu_route_change); 386 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 387 "Tot. number of statuses", fw_stats->status_rcvd); 388 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 389 "Extra frags on rings 0", fw_stats->r0_frags); 390 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 391 "Extra frags on rings 1", fw_stats->r1_frags); 392 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 393 "Extra frags on rings 2", fw_stats->r2_frags); 394 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 395 "Extra frags on rings 3", fw_stats->r3_frags); 396 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 397 "MSDUs delivered to HTT", fw_stats->htt_msdus); 398 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 399 "MPDUs delivered to HTT", fw_stats->htt_mpdus); 400 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 401 "MSDUs delivered to stack", fw_stats->loc_msdus); 402 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 403 "MPDUs delivered to stack", fw_stats->loc_mpdus); 404 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 405 "Oversized AMSUs", fw_stats->oversize_amsdu); 406 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 407 "PHY errors", fw_stats->phy_errs); 408 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 409 "PHY errors drops", fw_stats->phy_err_drop); 410 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", 411 "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs); 412 413 len += scnprintf(buf + len, buf_len - len, "\n"); 414 len += scnprintf(buf + len, buf_len - len, "%30s\n", 415 "ath10k PEER stats"); 416 len += scnprintf(buf + len, buf_len - len, "%30s\n\n", 417 "================="); 418 419 for (i = 0; i < fw_stats->peers; i++) { 420 len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", 421 "Peer MAC address", 422 fw_stats->peer_stat[i].peer_macaddr); 423 len += scnprintf(buf + len, buf_len - len, "%30s %u\n", 424 "Peer RSSI", fw_stats->peer_stat[i].peer_rssi); 425 len += scnprintf(buf + len, buf_len - len, "%30s %u\n", 426 "Peer TX rate", 427 fw_stats->peer_stat[i].peer_tx_rate); 428 len += scnprintf(buf + len, buf_len - len, "\n"); 429 } 430 spin_unlock_bh(&ar->data_lock); 431 432 if (len > buf_len) 433 len = buf_len; 434 435 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 436 437 exit: 438 mutex_unlock(&ar->conf_mutex); 439 kfree(buf); 440 return ret_cnt; 441 } 442 443 static const struct file_operations fops_fw_stats = { 444 .read = ath10k_read_fw_stats, 445 .open = simple_open, 446 .owner = THIS_MODULE, 447 .llseek = default_llseek, 448 }; 449 450 static ssize_t ath10k_read_simulate_fw_crash(struct file *file, 451 char __user *user_buf, 452 size_t count, loff_t *ppos) 453 { 454 const char buf[] = "To simulate firmware crash write the keyword" 455 " `crash` to this file.\nThis will force firmware" 456 " to report a crash to the host system.\n"; 457 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 458 } 459 460 static ssize_t ath10k_write_simulate_fw_crash(struct file *file, 461 const char __user *user_buf, 462 size_t count, loff_t *ppos) 463 { 464 struct ath10k *ar = file->private_data; 465 char buf[32] = {}; 466 int ret; 467 468 mutex_lock(&ar->conf_mutex); 469 470 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); 471 if (strcmp(buf, "crash") && strcmp(buf, "crash\n")) { 472 ret = -EINVAL; 473 goto exit; 474 } 475 476 if (ar->state != ATH10K_STATE_ON && 477 ar->state != ATH10K_STATE_RESTARTED) { 478 ret = -ENETDOWN; 479 goto exit; 480 } 481 482 ath10k_info("simulating firmware crash\n"); 483 484 ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0); 485 if (ret) 486 ath10k_warn("failed to force fw hang (%d)\n", ret); 487 488 if (ret == 0) 489 ret = count; 490 491 exit: 492 mutex_unlock(&ar->conf_mutex); 493 return ret; 494 } 495 496 static const struct file_operations fops_simulate_fw_crash = { 497 .read = ath10k_read_simulate_fw_crash, 498 .write = ath10k_write_simulate_fw_crash, 499 .open = simple_open, 500 .owner = THIS_MODULE, 501 .llseek = default_llseek, 502 }; 503 504 static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf, 505 size_t count, loff_t *ppos) 506 { 507 struct ath10k *ar = file->private_data; 508 unsigned int len; 509 char buf[50]; 510 511 len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id); 512 513 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 514 } 515 516 static const struct file_operations fops_chip_id = { 517 .read = ath10k_read_chip_id, 518 .open = simple_open, 519 .owner = THIS_MODULE, 520 .llseek = default_llseek, 521 }; 522 523 static int ath10k_debug_htt_stats_req(struct ath10k *ar) 524 { 525 u64 cookie; 526 int ret; 527 528 lockdep_assert_held(&ar->conf_mutex); 529 530 if (ar->debug.htt_stats_mask == 0) 531 /* htt stats are disabled */ 532 return 0; 533 534 if (ar->state != ATH10K_STATE_ON) 535 return 0; 536 537 cookie = get_jiffies_64(); 538 539 ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask, 540 cookie); 541 if (ret) { 542 ath10k_warn("failed to send htt stats request: %d\n", ret); 543 return ret; 544 } 545 546 queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork, 547 msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL)); 548 549 return 0; 550 } 551 552 static void ath10k_debug_htt_stats_dwork(struct work_struct *work) 553 { 554 struct ath10k *ar = container_of(work, struct ath10k, 555 debug.htt_stats_dwork.work); 556 557 mutex_lock(&ar->conf_mutex); 558 559 ath10k_debug_htt_stats_req(ar); 560 561 mutex_unlock(&ar->conf_mutex); 562 } 563 564 static ssize_t ath10k_read_htt_stats_mask(struct file *file, 565 char __user *user_buf, 566 size_t count, loff_t *ppos) 567 { 568 struct ath10k *ar = file->private_data; 569 char buf[32]; 570 unsigned int len; 571 572 len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask); 573 574 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 575 } 576 577 static ssize_t ath10k_write_htt_stats_mask(struct file *file, 578 const char __user *user_buf, 579 size_t count, loff_t *ppos) 580 { 581 struct ath10k *ar = file->private_data; 582 unsigned long mask; 583 int ret; 584 585 ret = kstrtoul_from_user(user_buf, count, 0, &mask); 586 if (ret) 587 return ret; 588 589 /* max 8 bit masks (for now) */ 590 if (mask > 0xff) 591 return -E2BIG; 592 593 mutex_lock(&ar->conf_mutex); 594 595 ar->debug.htt_stats_mask = mask; 596 597 ret = ath10k_debug_htt_stats_req(ar); 598 if (ret) 599 goto out; 600 601 ret = count; 602 603 out: 604 mutex_unlock(&ar->conf_mutex); 605 606 return ret; 607 } 608 609 static const struct file_operations fops_htt_stats_mask = { 610 .read = ath10k_read_htt_stats_mask, 611 .write = ath10k_write_htt_stats_mask, 612 .open = simple_open, 613 .owner = THIS_MODULE, 614 .llseek = default_llseek, 615 }; 616 617 static ssize_t ath10k_read_fw_dbglog(struct file *file, 618 char __user *user_buf, 619 size_t count, loff_t *ppos) 620 { 621 struct ath10k *ar = file->private_data; 622 unsigned int len; 623 char buf[32]; 624 625 len = scnprintf(buf, sizeof(buf), "0x%08x\n", 626 ar->debug.fw_dbglog_mask); 627 628 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 629 } 630 631 static ssize_t ath10k_write_fw_dbglog(struct file *file, 632 const char __user *user_buf, 633 size_t count, loff_t *ppos) 634 { 635 struct ath10k *ar = file->private_data; 636 unsigned long mask; 637 int ret; 638 639 ret = kstrtoul_from_user(user_buf, count, 0, &mask); 640 if (ret) 641 return ret; 642 643 mutex_lock(&ar->conf_mutex); 644 645 ar->debug.fw_dbglog_mask = mask; 646 647 if (ar->state == ATH10K_STATE_ON) { 648 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); 649 if (ret) { 650 ath10k_warn("dbglog cfg failed from debugfs: %d\n", 651 ret); 652 goto exit; 653 } 654 } 655 656 ret = count; 657 658 exit: 659 mutex_unlock(&ar->conf_mutex); 660 661 return ret; 662 } 663 664 static const struct file_operations fops_fw_dbglog = { 665 .read = ath10k_read_fw_dbglog, 666 .write = ath10k_write_fw_dbglog, 667 .open = simple_open, 668 .owner = THIS_MODULE, 669 .llseek = default_llseek, 670 }; 671 672 int ath10k_debug_start(struct ath10k *ar) 673 { 674 int ret; 675 676 lockdep_assert_held(&ar->conf_mutex); 677 678 ret = ath10k_debug_htt_stats_req(ar); 679 if (ret) 680 /* continue normally anyway, this isn't serious */ 681 ath10k_warn("failed to start htt stats workqueue: %d\n", ret); 682 683 if (ar->debug.fw_dbglog_mask) { 684 ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); 685 if (ret) 686 /* not serious */ 687 ath10k_warn("failed to enable dbglog during start: %d", 688 ret); 689 } 690 691 return 0; 692 } 693 694 void ath10k_debug_stop(struct ath10k *ar) 695 { 696 lockdep_assert_held(&ar->conf_mutex); 697 698 /* Must not use _sync to avoid deadlock, we do that in 699 * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid 700 * warning from del_timer(). */ 701 if (ar->debug.htt_stats_mask != 0) 702 cancel_delayed_work(&ar->debug.htt_stats_dwork); 703 } 704 705 static ssize_t ath10k_write_simulate_radar(struct file *file, 706 const char __user *user_buf, 707 size_t count, loff_t *ppos) 708 { 709 struct ath10k *ar = file->private_data; 710 711 ieee80211_radar_detected(ar->hw); 712 713 return count; 714 } 715 716 static const struct file_operations fops_simulate_radar = { 717 .write = ath10k_write_simulate_radar, 718 .open = simple_open, 719 .owner = THIS_MODULE, 720 .llseek = default_llseek, 721 }; 722 723 #define ATH10K_DFS_STAT(s, p) (\ 724 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \ 725 ar->debug.dfs_stats.p)) 726 727 #define ATH10K_DFS_POOL_STAT(s, p) (\ 728 len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \ 729 ar->debug.dfs_pool_stats.p)) 730 731 static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf, 732 size_t count, loff_t *ppos) 733 { 734 int retval = 0, len = 0; 735 const int size = 8000; 736 struct ath10k *ar = file->private_data; 737 char *buf; 738 739 buf = kzalloc(size, GFP_KERNEL); 740 if (buf == NULL) 741 return -ENOMEM; 742 743 if (!ar->dfs_detector) { 744 len += scnprintf(buf + len, size - len, "DFS not enabled\n"); 745 goto exit; 746 } 747 748 ar->debug.dfs_pool_stats = 749 ar->dfs_detector->get_stats(ar->dfs_detector); 750 751 len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n"); 752 753 ATH10K_DFS_STAT("reported phy errors", phy_errors); 754 ATH10K_DFS_STAT("pulse events reported", pulses_total); 755 ATH10K_DFS_STAT("DFS pulses detected", pulses_detected); 756 ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded); 757 ATH10K_DFS_STAT("Radars detected", radar_detected); 758 759 len += scnprintf(buf + len, size - len, "Global Pool statistics:\n"); 760 ATH10K_DFS_POOL_STAT("Pool references", pool_reference); 761 ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated); 762 ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error); 763 ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used); 764 ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated); 765 ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error); 766 ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used); 767 768 exit: 769 if (len > size) 770 len = size; 771 772 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 773 kfree(buf); 774 775 return retval; 776 } 777 778 static const struct file_operations fops_dfs_stats = { 779 .read = ath10k_read_dfs_stats, 780 .open = simple_open, 781 .owner = THIS_MODULE, 782 .llseek = default_llseek, 783 }; 784 785 int ath10k_debug_create(struct ath10k *ar) 786 { 787 ar->debug.debugfs_phy = debugfs_create_dir("ath10k", 788 ar->hw->wiphy->debugfsdir); 789 790 if (!ar->debug.debugfs_phy) 791 return -ENOMEM; 792 793 INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, 794 ath10k_debug_htt_stats_dwork); 795 796 init_completion(&ar->debug.event_stats_compl); 797 798 debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, 799 &fops_fw_stats); 800 801 debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, 802 &fops_wmi_services); 803 804 debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, 805 ar, &fops_simulate_fw_crash); 806 807 debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy, 808 ar, &fops_chip_id); 809 810 debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, 811 ar, &fops_htt_stats_mask); 812 813 debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, 814 ar, &fops_fw_dbglog); 815 816 if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { 817 debugfs_create_file("dfs_simulate_radar", S_IWUSR, 818 ar->debug.debugfs_phy, ar, 819 &fops_simulate_radar); 820 821 debugfs_create_bool("dfs_block_radar_events", S_IWUSR, 822 ar->debug.debugfs_phy, 823 &ar->dfs_block_radar_events); 824 825 debugfs_create_file("dfs_stats", S_IRUSR, 826 ar->debug.debugfs_phy, ar, 827 &fops_dfs_stats); 828 } 829 830 return 0; 831 } 832 833 void ath10k_debug_destroy(struct ath10k *ar) 834 { 835 cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); 836 } 837 838 #endif /* CONFIG_ATH10K_DEBUGFS */ 839 840 #ifdef CONFIG_ATH10K_DEBUG 841 void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) 842 { 843 struct va_format vaf; 844 va_list args; 845 846 va_start(args, fmt); 847 848 vaf.fmt = fmt; 849 vaf.va = &args; 850 851 if (ath10k_debug_mask & mask) 852 ath10k_printk(KERN_DEBUG, "%pV", &vaf); 853 854 trace_ath10k_log_dbg(mask, &vaf); 855 856 va_end(args); 857 } 858 EXPORT_SYMBOL(ath10k_dbg); 859 860 void ath10k_dbg_dump(enum ath10k_debug_mask mask, 861 const char *msg, const char *prefix, 862 const void *buf, size_t len) 863 { 864 if (ath10k_debug_mask & mask) { 865 if (msg) 866 ath10k_dbg(mask, "%s\n", msg); 867 868 print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); 869 } 870 871 /* tracing code doesn't like null strings :/ */ 872 trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", 873 buf, len); 874 } 875 EXPORT_SYMBOL(ath10k_dbg_dump); 876 877 #endif /* CONFIG_ATH10K_DEBUG */ 878