1 /* 2 * Copyright (c) 2008-2009 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <asm/unaligned.h> 18 19 #include "ath9k.h" 20 21 #define REG_WRITE_D(_ah, _reg, _val) \ 22 ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) 23 #define REG_READ_D(_ah, _reg) \ 24 ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) 25 26 static struct dentry *ath9k_debugfs_root; 27 28 static int ath9k_debugfs_open(struct inode *inode, struct file *file) 29 { 30 file->private_data = inode->i_private; 31 return 0; 32 } 33 34 #ifdef CONFIG_ATH_DEBUG 35 36 static ssize_t read_file_debug(struct file *file, char __user *user_buf, 37 size_t count, loff_t *ppos) 38 { 39 struct ath_softc *sc = file->private_data; 40 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 41 char buf[32]; 42 unsigned int len; 43 44 len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask); 45 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 46 } 47 48 static ssize_t write_file_debug(struct file *file, const char __user *user_buf, 49 size_t count, loff_t *ppos) 50 { 51 struct ath_softc *sc = file->private_data; 52 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 53 unsigned long mask; 54 char buf[32]; 55 ssize_t len; 56 57 len = min(count, sizeof(buf) - 1); 58 if (copy_from_user(buf, user_buf, len)) 59 return -EINVAL; 60 61 buf[len] = '\0'; 62 if (strict_strtoul(buf, 0, &mask)) 63 return -EINVAL; 64 65 common->debug_mask = mask; 66 return count; 67 } 68 69 static const struct file_operations fops_debug = { 70 .read = read_file_debug, 71 .write = write_file_debug, 72 .open = ath9k_debugfs_open, 73 .owner = THIS_MODULE 74 }; 75 76 #endif 77 78 #define DMA_BUF_LEN 1024 79 80 static ssize_t read_file_dma(struct file *file, char __user *user_buf, 81 size_t count, loff_t *ppos) 82 { 83 struct ath_softc *sc = file->private_data; 84 struct ath_hw *ah = sc->sc_ah; 85 char *buf; 86 int retval; 87 unsigned int len = 0; 88 u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; 89 int i, qcuOffset = 0, dcuOffset = 0; 90 u32 *qcuBase = &val[0], *dcuBase = &val[4]; 91 92 buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL); 93 if (!buf) 94 return 0; 95 96 ath9k_ps_wakeup(sc); 97 98 REG_WRITE_D(ah, AR_MACMISC, 99 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | 100 (AR_MACMISC_MISC_OBS_BUS_1 << 101 AR_MACMISC_MISC_OBS_BUS_MSB_S))); 102 103 len += snprintf(buf + len, DMA_BUF_LEN - len, 104 "Raw DMA Debug values:\n"); 105 106 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { 107 if (i % 4 == 0) 108 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); 109 110 val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); 111 len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ", 112 i, val[i]); 113 } 114 115 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n"); 116 len += snprintf(buf + len, DMA_BUF_LEN - len, 117 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); 118 119 for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { 120 if (i == 8) { 121 qcuOffset = 0; 122 qcuBase++; 123 } 124 125 if (i == 6) { 126 dcuOffset = 0; 127 dcuBase++; 128 } 129 130 len += snprintf(buf + len, DMA_BUF_LEN - len, 131 "%2d %2x %1x %2x %2x\n", 132 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, 133 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), 134 val[2] & (0x7 << (i * 3)) >> (i * 3), 135 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); 136 } 137 138 len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); 139 140 len += snprintf(buf + len, DMA_BUF_LEN - len, 141 "qcu_stitch state: %2x qcu_fetch state: %2x\n", 142 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); 143 len += snprintf(buf + len, DMA_BUF_LEN - len, 144 "qcu_complete state: %2x dcu_complete state: %2x\n", 145 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); 146 len += snprintf(buf + len, DMA_BUF_LEN - len, 147 "dcu_arb state: %2x dcu_fp state: %2x\n", 148 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); 149 len += snprintf(buf + len, DMA_BUF_LEN - len, 150 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", 151 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); 152 len += snprintf(buf + len, DMA_BUF_LEN - len, 153 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", 154 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); 155 len += snprintf(buf + len, DMA_BUF_LEN - len, 156 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", 157 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); 158 159 len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n", 160 REG_READ_D(ah, AR_OBS_BUS_1)); 161 len += snprintf(buf + len, DMA_BUF_LEN - len, 162 "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); 163 164 ath9k_ps_restore(sc); 165 166 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 167 kfree(buf); 168 return retval; 169 } 170 171 static const struct file_operations fops_dma = { 172 .read = read_file_dma, 173 .open = ath9k_debugfs_open, 174 .owner = THIS_MODULE 175 }; 176 177 178 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) 179 { 180 if (status) 181 sc->debug.stats.istats.total++; 182 if (status & ATH9K_INT_RX) 183 sc->debug.stats.istats.rxok++; 184 if (status & ATH9K_INT_RXEOL) 185 sc->debug.stats.istats.rxeol++; 186 if (status & ATH9K_INT_RXORN) 187 sc->debug.stats.istats.rxorn++; 188 if (status & ATH9K_INT_TX) 189 sc->debug.stats.istats.txok++; 190 if (status & ATH9K_INT_TXURN) 191 sc->debug.stats.istats.txurn++; 192 if (status & ATH9K_INT_MIB) 193 sc->debug.stats.istats.mib++; 194 if (status & ATH9K_INT_RXPHY) 195 sc->debug.stats.istats.rxphyerr++; 196 if (status & ATH9K_INT_RXKCM) 197 sc->debug.stats.istats.rx_keycache_miss++; 198 if (status & ATH9K_INT_SWBA) 199 sc->debug.stats.istats.swba++; 200 if (status & ATH9K_INT_BMISS) 201 sc->debug.stats.istats.bmiss++; 202 if (status & ATH9K_INT_BNR) 203 sc->debug.stats.istats.bnr++; 204 if (status & ATH9K_INT_CST) 205 sc->debug.stats.istats.cst++; 206 if (status & ATH9K_INT_GTT) 207 sc->debug.stats.istats.gtt++; 208 if (status & ATH9K_INT_TIM) 209 sc->debug.stats.istats.tim++; 210 if (status & ATH9K_INT_CABEND) 211 sc->debug.stats.istats.cabend++; 212 if (status & ATH9K_INT_DTIMSYNC) 213 sc->debug.stats.istats.dtimsync++; 214 if (status & ATH9K_INT_DTIM) 215 sc->debug.stats.istats.dtim++; 216 } 217 218 static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, 219 size_t count, loff_t *ppos) 220 { 221 struct ath_softc *sc = file->private_data; 222 char buf[512]; 223 unsigned int len = 0; 224 225 len += snprintf(buf + len, sizeof(buf) - len, 226 "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); 227 len += snprintf(buf + len, sizeof(buf) - len, 228 "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); 229 len += snprintf(buf + len, sizeof(buf) - len, 230 "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); 231 len += snprintf(buf + len, sizeof(buf) - len, 232 "%8s: %10u\n", "TX", sc->debug.stats.istats.txok); 233 len += snprintf(buf + len, sizeof(buf) - len, 234 "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); 235 len += snprintf(buf + len, sizeof(buf) - len, 236 "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); 237 len += snprintf(buf + len, sizeof(buf) - len, 238 "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); 239 len += snprintf(buf + len, sizeof(buf) - len, 240 "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); 241 len += snprintf(buf + len, sizeof(buf) - len, 242 "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); 243 len += snprintf(buf + len, sizeof(buf) - len, 244 "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); 245 len += snprintf(buf + len, sizeof(buf) - len, 246 "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); 247 len += snprintf(buf + len, sizeof(buf) - len, 248 "%8s: %10u\n", "CST", sc->debug.stats.istats.cst); 249 len += snprintf(buf + len, sizeof(buf) - len, 250 "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); 251 len += snprintf(buf + len, sizeof(buf) - len, 252 "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); 253 len += snprintf(buf + len, sizeof(buf) - len, 254 "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); 255 len += snprintf(buf + len, sizeof(buf) - len, 256 "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); 257 len += snprintf(buf + len, sizeof(buf) - len, 258 "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); 259 len += snprintf(buf + len, sizeof(buf) - len, 260 "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); 261 262 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 263 } 264 265 static const struct file_operations fops_interrupt = { 266 .read = read_file_interrupt, 267 .open = ath9k_debugfs_open, 268 .owner = THIS_MODULE 269 }; 270 271 void ath_debug_stat_rc(struct ath_softc *sc, int final_rate) 272 { 273 struct ath_rc_stats *stats; 274 275 stats = &sc->debug.stats.rcstats[final_rate]; 276 stats->success++; 277 } 278 279 void ath_debug_stat_retries(struct ath_softc *sc, int rix, 280 int xretries, int retries, u8 per) 281 { 282 struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix]; 283 284 stats->xretries += xretries; 285 stats->retries += retries; 286 stats->per = per; 287 } 288 289 static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, 290 size_t count, loff_t *ppos) 291 { 292 struct ath_softc *sc = file->private_data; 293 char *buf; 294 unsigned int len = 0, max; 295 int i = 0; 296 ssize_t retval; 297 298 if (sc->cur_rate_table == NULL) 299 return 0; 300 301 max = 80 + sc->cur_rate_table->rate_cnt * 1024; 302 buf = kmalloc(max + 1, GFP_KERNEL); 303 if (buf == NULL) 304 return 0; 305 buf[max] = 0; 306 307 len += sprintf(buf, "%6s %6s %6s " 308 "%10s %10s %10s %10s\n", 309 "HT", "MCS", "Rate", 310 "Success", "Retries", "XRetries", "PER"); 311 312 for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { 313 u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; 314 struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; 315 char mcs[5]; 316 char htmode[5]; 317 int used_mcs = 0, used_htmode = 0; 318 319 if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { 320 used_mcs = snprintf(mcs, 5, "%d", 321 sc->cur_rate_table->info[i].ratecode); 322 323 if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) 324 used_htmode = snprintf(htmode, 5, "HT40"); 325 else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) 326 used_htmode = snprintf(htmode, 5, "HT20"); 327 else 328 used_htmode = snprintf(htmode, 5, "????"); 329 } 330 331 mcs[used_mcs] = '\0'; 332 htmode[used_htmode] = '\0'; 333 334 len += snprintf(buf + len, max - len, 335 "%6s %6s %3u.%d: " 336 "%10u %10u %10u %10u\n", 337 htmode, 338 mcs, 339 ratekbps / 1000, 340 (ratekbps % 1000) / 100, 341 stats->success, 342 stats->retries, 343 stats->xretries, 344 stats->per); 345 } 346 347 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 348 kfree(buf); 349 return retval; 350 } 351 352 static const struct file_operations fops_rcstat = { 353 .read = read_file_rcstat, 354 .open = ath9k_debugfs_open, 355 .owner = THIS_MODULE 356 }; 357 358 static const char * ath_wiphy_state_str(enum ath_wiphy_state state) 359 { 360 switch (state) { 361 case ATH_WIPHY_INACTIVE: 362 return "INACTIVE"; 363 case ATH_WIPHY_ACTIVE: 364 return "ACTIVE"; 365 case ATH_WIPHY_PAUSING: 366 return "PAUSING"; 367 case ATH_WIPHY_PAUSED: 368 return "PAUSED"; 369 case ATH_WIPHY_SCAN: 370 return "SCAN"; 371 } 372 return "?"; 373 } 374 375 static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, 376 size_t count, loff_t *ppos) 377 { 378 struct ath_softc *sc = file->private_data; 379 char buf[512]; 380 unsigned int len = 0; 381 int i; 382 u8 addr[ETH_ALEN]; 383 384 len += snprintf(buf + len, sizeof(buf) - len, 385 "primary: %s (%s chan=%d ht=%d)\n", 386 wiphy_name(sc->pri_wiphy->hw->wiphy), 387 ath_wiphy_state_str(sc->pri_wiphy->state), 388 sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); 389 for (i = 0; i < sc->num_sec_wiphy; i++) { 390 struct ath_wiphy *aphy = sc->sec_wiphy[i]; 391 if (aphy == NULL) 392 continue; 393 len += snprintf(buf + len, sizeof(buf) - len, 394 "secondary: %s (%s chan=%d ht=%d)\n", 395 wiphy_name(aphy->hw->wiphy), 396 ath_wiphy_state_str(aphy->state), 397 aphy->chan_idx, aphy->chan_is_ht); 398 } 399 400 put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); 401 put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); 402 len += snprintf(buf + len, sizeof(buf) - len, 403 "addr: %pM\n", addr); 404 put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); 405 put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); 406 len += snprintf(buf + len, sizeof(buf) - len, 407 "addrmask: %pM\n", addr); 408 409 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 410 } 411 412 static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) 413 { 414 int i; 415 if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) 416 return sc->pri_wiphy; 417 for (i = 0; i < sc->num_sec_wiphy; i++) { 418 struct ath_wiphy *aphy = sc->sec_wiphy[i]; 419 if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) 420 return aphy; 421 } 422 return NULL; 423 } 424 425 static int del_wiphy(struct ath_softc *sc, const char *name) 426 { 427 struct ath_wiphy *aphy = get_wiphy(sc, name); 428 if (!aphy) 429 return -ENOENT; 430 return ath9k_wiphy_del(aphy); 431 } 432 433 static int pause_wiphy(struct ath_softc *sc, const char *name) 434 { 435 struct ath_wiphy *aphy = get_wiphy(sc, name); 436 if (!aphy) 437 return -ENOENT; 438 return ath9k_wiphy_pause(aphy); 439 } 440 441 static int unpause_wiphy(struct ath_softc *sc, const char *name) 442 { 443 struct ath_wiphy *aphy = get_wiphy(sc, name); 444 if (!aphy) 445 return -ENOENT; 446 return ath9k_wiphy_unpause(aphy); 447 } 448 449 static int select_wiphy(struct ath_softc *sc, const char *name) 450 { 451 struct ath_wiphy *aphy = get_wiphy(sc, name); 452 if (!aphy) 453 return -ENOENT; 454 return ath9k_wiphy_select(aphy); 455 } 456 457 static int schedule_wiphy(struct ath_softc *sc, const char *msec) 458 { 459 ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); 460 return 0; 461 } 462 463 static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, 464 size_t count, loff_t *ppos) 465 { 466 struct ath_softc *sc = file->private_data; 467 char buf[50]; 468 size_t len; 469 470 len = min(count, sizeof(buf) - 1); 471 if (copy_from_user(buf, user_buf, len)) 472 return -EFAULT; 473 buf[len] = '\0'; 474 if (len > 0 && buf[len - 1] == '\n') 475 buf[len - 1] = '\0'; 476 477 if (strncmp(buf, "add", 3) == 0) { 478 int res = ath9k_wiphy_add(sc); 479 if (res < 0) 480 return res; 481 } else if (strncmp(buf, "del=", 4) == 0) { 482 int res = del_wiphy(sc, buf + 4); 483 if (res < 0) 484 return res; 485 } else if (strncmp(buf, "pause=", 6) == 0) { 486 int res = pause_wiphy(sc, buf + 6); 487 if (res < 0) 488 return res; 489 } else if (strncmp(buf, "unpause=", 8) == 0) { 490 int res = unpause_wiphy(sc, buf + 8); 491 if (res < 0) 492 return res; 493 } else if (strncmp(buf, "select=", 7) == 0) { 494 int res = select_wiphy(sc, buf + 7); 495 if (res < 0) 496 return res; 497 } else if (strncmp(buf, "schedule=", 9) == 0) { 498 int res = schedule_wiphy(sc, buf + 9); 499 if (res < 0) 500 return res; 501 } else 502 return -EOPNOTSUPP; 503 504 return count; 505 } 506 507 static const struct file_operations fops_wiphy = { 508 .read = read_file_wiphy, 509 .write = write_file_wiphy, 510 .open = ath9k_debugfs_open, 511 .owner = THIS_MODULE 512 }; 513 514 #define PR(str, elem) \ 515 do { \ 516 len += snprintf(buf + len, size - len, \ 517 "%s%13u%11u%10u%10u\n", str, \ 518 sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \ 519 sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \ 520 sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \ 521 sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \ 522 } while(0) 523 524 static ssize_t read_file_xmit(struct file *file, char __user *user_buf, 525 size_t count, loff_t *ppos) 526 { 527 struct ath_softc *sc = file->private_data; 528 char *buf; 529 unsigned int len = 0, size = 2048; 530 ssize_t retval = 0; 531 532 buf = kzalloc(size, GFP_KERNEL); 533 if (buf == NULL) 534 return 0; 535 536 len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); 537 538 PR("MPDUs Queued: ", queued); 539 PR("MPDUs Completed: ", completed); 540 PR("Aggregates: ", a_aggr); 541 PR("AMPDUs Queued: ", a_queued); 542 PR("AMPDUs Completed:", a_completed); 543 PR("AMPDUs Retried: ", a_retries); 544 PR("AMPDUs XRetried: ", a_xretries); 545 PR("FIFO Underrun: ", fifo_underrun); 546 PR("TXOP Exceeded: ", xtxop); 547 PR("TXTIMER Expiry: ", timer_exp); 548 PR("DESC CFG Error: ", desc_cfg_err); 549 PR("DATA Underrun: ", data_underrun); 550 PR("DELIM Underrun: ", delim_underrun); 551 552 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 553 kfree(buf); 554 555 return retval; 556 } 557 558 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, 559 struct ath_buf *bf) 560 { 561 struct ath_desc *ds = bf->bf_desc; 562 563 if (bf_isampdu(bf)) { 564 if (bf_isxretried(bf)) 565 TX_STAT_INC(txq->axq_qnum, a_xretries); 566 else 567 TX_STAT_INC(txq->axq_qnum, a_completed); 568 } else { 569 TX_STAT_INC(txq->axq_qnum, completed); 570 } 571 572 if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO) 573 TX_STAT_INC(txq->axq_qnum, fifo_underrun); 574 if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP) 575 TX_STAT_INC(txq->axq_qnum, xtxop); 576 if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED) 577 TX_STAT_INC(txq->axq_qnum, timer_exp); 578 if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR) 579 TX_STAT_INC(txq->axq_qnum, desc_cfg_err); 580 if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN) 581 TX_STAT_INC(txq->axq_qnum, data_underrun); 582 if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN) 583 TX_STAT_INC(txq->axq_qnum, delim_underrun); 584 } 585 586 static const struct file_operations fops_xmit = { 587 .read = read_file_xmit, 588 .open = ath9k_debugfs_open, 589 .owner = THIS_MODULE 590 }; 591 592 static ssize_t read_file_recv(struct file *file, char __user *user_buf, 593 size_t count, loff_t *ppos) 594 { 595 #define PHY_ERR(s, p) \ 596 len += snprintf(buf + len, size - len, "%18s : %10u\n", s, \ 597 sc->debug.stats.rxstats.phy_err_stats[p]); 598 599 struct ath_softc *sc = file->private_data; 600 char *buf; 601 unsigned int len = 0, size = 1152; 602 ssize_t retval = 0; 603 604 buf = kzalloc(size, GFP_KERNEL); 605 if (buf == NULL) 606 return 0; 607 608 len += snprintf(buf + len, size - len, 609 "%18s : %10u\n", "CRC ERR", 610 sc->debug.stats.rxstats.crc_err); 611 len += snprintf(buf + len, size - len, 612 "%18s : %10u\n", "DECRYPT CRC ERR", 613 sc->debug.stats.rxstats.decrypt_crc_err); 614 len += snprintf(buf + len, size - len, 615 "%18s : %10u\n", "PHY ERR", 616 sc->debug.stats.rxstats.phy_err); 617 len += snprintf(buf + len, size - len, 618 "%18s : %10u\n", "MIC ERR", 619 sc->debug.stats.rxstats.mic_err); 620 len += snprintf(buf + len, size - len, 621 "%18s : %10u\n", "PRE-DELIM CRC ERR", 622 sc->debug.stats.rxstats.pre_delim_crc_err); 623 len += snprintf(buf + len, size - len, 624 "%18s : %10u\n", "POST-DELIM CRC ERR", 625 sc->debug.stats.rxstats.post_delim_crc_err); 626 len += snprintf(buf + len, size - len, 627 "%18s : %10u\n", "DECRYPT BUSY ERR", 628 sc->debug.stats.rxstats.decrypt_busy_err); 629 630 PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); 631 PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); 632 PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); 633 PHY_ERR("RATE", ATH9K_PHYERR_RATE); 634 PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); 635 PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); 636 PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); 637 PHY_ERR("TOR", ATH9K_PHYERR_TOR); 638 PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); 639 PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); 640 PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); 641 PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); 642 PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); 643 PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); 644 PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); 645 PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); 646 PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); 647 PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); 648 PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); 649 PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); 650 PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); 651 PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); 652 PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); 653 PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); 654 PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); 655 PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); 656 657 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 658 kfree(buf); 659 660 return retval; 661 662 #undef PHY_ERR 663 } 664 665 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) 666 { 667 #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ 668 #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ 669 670 struct ath_desc *ds = bf->bf_desc; 671 u32 phyerr; 672 673 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) 674 RX_STAT_INC(crc_err); 675 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) 676 RX_STAT_INC(decrypt_crc_err); 677 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) 678 RX_STAT_INC(mic_err); 679 if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) 680 RX_STAT_INC(pre_delim_crc_err); 681 if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) 682 RX_STAT_INC(post_delim_crc_err); 683 if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) 684 RX_STAT_INC(decrypt_busy_err); 685 686 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { 687 RX_STAT_INC(phy_err); 688 phyerr = ds->ds_rxstat.rs_phyerr & 0x24; 689 RX_PHY_ERR_INC(phyerr); 690 } 691 692 #undef RX_STAT_INC 693 #undef RX_PHY_ERR_INC 694 } 695 696 static const struct file_operations fops_recv = { 697 .read = read_file_recv, 698 .open = ath9k_debugfs_open, 699 .owner = THIS_MODULE 700 }; 701 702 int ath9k_init_debug(struct ath_hw *ah) 703 { 704 struct ath_common *common = ath9k_hw_common(ah); 705 struct ath_softc *sc = (struct ath_softc *) common->priv; 706 707 if (!ath9k_debugfs_root) 708 return -ENOENT; 709 710 sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), 711 ath9k_debugfs_root); 712 if (!sc->debug.debugfs_phy) 713 goto err; 714 715 #ifdef CONFIG_ATH_DEBUG 716 sc->debug.debugfs_debug = debugfs_create_file("debug", 717 S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); 718 if (!sc->debug.debugfs_debug) 719 goto err; 720 #endif 721 722 sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, 723 sc->debug.debugfs_phy, sc, &fops_dma); 724 if (!sc->debug.debugfs_dma) 725 goto err; 726 727 sc->debug.debugfs_interrupt = debugfs_create_file("interrupt", 728 S_IRUSR, 729 sc->debug.debugfs_phy, 730 sc, &fops_interrupt); 731 if (!sc->debug.debugfs_interrupt) 732 goto err; 733 734 sc->debug.debugfs_rcstat = debugfs_create_file("rcstat", 735 S_IRUSR, 736 sc->debug.debugfs_phy, 737 sc, &fops_rcstat); 738 if (!sc->debug.debugfs_rcstat) 739 goto err; 740 741 sc->debug.debugfs_wiphy = debugfs_create_file( 742 "wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, 743 &fops_wiphy); 744 if (!sc->debug.debugfs_wiphy) 745 goto err; 746 747 sc->debug.debugfs_xmit = debugfs_create_file("xmit", 748 S_IRUSR, 749 sc->debug.debugfs_phy, 750 sc, &fops_xmit); 751 if (!sc->debug.debugfs_xmit) 752 goto err; 753 754 sc->debug.debugfs_recv = debugfs_create_file("recv", 755 S_IRUSR, 756 sc->debug.debugfs_phy, 757 sc, &fops_recv); 758 if (!sc->debug.debugfs_recv) 759 goto err; 760 761 return 0; 762 err: 763 ath9k_exit_debug(ah); 764 return -ENOMEM; 765 } 766 767 void ath9k_exit_debug(struct ath_hw *ah) 768 { 769 struct ath_common *common = ath9k_hw_common(ah); 770 struct ath_softc *sc = (struct ath_softc *) common->priv; 771 772 debugfs_remove(sc->debug.debugfs_recv); 773 debugfs_remove(sc->debug.debugfs_xmit); 774 debugfs_remove(sc->debug.debugfs_wiphy); 775 debugfs_remove(sc->debug.debugfs_rcstat); 776 debugfs_remove(sc->debug.debugfs_interrupt); 777 debugfs_remove(sc->debug.debugfs_dma); 778 debugfs_remove(sc->debug.debugfs_debug); 779 debugfs_remove(sc->debug.debugfs_phy); 780 } 781 782 int ath9k_debug_create_root(void) 783 { 784 ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); 785 if (!ath9k_debugfs_root) 786 return -ENOENT; 787 788 return 0; 789 } 790 791 void ath9k_debug_remove_root(void) 792 { 793 debugfs_remove(ath9k_debugfs_root); 794 ath9k_debugfs_root = NULL; 795 } 796