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