1 /****************************************************************************** 2 * 3 * GPL LICENSE SUMMARY 4 * 5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of version 2 of the GNU General Public License as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 19 * USA 20 * 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * Contact Information: 25 * Intel Linux Wireless <ilw@linux.intel.com> 26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 27 *****************************************************************************/ 28 #include <linux/ieee80211.h> 29 #include <linux/export.h> 30 #include <net/mac80211.h> 31 32 #include "common.h" 33 34 static void 35 il_clear_traffic_stats(struct il_priv *il) 36 { 37 memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); 38 memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); 39 } 40 41 /* 42 * il_update_stats function record all the MGMT, CTRL and DATA pkt for 43 * both TX and Rx . Use debugfs to display the rx/rx_stats 44 */ 45 void 46 il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) 47 { 48 struct traffic_stats *stats; 49 50 if (is_tx) 51 stats = &il->tx_stats; 52 else 53 stats = &il->rx_stats; 54 55 if (ieee80211_is_mgmt(fc)) { 56 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 57 case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): 58 stats->mgmt[MANAGEMENT_ASSOC_REQ]++; 59 break; 60 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): 61 stats->mgmt[MANAGEMENT_ASSOC_RESP]++; 62 break; 63 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): 64 stats->mgmt[MANAGEMENT_REASSOC_REQ]++; 65 break; 66 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): 67 stats->mgmt[MANAGEMENT_REASSOC_RESP]++; 68 break; 69 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): 70 stats->mgmt[MANAGEMENT_PROBE_REQ]++; 71 break; 72 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): 73 stats->mgmt[MANAGEMENT_PROBE_RESP]++; 74 break; 75 case cpu_to_le16(IEEE80211_STYPE_BEACON): 76 stats->mgmt[MANAGEMENT_BEACON]++; 77 break; 78 case cpu_to_le16(IEEE80211_STYPE_ATIM): 79 stats->mgmt[MANAGEMENT_ATIM]++; 80 break; 81 case cpu_to_le16(IEEE80211_STYPE_DISASSOC): 82 stats->mgmt[MANAGEMENT_DISASSOC]++; 83 break; 84 case cpu_to_le16(IEEE80211_STYPE_AUTH): 85 stats->mgmt[MANAGEMENT_AUTH]++; 86 break; 87 case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 88 stats->mgmt[MANAGEMENT_DEAUTH]++; 89 break; 90 case cpu_to_le16(IEEE80211_STYPE_ACTION): 91 stats->mgmt[MANAGEMENT_ACTION]++; 92 break; 93 } 94 } else if (ieee80211_is_ctl(fc)) { 95 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 96 case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): 97 stats->ctrl[CONTROL_BACK_REQ]++; 98 break; 99 case cpu_to_le16(IEEE80211_STYPE_BACK): 100 stats->ctrl[CONTROL_BACK]++; 101 break; 102 case cpu_to_le16(IEEE80211_STYPE_PSPOLL): 103 stats->ctrl[CONTROL_PSPOLL]++; 104 break; 105 case cpu_to_le16(IEEE80211_STYPE_RTS): 106 stats->ctrl[CONTROL_RTS]++; 107 break; 108 case cpu_to_le16(IEEE80211_STYPE_CTS): 109 stats->ctrl[CONTROL_CTS]++; 110 break; 111 case cpu_to_le16(IEEE80211_STYPE_ACK): 112 stats->ctrl[CONTROL_ACK]++; 113 break; 114 case cpu_to_le16(IEEE80211_STYPE_CFEND): 115 stats->ctrl[CONTROL_CFEND]++; 116 break; 117 case cpu_to_le16(IEEE80211_STYPE_CFENDACK): 118 stats->ctrl[CONTROL_CFENDACK]++; 119 break; 120 } 121 } else { 122 /* data */ 123 stats->data_cnt++; 124 stats->data_bytes += len; 125 } 126 } 127 EXPORT_SYMBOL(il_update_stats); 128 129 /* create and remove of files */ 130 #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 131 if (!debugfs_create_file(#name, mode, parent, il, \ 132 &il_dbgfs_##name##_ops)) \ 133 goto err; \ 134 } while (0) 135 136 #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 137 struct dentry *__tmp; \ 138 __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ 139 parent, ptr); \ 140 if (IS_ERR(__tmp) || !__tmp) \ 141 goto err; \ 142 } while (0) 143 144 #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ 145 struct dentry *__tmp; \ 146 __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ 147 parent, ptr); \ 148 if (IS_ERR(__tmp) || !__tmp) \ 149 goto err; \ 150 } while (0) 151 152 /* file operation */ 153 #define DEBUGFS_READ_FUNC(name) \ 154 static ssize_t il_dbgfs_##name##_read(struct file *file, \ 155 char __user *user_buf, \ 156 size_t count, loff_t *ppos); 157 158 #define DEBUGFS_WRITE_FUNC(name) \ 159 static ssize_t il_dbgfs_##name##_write(struct file *file, \ 160 const char __user *user_buf, \ 161 size_t count, loff_t *ppos); 162 163 164 #define DEBUGFS_READ_FILE_OPS(name) \ 165 DEBUGFS_READ_FUNC(name); \ 166 static const struct file_operations il_dbgfs_##name##_ops = { \ 167 .read = il_dbgfs_##name##_read, \ 168 .open = simple_open, \ 169 .llseek = generic_file_llseek, \ 170 }; 171 172 #define DEBUGFS_WRITE_FILE_OPS(name) \ 173 DEBUGFS_WRITE_FUNC(name); \ 174 static const struct file_operations il_dbgfs_##name##_ops = { \ 175 .write = il_dbgfs_##name##_write, \ 176 .open = simple_open, \ 177 .llseek = generic_file_llseek, \ 178 }; 179 180 #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 181 DEBUGFS_READ_FUNC(name); \ 182 DEBUGFS_WRITE_FUNC(name); \ 183 static const struct file_operations il_dbgfs_##name##_ops = { \ 184 .write = il_dbgfs_##name##_write, \ 185 .read = il_dbgfs_##name##_read, \ 186 .open = simple_open, \ 187 .llseek = generic_file_llseek, \ 188 }; 189 190 static const char * 191 il_get_mgmt_string(int cmd) 192 { 193 switch (cmd) { 194 IL_CMD(MANAGEMENT_ASSOC_REQ); 195 IL_CMD(MANAGEMENT_ASSOC_RESP); 196 IL_CMD(MANAGEMENT_REASSOC_REQ); 197 IL_CMD(MANAGEMENT_REASSOC_RESP); 198 IL_CMD(MANAGEMENT_PROBE_REQ); 199 IL_CMD(MANAGEMENT_PROBE_RESP); 200 IL_CMD(MANAGEMENT_BEACON); 201 IL_CMD(MANAGEMENT_ATIM); 202 IL_CMD(MANAGEMENT_DISASSOC); 203 IL_CMD(MANAGEMENT_AUTH); 204 IL_CMD(MANAGEMENT_DEAUTH); 205 IL_CMD(MANAGEMENT_ACTION); 206 default: 207 return "UNKNOWN"; 208 209 } 210 } 211 212 static const char * 213 il_get_ctrl_string(int cmd) 214 { 215 switch (cmd) { 216 IL_CMD(CONTROL_BACK_REQ); 217 IL_CMD(CONTROL_BACK); 218 IL_CMD(CONTROL_PSPOLL); 219 IL_CMD(CONTROL_RTS); 220 IL_CMD(CONTROL_CTS); 221 IL_CMD(CONTROL_ACK); 222 IL_CMD(CONTROL_CFEND); 223 IL_CMD(CONTROL_CFENDACK); 224 default: 225 return "UNKNOWN"; 226 227 } 228 } 229 230 static ssize_t 231 il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count, 232 loff_t *ppos) 233 { 234 235 struct il_priv *il = file->private_data; 236 char *buf; 237 int pos = 0; 238 239 int cnt; 240 ssize_t ret; 241 const size_t bufsz = 242 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 243 buf = kzalloc(bufsz, GFP_KERNEL); 244 if (!buf) 245 return -ENOMEM; 246 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 247 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 248 pos += 249 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 250 il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]); 251 } 252 pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); 253 for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 254 pos += 255 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 256 il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]); 257 } 258 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 259 pos += 260 scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 261 il->tx_stats.data_cnt); 262 pos += 263 scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 264 il->tx_stats.data_bytes); 265 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 266 kfree(buf); 267 return ret; 268 } 269 270 static ssize_t 271 il_dbgfs_clear_traffic_stats_write(struct file *file, 272 const char __user *user_buf, size_t count, 273 loff_t *ppos) 274 { 275 struct il_priv *il = file->private_data; 276 u32 clear_flag; 277 char buf[8]; 278 int buf_size; 279 280 memset(buf, 0, sizeof(buf)); 281 buf_size = min(count, sizeof(buf) - 1); 282 if (copy_from_user(buf, user_buf, buf_size)) 283 return -EFAULT; 284 if (sscanf(buf, "%x", &clear_flag) != 1) 285 return -EFAULT; 286 il_clear_traffic_stats(il); 287 288 return count; 289 } 290 291 static ssize_t 292 il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count, 293 loff_t *ppos) 294 { 295 296 struct il_priv *il = file->private_data; 297 char *buf; 298 int pos = 0; 299 int cnt; 300 ssize_t ret; 301 const size_t bufsz = 302 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 303 buf = kzalloc(bufsz, GFP_KERNEL); 304 if (!buf) 305 return -ENOMEM; 306 307 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 308 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 309 pos += 310 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 311 il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]); 312 } 313 pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); 314 for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 315 pos += 316 scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 317 il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]); 318 } 319 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 320 pos += 321 scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 322 il->rx_stats.data_cnt); 323 pos += 324 scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 325 il->rx_stats.data_bytes); 326 327 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 328 kfree(buf); 329 return ret; 330 } 331 332 #define BYTE1_MASK 0x000000ff; 333 #define BYTE2_MASK 0x0000ffff; 334 #define BYTE3_MASK 0x00ffffff; 335 static ssize_t 336 il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count, 337 loff_t *ppos) 338 { 339 u32 val; 340 char *buf; 341 ssize_t ret; 342 int i; 343 int pos = 0; 344 struct il_priv *il = file->private_data; 345 size_t bufsz; 346 347 /* default is to dump the entire data segment */ 348 if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) { 349 il->dbgfs_sram_offset = 0x800000; 350 if (il->ucode_type == UCODE_INIT) 351 il->dbgfs_sram_len = il->ucode_init_data.len; 352 else 353 il->dbgfs_sram_len = il->ucode_data.len; 354 } 355 bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10; 356 buf = kmalloc(bufsz, GFP_KERNEL); 357 if (!buf) 358 return -ENOMEM; 359 pos += 360 scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", 361 il->dbgfs_sram_len); 362 pos += 363 scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", 364 il->dbgfs_sram_offset); 365 for (i = il->dbgfs_sram_len; i > 0; i -= 4) { 366 val = 367 il_read_targ_mem(il, 368 il->dbgfs_sram_offset + 369 il->dbgfs_sram_len - i); 370 if (i < 4) { 371 switch (i) { 372 case 1: 373 val &= BYTE1_MASK; 374 break; 375 case 2: 376 val &= BYTE2_MASK; 377 break; 378 case 3: 379 val &= BYTE3_MASK; 380 break; 381 } 382 } 383 if (!(i % 16)) 384 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 385 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); 386 } 387 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 388 389 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 390 kfree(buf); 391 return ret; 392 } 393 394 static ssize_t 395 il_dbgfs_sram_write(struct file *file, const char __user *user_buf, 396 size_t count, loff_t *ppos) 397 { 398 struct il_priv *il = file->private_data; 399 char buf[64]; 400 int buf_size; 401 u32 offset, len; 402 403 memset(buf, 0, sizeof(buf)); 404 buf_size = min(count, sizeof(buf) - 1); 405 if (copy_from_user(buf, user_buf, buf_size)) 406 return -EFAULT; 407 408 if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 409 il->dbgfs_sram_offset = offset; 410 il->dbgfs_sram_len = len; 411 } else { 412 il->dbgfs_sram_offset = 0; 413 il->dbgfs_sram_len = 0; 414 } 415 416 return count; 417 } 418 419 static ssize_t 420 il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, 421 loff_t *ppos) 422 { 423 struct il_priv *il = file->private_data; 424 struct il_station_entry *station; 425 int max_sta = il->hw_params.max_stations; 426 char *buf; 427 int i, j, pos = 0; 428 ssize_t ret; 429 /* Add 30 for initial string */ 430 const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations); 431 432 buf = kmalloc(bufsz, GFP_KERNEL); 433 if (!buf) 434 return -ENOMEM; 435 436 pos += 437 scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", 438 il->num_stations); 439 440 for (i = 0; i < max_sta; i++) { 441 station = &il->stations[i]; 442 if (!station->used) 443 continue; 444 pos += 445 scnprintf(buf + pos, bufsz - pos, 446 "station %d - addr: %pM, flags: %#x\n", i, 447 station->sta.sta.addr, 448 station->sta.station_flags_msk); 449 pos += 450 scnprintf(buf + pos, bufsz - pos, 451 "TID\tseq_num\ttxq_id\tframes\ttfds\t"); 452 pos += 453 scnprintf(buf + pos, bufsz - pos, 454 "start_idx\tbitmap\t\t\trate_n_flags\n"); 455 456 for (j = 0; j < MAX_TID_COUNT; j++) { 457 pos += 458 scnprintf(buf + pos, bufsz - pos, 459 "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", 460 j, station->tid[j].seq_number, 461 station->tid[j].agg.txq_id, 462 station->tid[j].agg.frame_count, 463 station->tid[j].tfds_in_queue, 464 station->tid[j].agg.start_idx, 465 station->tid[j].agg.bitmap, 466 station->tid[j].agg.rate_n_flags); 467 468 if (station->tid[j].agg.wait_for_ba) 469 pos += 470 scnprintf(buf + pos, bufsz - pos, 471 " - waitforba"); 472 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 473 } 474 475 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 476 } 477 478 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 479 kfree(buf); 480 return ret; 481 } 482 483 static ssize_t 484 il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, 485 loff_t *ppos) 486 { 487 ssize_t ret; 488 struct il_priv *il = file->private_data; 489 int pos = 0, ofs = 0, buf_size = 0; 490 const u8 *ptr; 491 char *buf; 492 u16 eeprom_ver; 493 size_t eeprom_len = il->cfg->eeprom_size; 494 buf_size = 4 * eeprom_len + 256; 495 496 if (eeprom_len % 16) { 497 IL_ERR("NVM size is not multiple of 16.\n"); 498 return -ENODATA; 499 } 500 501 ptr = il->eeprom; 502 if (!ptr) { 503 IL_ERR("Invalid EEPROM memory\n"); 504 return -ENOMEM; 505 } 506 507 /* 4 characters for byte 0xYY */ 508 buf = kzalloc(buf_size, GFP_KERNEL); 509 if (!buf) { 510 IL_ERR("Can not allocate Buffer\n"); 511 return -ENOMEM; 512 } 513 eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION); 514 pos += 515 scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n", 516 eeprom_ver); 517 for (ofs = 0; ofs < eeprom_len; ofs += 16) { 518 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n", 519 ofs, ptr + ofs); 520 } 521 522 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 523 kfree(buf); 524 return ret; 525 } 526 527 static ssize_t 528 il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, 529 loff_t *ppos) 530 { 531 struct il_priv *il = file->private_data; 532 struct ieee80211_channel *channels = NULL; 533 const struct ieee80211_supported_band *supp_band = NULL; 534 int pos = 0, i, bufsz = PAGE_SIZE; 535 char *buf; 536 ssize_t ret; 537 538 if (!test_bit(S_GEO_CONFIGURED, &il->status)) 539 return -EAGAIN; 540 541 buf = kzalloc(bufsz, GFP_KERNEL); 542 if (!buf) { 543 IL_ERR("Can not allocate Buffer\n"); 544 return -ENOMEM; 545 } 546 547 supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); 548 if (supp_band) { 549 channels = supp_band->channels; 550 551 pos += 552 scnprintf(buf + pos, bufsz - pos, 553 "Displaying %d channels in 2.4GHz band 802.11bg):\n", 554 supp_band->n_channels); 555 556 for (i = 0; i < supp_band->n_channels; i++) 557 pos += 558 scnprintf(buf + pos, bufsz - pos, 559 "%d: %ddBm: BSS%s%s, %s.\n", 560 channels[i].hw_value, 561 channels[i].max_power, 562 channels[i]. 563 flags & IEEE80211_CHAN_RADAR ? 564 " (IEEE 802.11h required)" : "", 565 ((channels[i]. 566 flags & IEEE80211_CHAN_NO_IR) || 567 (channels[i]. 568 flags & IEEE80211_CHAN_RADAR)) ? "" : 569 ", IBSS", 570 channels[i]. 571 flags & IEEE80211_CHAN_NO_IR ? 572 "passive only" : "active/passive"); 573 } 574 supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); 575 if (supp_band) { 576 channels = supp_band->channels; 577 578 pos += 579 scnprintf(buf + pos, bufsz - pos, 580 "Displaying %d channels in 5.2GHz band (802.11a)\n", 581 supp_band->n_channels); 582 583 for (i = 0; i < supp_band->n_channels; i++) 584 pos += 585 scnprintf(buf + pos, bufsz - pos, 586 "%d: %ddBm: BSS%s%s, %s.\n", 587 channels[i].hw_value, 588 channels[i].max_power, 589 channels[i]. 590 flags & IEEE80211_CHAN_RADAR ? 591 " (IEEE 802.11h required)" : "", 592 ((channels[i]. 593 flags & IEEE80211_CHAN_NO_IR) || 594 (channels[i]. 595 flags & IEEE80211_CHAN_RADAR)) ? "" : 596 ", IBSS", 597 channels[i]. 598 flags & IEEE80211_CHAN_NO_IR ? 599 "passive only" : "active/passive"); 600 } 601 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 602 kfree(buf); 603 return ret; 604 } 605 606 static ssize_t 607 il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, 608 loff_t *ppos) 609 { 610 611 struct il_priv *il = file->private_data; 612 char buf[512]; 613 int pos = 0; 614 const size_t bufsz = sizeof(buf); 615 616 pos += 617 scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n", 618 test_bit(S_HCMD_ACTIVE, &il->status)); 619 pos += 620 scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", 621 test_bit(S_INT_ENABLED, &il->status)); 622 pos += 623 scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n", 624 test_bit(S_RFKILL, &il->status)); 625 pos += 626 scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", 627 test_bit(S_CT_KILL, &il->status)); 628 pos += 629 scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n", 630 test_bit(S_INIT, &il->status)); 631 pos += 632 scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n", 633 test_bit(S_ALIVE, &il->status)); 634 pos += 635 scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n", 636 test_bit(S_READY, &il->status)); 637 pos += 638 scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n", 639 test_bit(S_TEMPERATURE, &il->status)); 640 pos += 641 scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n", 642 test_bit(S_GEO_CONFIGURED, &il->status)); 643 pos += 644 scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n", 645 test_bit(S_EXIT_PENDING, &il->status)); 646 pos += 647 scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n", 648 test_bit(S_STATS, &il->status)); 649 pos += 650 scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n", 651 test_bit(S_SCANNING, &il->status)); 652 pos += 653 scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n", 654 test_bit(S_SCAN_ABORTING, &il->status)); 655 pos += 656 scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n", 657 test_bit(S_SCAN_HW, &il->status)); 658 pos += 659 scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n", 660 test_bit(S_POWER_PMI, &il->status)); 661 pos += 662 scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n", 663 test_bit(S_FW_ERROR, &il->status)); 664 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 665 } 666 667 static ssize_t 668 il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, 669 loff_t *ppos) 670 { 671 672 struct il_priv *il = file->private_data; 673 int pos = 0; 674 int cnt = 0; 675 char *buf; 676 int bufsz = 24 * 64; /* 24 items * 64 char per item */ 677 ssize_t ret; 678 679 buf = kzalloc(bufsz, GFP_KERNEL); 680 if (!buf) { 681 IL_ERR("Can not allocate Buffer\n"); 682 return -ENOMEM; 683 } 684 685 pos += 686 scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n"); 687 688 pos += 689 scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 690 il->isr_stats.hw); 691 pos += 692 scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 693 il->isr_stats.sw); 694 if (il->isr_stats.sw || il->isr_stats.hw) { 695 pos += 696 scnprintf(buf + pos, bufsz - pos, 697 "\tLast Restarting Code: 0x%X\n", 698 il->isr_stats.err_code); 699 } 700 #ifdef CONFIG_IWLEGACY_DEBUG 701 pos += 702 scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 703 il->isr_stats.sch); 704 pos += 705 scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 706 il->isr_stats.alive); 707 #endif 708 pos += 709 scnprintf(buf + pos, bufsz - pos, 710 "HW RF KILL switch toggled:\t %u\n", 711 il->isr_stats.rfkill); 712 713 pos += 714 scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 715 il->isr_stats.ctkill); 716 717 pos += 718 scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 719 il->isr_stats.wakeup); 720 721 pos += 722 scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n", 723 il->isr_stats.rx); 724 for (cnt = 0; cnt < IL_CN_MAX; cnt++) { 725 if (il->isr_stats.handlers[cnt] > 0) 726 pos += 727 scnprintf(buf + pos, bufsz - pos, 728 "\tRx handler[%36s]:\t\t %u\n", 729 il_get_cmd_string(cnt), 730 il->isr_stats.handlers[cnt]); 731 } 732 733 pos += 734 scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 735 il->isr_stats.tx); 736 737 pos += 738 scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 739 il->isr_stats.unhandled); 740 741 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 742 kfree(buf); 743 return ret; 744 } 745 746 static ssize_t 747 il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, 748 size_t count, loff_t *ppos) 749 { 750 struct il_priv *il = file->private_data; 751 char buf[8]; 752 int buf_size; 753 u32 reset_flag; 754 755 memset(buf, 0, sizeof(buf)); 756 buf_size = min(count, sizeof(buf) - 1); 757 if (copy_from_user(buf, user_buf, buf_size)) 758 return -EFAULT; 759 if (sscanf(buf, "%x", &reset_flag) != 1) 760 return -EFAULT; 761 if (reset_flag == 0) 762 il_clear_isr_stats(il); 763 764 return count; 765 } 766 767 static ssize_t 768 il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, 769 loff_t *ppos) 770 { 771 struct il_priv *il = file->private_data; 772 int pos = 0, i; 773 char buf[256]; 774 const size_t bufsz = sizeof(buf); 775 776 for (i = 0; i < AC_NUM; i++) { 777 pos += 778 scnprintf(buf + pos, bufsz - pos, 779 "\tcw_min\tcw_max\taifsn\ttxop\n"); 780 pos += 781 scnprintf(buf + pos, bufsz - pos, 782 "AC[%d]\t%u\t%u\t%u\t%u\n", i, 783 il->qos_data.def_qos_parm.ac[i].cw_min, 784 il->qos_data.def_qos_parm.ac[i].cw_max, 785 il->qos_data.def_qos_parm.ac[i].aifsn, 786 il->qos_data.def_qos_parm.ac[i].edca_txop); 787 } 788 789 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 790 } 791 792 static ssize_t 793 il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf, 794 size_t count, loff_t *ppos) 795 { 796 struct il_priv *il = file->private_data; 797 char buf[8]; 798 int buf_size; 799 int ht40; 800 801 memset(buf, 0, sizeof(buf)); 802 buf_size = min(count, sizeof(buf) - 1); 803 if (copy_from_user(buf, user_buf, buf_size)) 804 return -EFAULT; 805 if (sscanf(buf, "%d", &ht40) != 1) 806 return -EFAULT; 807 if (!il_is_any_associated(il)) 808 il->disable_ht40 = ht40 ? true : false; 809 else { 810 IL_ERR("Sta associated with AP - " 811 "Change to 40MHz channel support is not allowed\n"); 812 return -EINVAL; 813 } 814 815 return count; 816 } 817 818 static ssize_t 819 il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf, 820 size_t count, loff_t *ppos) 821 { 822 struct il_priv *il = file->private_data; 823 char buf[100]; 824 int pos = 0; 825 const size_t bufsz = sizeof(buf); 826 827 pos += 828 scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n", 829 il->disable_ht40 ? "Disabled" : "Enabled"); 830 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 831 } 832 833 DEBUGFS_READ_WRITE_FILE_OPS(sram); 834 DEBUGFS_READ_FILE_OPS(nvm); 835 DEBUGFS_READ_FILE_OPS(stations); 836 DEBUGFS_READ_FILE_OPS(channels); 837 DEBUGFS_READ_FILE_OPS(status); 838 DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 839 DEBUGFS_READ_FILE_OPS(qos); 840 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 841 842 static ssize_t 843 il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, 844 loff_t *ppos) 845 { 846 847 struct il_priv *il = file->private_data; 848 struct il_tx_queue *txq; 849 struct il_queue *q; 850 char *buf; 851 int pos = 0; 852 int cnt; 853 int ret; 854 const size_t bufsz = 855 sizeof(char) * 64 * il->cfg->num_of_queues; 856 857 if (!il->txq) { 858 IL_ERR("txq not ready\n"); 859 return -EAGAIN; 860 } 861 buf = kzalloc(bufsz, GFP_KERNEL); 862 if (!buf) 863 return -ENOMEM; 864 865 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { 866 txq = &il->txq[cnt]; 867 q = &txq->q; 868 pos += 869 scnprintf(buf + pos, bufsz - pos, 870 "hwq %.2d: read=%u write=%u stop=%d" 871 " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, 872 q->read_ptr, q->write_ptr, 873 !!test_bit(cnt, il->queue_stopped), 874 txq->swq_id, txq->swq_id & 3, 875 (txq->swq_id >> 2) & 0x1f); 876 if (cnt >= 4) 877 continue; 878 /* for the ACs, display the stop count too */ 879 pos += 880 scnprintf(buf + pos, bufsz - pos, 881 " stop-count: %d\n", 882 atomic_read(&il->queue_stop_count[cnt])); 883 } 884 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 885 kfree(buf); 886 return ret; 887 } 888 889 static ssize_t 890 il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, 891 loff_t *ppos) 892 { 893 894 struct il_priv *il = file->private_data; 895 struct il_rx_queue *rxq = &il->rxq; 896 char buf[256]; 897 int pos = 0; 898 const size_t bufsz = sizeof(buf); 899 900 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read); 901 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write); 902 pos += 903 scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 904 rxq->free_count); 905 if (rxq->rb_stts) { 906 pos += 907 scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 908 le16_to_cpu(rxq->rb_stts-> 909 closed_rb_num) & 0x0FFF); 910 } else { 911 pos += 912 scnprintf(buf + pos, bufsz - pos, 913 "closed_rb_num: Not Allocated\n"); 914 } 915 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 916 } 917 918 static ssize_t 919 il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, 920 size_t count, loff_t *ppos) 921 { 922 struct il_priv *il = file->private_data; 923 924 return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos); 925 } 926 927 static ssize_t 928 il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, 929 size_t count, loff_t *ppos) 930 { 931 struct il_priv *il = file->private_data; 932 933 return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos); 934 } 935 936 static ssize_t 937 il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, 938 size_t count, loff_t *ppos) 939 { 940 struct il_priv *il = file->private_data; 941 942 return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos); 943 } 944 945 static ssize_t 946 il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf, 947 size_t count, loff_t *ppos) 948 { 949 950 struct il_priv *il = file->private_data; 951 int pos = 0; 952 int cnt = 0; 953 char *buf; 954 int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100; 955 ssize_t ret; 956 struct il_sensitivity_data *data; 957 958 data = &il->sensitivity_data; 959 buf = kzalloc(bufsz, GFP_KERNEL); 960 if (!buf) { 961 IL_ERR("Can not allocate Buffer\n"); 962 return -ENOMEM; 963 } 964 965 pos += 966 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 967 data->auto_corr_ofdm); 968 pos += 969 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n", 970 data->auto_corr_ofdm_mrc); 971 pos += 972 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 973 data->auto_corr_ofdm_x1); 974 pos += 975 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n", 976 data->auto_corr_ofdm_mrc_x1); 977 pos += 978 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 979 data->auto_corr_cck); 980 pos += 981 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 982 data->auto_corr_cck_mrc); 983 pos += 984 scnprintf(buf + pos, bufsz - pos, 985 "last_bad_plcp_cnt_ofdm:\t\t %u\n", 986 data->last_bad_plcp_cnt_ofdm); 987 pos += 988 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 989 data->last_fa_cnt_ofdm); 990 pos += 991 scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n", 992 data->last_bad_plcp_cnt_cck); 993 pos += 994 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 995 data->last_fa_cnt_cck); 996 pos += 997 scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 998 data->nrg_curr_state); 999 pos += 1000 scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 1001 data->nrg_prev_state); 1002 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 1003 for (cnt = 0; cnt < 10; cnt++) { 1004 pos += 1005 scnprintf(buf + pos, bufsz - pos, " %u", 1006 data->nrg_value[cnt]); 1007 } 1008 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1009 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 1010 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 1011 pos += 1012 scnprintf(buf + pos, bufsz - pos, " %u", 1013 data->nrg_silence_rssi[cnt]); 1014 } 1015 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1016 pos += 1017 scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 1018 data->nrg_silence_ref); 1019 pos += 1020 scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 1021 data->nrg_energy_idx); 1022 pos += 1023 scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 1024 data->nrg_silence_idx); 1025 pos += 1026 scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 1027 data->nrg_th_cck); 1028 pos += 1029 scnprintf(buf + pos, bufsz - pos, 1030 "nrg_auto_corr_silence_diff:\t %u\n", 1031 data->nrg_auto_corr_silence_diff); 1032 pos += 1033 scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 1034 data->num_in_cck_no_fa); 1035 pos += 1036 scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 1037 data->nrg_th_ofdm); 1038 1039 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1040 kfree(buf); 1041 return ret; 1042 } 1043 1044 static ssize_t 1045 il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf, 1046 size_t count, loff_t *ppos) 1047 { 1048 1049 struct il_priv *il = file->private_data; 1050 int pos = 0; 1051 int cnt = 0; 1052 char *buf; 1053 int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100; 1054 ssize_t ret; 1055 struct il_chain_noise_data *data; 1056 1057 data = &il->chain_noise_data; 1058 buf = kzalloc(bufsz, GFP_KERNEL); 1059 if (!buf) { 1060 IL_ERR("Can not allocate Buffer\n"); 1061 return -ENOMEM; 1062 } 1063 1064 pos += 1065 scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 1066 data->active_chains); 1067 pos += 1068 scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 1069 data->chain_noise_a); 1070 pos += 1071 scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 1072 data->chain_noise_b); 1073 pos += 1074 scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 1075 data->chain_noise_c); 1076 pos += 1077 scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 1078 data->chain_signal_a); 1079 pos += 1080 scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 1081 data->chain_signal_b); 1082 pos += 1083 scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 1084 data->chain_signal_c); 1085 pos += 1086 scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 1087 data->beacon_count); 1088 1089 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 1090 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1091 pos += 1092 scnprintf(buf + pos, bufsz - pos, " %u", 1093 data->disconn_array[cnt]); 1094 } 1095 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1096 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 1097 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1098 pos += 1099 scnprintf(buf + pos, bufsz - pos, " %u", 1100 data->delta_gain_code[cnt]); 1101 } 1102 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1103 pos += 1104 scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 1105 data->radio_write); 1106 pos += 1107 scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 1108 data->state); 1109 1110 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1111 kfree(buf); 1112 return ret; 1113 } 1114 1115 static ssize_t 1116 il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, 1117 size_t count, loff_t *ppos) 1118 { 1119 struct il_priv *il = file->private_data; 1120 char buf[60]; 1121 int pos = 0; 1122 const size_t bufsz = sizeof(buf); 1123 u32 pwrsave_status; 1124 1125 pwrsave_status = 1126 _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; 1127 1128 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 1129 pos += 1130 scnprintf(buf + pos, bufsz - pos, "%s\n", 1131 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 1132 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 1133 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 1134 "error"); 1135 1136 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1137 } 1138 1139 static ssize_t 1140 il_dbgfs_clear_ucode_stats_write(struct file *file, 1141 const char __user *user_buf, size_t count, 1142 loff_t *ppos) 1143 { 1144 struct il_priv *il = file->private_data; 1145 char buf[8]; 1146 int buf_size; 1147 int clear; 1148 1149 memset(buf, 0, sizeof(buf)); 1150 buf_size = min(count, sizeof(buf) - 1); 1151 if (copy_from_user(buf, user_buf, buf_size)) 1152 return -EFAULT; 1153 if (sscanf(buf, "%d", &clear) != 1) 1154 return -EFAULT; 1155 1156 /* make request to uCode to retrieve stats information */ 1157 mutex_lock(&il->mutex); 1158 il_send_stats_request(il, CMD_SYNC, true); 1159 mutex_unlock(&il->mutex); 1160 1161 return count; 1162 } 1163 1164 static ssize_t 1165 il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, 1166 size_t count, loff_t *ppos) 1167 { 1168 1169 struct il_priv *il = file->private_data; 1170 int len = 0; 1171 char buf[20]; 1172 1173 len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); 1174 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1175 } 1176 1177 static ssize_t 1178 il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, 1179 size_t count, loff_t *ppos) 1180 { 1181 1182 struct il_priv *il = file->private_data; 1183 int len = 0; 1184 char buf[20]; 1185 1186 len = 1187 sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); 1188 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1189 } 1190 1191 static ssize_t 1192 il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, 1193 loff_t *ppos) 1194 { 1195 struct il_priv *il = file->private_data; 1196 char *buf; 1197 int pos = 0; 1198 ssize_t ret = -EFAULT; 1199 1200 if (il->ops->dump_fh) { 1201 ret = pos = il->ops->dump_fh(il, &buf, true); 1202 if (buf) { 1203 ret = 1204 simple_read_from_buffer(user_buf, count, ppos, buf, 1205 pos); 1206 kfree(buf); 1207 } 1208 } 1209 1210 return ret; 1211 } 1212 1213 static ssize_t 1214 il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, 1215 size_t count, loff_t *ppos) 1216 { 1217 1218 struct il_priv *il = file->private_data; 1219 int pos = 0; 1220 char buf[12]; 1221 const size_t bufsz = sizeof(buf); 1222 1223 pos += 1224 scnprintf(buf + pos, bufsz - pos, "%d\n", 1225 il->missed_beacon_threshold); 1226 1227 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1228 } 1229 1230 static ssize_t 1231 il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf, 1232 size_t count, loff_t *ppos) 1233 { 1234 struct il_priv *il = file->private_data; 1235 char buf[8]; 1236 int buf_size; 1237 int missed; 1238 1239 memset(buf, 0, sizeof(buf)); 1240 buf_size = min(count, sizeof(buf) - 1); 1241 if (copy_from_user(buf, user_buf, buf_size)) 1242 return -EFAULT; 1243 if (sscanf(buf, "%d", &missed) != 1) 1244 return -EINVAL; 1245 1246 if (missed < IL_MISSED_BEACON_THRESHOLD_MIN || 1247 missed > IL_MISSED_BEACON_THRESHOLD_MAX) 1248 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF; 1249 else 1250 il->missed_beacon_threshold = missed; 1251 1252 return count; 1253 } 1254 1255 static ssize_t 1256 il_dbgfs_force_reset_read(struct file *file, char __user *user_buf, 1257 size_t count, loff_t *ppos) 1258 { 1259 1260 struct il_priv *il = file->private_data; 1261 int pos = 0; 1262 char buf[300]; 1263 const size_t bufsz = sizeof(buf); 1264 struct il_force_reset *force_reset; 1265 1266 force_reset = &il->force_reset; 1267 1268 pos += 1269 scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n", 1270 force_reset->reset_request_count); 1271 pos += 1272 scnprintf(buf + pos, bufsz - pos, 1273 "\tnumber of reset request success: %d\n", 1274 force_reset->reset_success_count); 1275 pos += 1276 scnprintf(buf + pos, bufsz - pos, 1277 "\tnumber of reset request reject: %d\n", 1278 force_reset->reset_reject_count); 1279 pos += 1280 scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n", 1281 force_reset->reset_duration); 1282 1283 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1284 } 1285 1286 static ssize_t 1287 il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf, 1288 size_t count, loff_t *ppos) 1289 { 1290 1291 int ret; 1292 struct il_priv *il = file->private_data; 1293 1294 ret = il_force_reset(il, true); 1295 1296 return ret ? ret : count; 1297 } 1298 1299 static ssize_t 1300 il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, 1301 size_t count, loff_t *ppos) 1302 { 1303 1304 struct il_priv *il = file->private_data; 1305 char buf[8]; 1306 int buf_size; 1307 int timeout; 1308 1309 memset(buf, 0, sizeof(buf)); 1310 buf_size = min(count, sizeof(buf) - 1); 1311 if (copy_from_user(buf, user_buf, buf_size)) 1312 return -EFAULT; 1313 if (sscanf(buf, "%d", &timeout) != 1) 1314 return -EINVAL; 1315 if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) 1316 timeout = IL_DEF_WD_TIMEOUT; 1317 1318 il->cfg->wd_timeout = timeout; 1319 il_setup_watchdog(il); 1320 return count; 1321 } 1322 1323 DEBUGFS_READ_FILE_OPS(rx_stats); 1324 DEBUGFS_READ_FILE_OPS(tx_stats); 1325 DEBUGFS_READ_FILE_OPS(rx_queue); 1326 DEBUGFS_READ_FILE_OPS(tx_queue); 1327 DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 1328 DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 1329 DEBUGFS_READ_FILE_OPS(ucode_general_stats); 1330 DEBUGFS_READ_FILE_OPS(sensitivity); 1331 DEBUGFS_READ_FILE_OPS(chain_noise); 1332 DEBUGFS_READ_FILE_OPS(power_save_status); 1333 DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats); 1334 DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats); 1335 DEBUGFS_READ_FILE_OPS(fh_reg); 1336 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 1337 DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1338 DEBUGFS_READ_FILE_OPS(rxon_flags); 1339 DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1340 DEBUGFS_WRITE_FILE_OPS(wd_timeout); 1341 1342 /* 1343 * Create the debugfs files and directories 1344 * 1345 */ 1346 int 1347 il_dbgfs_register(struct il_priv *il, const char *name) 1348 { 1349 struct dentry *phyd = il->hw->wiphy->debugfsdir; 1350 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 1351 1352 dir_drv = debugfs_create_dir(name, phyd); 1353 if (!dir_drv) 1354 return -ENOMEM; 1355 1356 il->debugfs_dir = dir_drv; 1357 1358 dir_data = debugfs_create_dir("data", dir_drv); 1359 if (!dir_data) 1360 goto err; 1361 dir_rf = debugfs_create_dir("rf", dir_drv); 1362 if (!dir_rf) 1363 goto err; 1364 dir_debug = debugfs_create_dir("debug", dir_drv); 1365 if (!dir_debug) 1366 goto err; 1367 1368 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 1369 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 1370 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 1371 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 1372 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1373 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1374 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1375 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 1376 DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); 1377 DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); 1378 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 1379 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 1380 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 1381 DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR); 1382 DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR); 1383 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 1384 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 1385 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 1386 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 1387 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 1388 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 1389 1390 if (il->cfg->sensitivity_calib_by_driver) 1391 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 1392 if (il->cfg->chain_noise_calib_by_driver) 1393 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 1394 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1395 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1396 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 1397 if (il->cfg->sensitivity_calib_by_driver) 1398 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 1399 &il->disable_sens_cal); 1400 if (il->cfg->chain_noise_calib_by_driver) 1401 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 1402 &il->disable_chain_noise_cal); 1403 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); 1404 return 0; 1405 1406 err: 1407 IL_ERR("Can't create the debugfs directory\n"); 1408 il_dbgfs_unregister(il); 1409 return -ENOMEM; 1410 } 1411 EXPORT_SYMBOL(il_dbgfs_register); 1412 1413 /** 1414 * Remove the debugfs files and directories 1415 * 1416 */ 1417 void 1418 il_dbgfs_unregister(struct il_priv *il) 1419 { 1420 if (!il->debugfs_dir) 1421 return; 1422 1423 debugfs_remove_recursive(il->debugfs_dir); 1424 il->debugfs_dir = NULL; 1425 } 1426 EXPORT_SYMBOL(il_dbgfs_unregister); 1427