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