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 34static void 35il_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 */ 45void 46il_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} 127EXPORT_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) \ 154static 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) \ 159static 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); \ 166static 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); \ 174static 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); \ 183static 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 190static const char * 191il_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 212static const char * 213il_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 230static ssize_t 231il_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 270static ssize_t 271il_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 291static ssize_t 292il_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; 335static ssize_t 336il_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 394static ssize_t 395il_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 419static ssize_t 420il_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 483static ssize_t 484il_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 ", ofs); 519 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos, 520 buf_size - pos, 0); 521 pos += strlen(buf + pos); 522 if (buf_size - pos > 0) 523 buf[pos++] = '\n'; 524 } 525 526 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 527 kfree(buf); 528 return ret; 529} 530 531static ssize_t 532il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, 533 loff_t *ppos) 534{ 535 struct il_priv *il = file->private_data; 536 struct ieee80211_channel *channels = NULL; 537 const struct ieee80211_supported_band *supp_band = NULL; 538 int pos = 0, i, bufsz = PAGE_SIZE; 539 char *buf; 540 ssize_t ret; 541 542 if (!test_bit(S_GEO_CONFIGURED, &il->status)) 543 return -EAGAIN; 544 545 buf = kzalloc(bufsz, GFP_KERNEL); 546 if (!buf) { 547 IL_ERR("Can not allocate Buffer\n"); 548 return -ENOMEM; 549 } 550 551 supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); 552 if (supp_band) { 553 channels = supp_band->channels; 554 555 pos += 556 scnprintf(buf + pos, bufsz - pos, 557 "Displaying %d channels in 2.4GHz band 802.11bg):\n", 558 supp_band->n_channels); 559 560 for (i = 0; i < supp_band->n_channels; i++) 561 pos += 562 scnprintf(buf + pos, bufsz - pos, 563 "%d: %ddBm: BSS%s%s, %s.\n", 564 channels[i].hw_value, 565 channels[i].max_power, 566 channels[i]. 567 flags & IEEE80211_CHAN_RADAR ? 568 " (IEEE 802.11h required)" : "", 569 ((channels[i]. 570 flags & IEEE80211_CHAN_NO_IR) || 571 (channels[i]. 572 flags & IEEE80211_CHAN_RADAR)) ? "" : 573 ", IBSS", 574 channels[i]. 575 flags & IEEE80211_CHAN_NO_IR ? 576 "passive only" : "active/passive"); 577 } 578 supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); 579 if (supp_band) { 580 channels = supp_band->channels; 581 582 pos += 583 scnprintf(buf + pos, bufsz - pos, 584 "Displaying %d channels in 5.2GHz band (802.11a)\n", 585 supp_band->n_channels); 586 587 for (i = 0; i < supp_band->n_channels; i++) 588 pos += 589 scnprintf(buf + pos, bufsz - pos, 590 "%d: %ddBm: BSS%s%s, %s.\n", 591 channels[i].hw_value, 592 channels[i].max_power, 593 channels[i]. 594 flags & IEEE80211_CHAN_RADAR ? 595 " (IEEE 802.11h required)" : "", 596 ((channels[i]. 597 flags & IEEE80211_CHAN_NO_IR) || 598 (channels[i]. 599 flags & IEEE80211_CHAN_RADAR)) ? "" : 600 ", IBSS", 601 channels[i]. 602 flags & IEEE80211_CHAN_NO_IR ? 603 "passive only" : "active/passive"); 604 } 605 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 606 kfree(buf); 607 return ret; 608} 609 610static ssize_t 611il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, 612 loff_t *ppos) 613{ 614 615 struct il_priv *il = file->private_data; 616 char buf[512]; 617 int pos = 0; 618 const size_t bufsz = sizeof(buf); 619 620 pos += 621 scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n", 622 test_bit(S_HCMD_ACTIVE, &il->status)); 623 pos += 624 scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", 625 test_bit(S_INT_ENABLED, &il->status)); 626 pos += 627 scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n", 628 test_bit(S_RFKILL, &il->status)); 629 pos += 630 scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", 631 test_bit(S_CT_KILL, &il->status)); 632 pos += 633 scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n", 634 test_bit(S_INIT, &il->status)); 635 pos += 636 scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n", 637 test_bit(S_ALIVE, &il->status)); 638 pos += 639 scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n", 640 test_bit(S_READY, &il->status)); 641 pos += 642 scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n", 643 test_bit(S_TEMPERATURE, &il->status)); 644 pos += 645 scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n", 646 test_bit(S_GEO_CONFIGURED, &il->status)); 647 pos += 648 scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n", 649 test_bit(S_EXIT_PENDING, &il->status)); 650 pos += 651 scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n", 652 test_bit(S_STATS, &il->status)); 653 pos += 654 scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n", 655 test_bit(S_SCANNING, &il->status)); 656 pos += 657 scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n", 658 test_bit(S_SCAN_ABORTING, &il->status)); 659 pos += 660 scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n", 661 test_bit(S_SCAN_HW, &il->status)); 662 pos += 663 scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n", 664 test_bit(S_POWER_PMI, &il->status)); 665 pos += 666 scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n", 667 test_bit(S_FW_ERROR, &il->status)); 668 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 669} 670 671static ssize_t 672il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, 673 loff_t *ppos) 674{ 675 676 struct il_priv *il = file->private_data; 677 int pos = 0; 678 int cnt = 0; 679 char *buf; 680 int bufsz = 24 * 64; /* 24 items * 64 char per item */ 681 ssize_t ret; 682 683 buf = kzalloc(bufsz, GFP_KERNEL); 684 if (!buf) { 685 IL_ERR("Can not allocate Buffer\n"); 686 return -ENOMEM; 687 } 688 689 pos += 690 scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n"); 691 692 pos += 693 scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 694 il->isr_stats.hw); 695 pos += 696 scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 697 il->isr_stats.sw); 698 if (il->isr_stats.sw || il->isr_stats.hw) { 699 pos += 700 scnprintf(buf + pos, bufsz - pos, 701 "\tLast Restarting Code: 0x%X\n", 702 il->isr_stats.err_code); 703 } 704#ifdef CONFIG_IWLEGACY_DEBUG 705 pos += 706 scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 707 il->isr_stats.sch); 708 pos += 709 scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 710 il->isr_stats.alive); 711#endif 712 pos += 713 scnprintf(buf + pos, bufsz - pos, 714 "HW RF KILL switch toggled:\t %u\n", 715 il->isr_stats.rfkill); 716 717 pos += 718 scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 719 il->isr_stats.ctkill); 720 721 pos += 722 scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 723 il->isr_stats.wakeup); 724 725 pos += 726 scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n", 727 il->isr_stats.rx); 728 for (cnt = 0; cnt < IL_CN_MAX; cnt++) { 729 if (il->isr_stats.handlers[cnt] > 0) 730 pos += 731 scnprintf(buf + pos, bufsz - pos, 732 "\tRx handler[%36s]:\t\t %u\n", 733 il_get_cmd_string(cnt), 734 il->isr_stats.handlers[cnt]); 735 } 736 737 pos += 738 scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 739 il->isr_stats.tx); 740 741 pos += 742 scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 743 il->isr_stats.unhandled); 744 745 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 746 kfree(buf); 747 return ret; 748} 749 750static ssize_t 751il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, 752 size_t count, loff_t *ppos) 753{ 754 struct il_priv *il = file->private_data; 755 char buf[8]; 756 int buf_size; 757 u32 reset_flag; 758 759 memset(buf, 0, sizeof(buf)); 760 buf_size = min(count, sizeof(buf) - 1); 761 if (copy_from_user(buf, user_buf, buf_size)) 762 return -EFAULT; 763 if (sscanf(buf, "%x", &reset_flag) != 1) 764 return -EFAULT; 765 if (reset_flag == 0) 766 il_clear_isr_stats(il); 767 768 return count; 769} 770 771static ssize_t 772il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, 773 loff_t *ppos) 774{ 775 struct il_priv *il = file->private_data; 776 int pos = 0, i; 777 char buf[256]; 778 const size_t bufsz = sizeof(buf); 779 780 for (i = 0; i < AC_NUM; i++) { 781 pos += 782 scnprintf(buf + pos, bufsz - pos, 783 "\tcw_min\tcw_max\taifsn\ttxop\n"); 784 pos += 785 scnprintf(buf + pos, bufsz - pos, 786 "AC[%d]\t%u\t%u\t%u\t%u\n", i, 787 il->qos_data.def_qos_parm.ac[i].cw_min, 788 il->qos_data.def_qos_parm.ac[i].cw_max, 789 il->qos_data.def_qos_parm.ac[i].aifsn, 790 il->qos_data.def_qos_parm.ac[i].edca_txop); 791 } 792 793 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 794} 795 796static ssize_t 797il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf, 798 size_t count, loff_t *ppos) 799{ 800 struct il_priv *il = file->private_data; 801 char buf[8]; 802 int buf_size; 803 int ht40; 804 805 memset(buf, 0, sizeof(buf)); 806 buf_size = min(count, sizeof(buf) - 1); 807 if (copy_from_user(buf, user_buf, buf_size)) 808 return -EFAULT; 809 if (sscanf(buf, "%d", &ht40) != 1) 810 return -EFAULT; 811 if (!il_is_any_associated(il)) 812 il->disable_ht40 = ht40 ? true : false; 813 else { 814 IL_ERR("Sta associated with AP - " 815 "Change to 40MHz channel support is not allowed\n"); 816 return -EINVAL; 817 } 818 819 return count; 820} 821 822static ssize_t 823il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf, 824 size_t count, loff_t *ppos) 825{ 826 struct il_priv *il = file->private_data; 827 char buf[100]; 828 int pos = 0; 829 const size_t bufsz = sizeof(buf); 830 831 pos += 832 scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n", 833 il->disable_ht40 ? "Disabled" : "Enabled"); 834 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 835} 836 837DEBUGFS_READ_WRITE_FILE_OPS(sram); 838DEBUGFS_READ_FILE_OPS(nvm); 839DEBUGFS_READ_FILE_OPS(stations); 840DEBUGFS_READ_FILE_OPS(channels); 841DEBUGFS_READ_FILE_OPS(status); 842DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 843DEBUGFS_READ_FILE_OPS(qos); 844DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 845 846static ssize_t 847il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, 848 loff_t *ppos) 849{ 850 851 struct il_priv *il = file->private_data; 852 struct il_tx_queue *txq; 853 struct il_queue *q; 854 char *buf; 855 int pos = 0; 856 int cnt; 857 int ret; 858 const size_t bufsz = 859 sizeof(char) * 64 * il->cfg->num_of_queues; 860 861 if (!il->txq) { 862 IL_ERR("txq not ready\n"); 863 return -EAGAIN; 864 } 865 buf = kzalloc(bufsz, GFP_KERNEL); 866 if (!buf) 867 return -ENOMEM; 868 869 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { 870 txq = &il->txq[cnt]; 871 q = &txq->q; 872 pos += 873 scnprintf(buf + pos, bufsz - pos, 874 "hwq %.2d: read=%u write=%u stop=%d" 875 " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, 876 q->read_ptr, q->write_ptr, 877 !!test_bit(cnt, il->queue_stopped), 878 txq->swq_id, txq->swq_id & 3, 879 (txq->swq_id >> 2) & 0x1f); 880 if (cnt >= 4) 881 continue; 882 /* for the ACs, display the stop count too */ 883 pos += 884 scnprintf(buf + pos, bufsz - pos, 885 " stop-count: %d\n", 886 atomic_read(&il->queue_stop_count[cnt])); 887 } 888 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 889 kfree(buf); 890 return ret; 891} 892 893static ssize_t 894il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, 895 loff_t *ppos) 896{ 897 898 struct il_priv *il = file->private_data; 899 struct il_rx_queue *rxq = &il->rxq; 900 char buf[256]; 901 int pos = 0; 902 const size_t bufsz = sizeof(buf); 903 904 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read); 905 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write); 906 pos += 907 scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 908 rxq->free_count); 909 if (rxq->rb_stts) { 910 pos += 911 scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 912 le16_to_cpu(rxq->rb_stts-> 913 closed_rb_num) & 0x0FFF); 914 } else { 915 pos += 916 scnprintf(buf + pos, bufsz - pos, 917 "closed_rb_num: Not Allocated\n"); 918 } 919 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 920} 921 922static ssize_t 923il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, 924 size_t count, loff_t *ppos) 925{ 926 struct il_priv *il = file->private_data; 927 928 return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos); 929} 930 931static ssize_t 932il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, 933 size_t count, loff_t *ppos) 934{ 935 struct il_priv *il = file->private_data; 936 937 return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos); 938} 939 940static ssize_t 941il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, 942 size_t count, loff_t *ppos) 943{ 944 struct il_priv *il = file->private_data; 945 946 return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos); 947} 948 949static ssize_t 950il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf, 951 size_t count, loff_t *ppos) 952{ 953 954 struct il_priv *il = file->private_data; 955 int pos = 0; 956 int cnt = 0; 957 char *buf; 958 int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100; 959 ssize_t ret; 960 struct il_sensitivity_data *data; 961 962 data = &il->sensitivity_data; 963 buf = kzalloc(bufsz, GFP_KERNEL); 964 if (!buf) { 965 IL_ERR("Can not allocate Buffer\n"); 966 return -ENOMEM; 967 } 968 969 pos += 970 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 971 data->auto_corr_ofdm); 972 pos += 973 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n", 974 data->auto_corr_ofdm_mrc); 975 pos += 976 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 977 data->auto_corr_ofdm_x1); 978 pos += 979 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n", 980 data->auto_corr_ofdm_mrc_x1); 981 pos += 982 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 983 data->auto_corr_cck); 984 pos += 985 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 986 data->auto_corr_cck_mrc); 987 pos += 988 scnprintf(buf + pos, bufsz - pos, 989 "last_bad_plcp_cnt_ofdm:\t\t %u\n", 990 data->last_bad_plcp_cnt_ofdm); 991 pos += 992 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 993 data->last_fa_cnt_ofdm); 994 pos += 995 scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n", 996 data->last_bad_plcp_cnt_cck); 997 pos += 998 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 999 data->last_fa_cnt_cck); 1000 pos += 1001 scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 1002 data->nrg_curr_state); 1003 pos += 1004 scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 1005 data->nrg_prev_state); 1006 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 1007 for (cnt = 0; cnt < 10; cnt++) { 1008 pos += 1009 scnprintf(buf + pos, bufsz - pos, " %u", 1010 data->nrg_value[cnt]); 1011 } 1012 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1013 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 1014 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 1015 pos += 1016 scnprintf(buf + pos, bufsz - pos, " %u", 1017 data->nrg_silence_rssi[cnt]); 1018 } 1019 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1020 pos += 1021 scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 1022 data->nrg_silence_ref); 1023 pos += 1024 scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 1025 data->nrg_energy_idx); 1026 pos += 1027 scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 1028 data->nrg_silence_idx); 1029 pos += 1030 scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 1031 data->nrg_th_cck); 1032 pos += 1033 scnprintf(buf + pos, bufsz - pos, 1034 "nrg_auto_corr_silence_diff:\t %u\n", 1035 data->nrg_auto_corr_silence_diff); 1036 pos += 1037 scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 1038 data->num_in_cck_no_fa); 1039 pos += 1040 scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 1041 data->nrg_th_ofdm); 1042 1043 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1044 kfree(buf); 1045 return ret; 1046} 1047 1048static ssize_t 1049il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf, 1050 size_t count, loff_t *ppos) 1051{ 1052 1053 struct il_priv *il = file->private_data; 1054 int pos = 0; 1055 int cnt = 0; 1056 char *buf; 1057 int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100; 1058 ssize_t ret; 1059 struct il_chain_noise_data *data; 1060 1061 data = &il->chain_noise_data; 1062 buf = kzalloc(bufsz, GFP_KERNEL); 1063 if (!buf) { 1064 IL_ERR("Can not allocate Buffer\n"); 1065 return -ENOMEM; 1066 } 1067 1068 pos += 1069 scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 1070 data->active_chains); 1071 pos += 1072 scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 1073 data->chain_noise_a); 1074 pos += 1075 scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 1076 data->chain_noise_b); 1077 pos += 1078 scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 1079 data->chain_noise_c); 1080 pos += 1081 scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 1082 data->chain_signal_a); 1083 pos += 1084 scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 1085 data->chain_signal_b); 1086 pos += 1087 scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 1088 data->chain_signal_c); 1089 pos += 1090 scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 1091 data->beacon_count); 1092 1093 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 1094 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1095 pos += 1096 scnprintf(buf + pos, bufsz - pos, " %u", 1097 data->disconn_array[cnt]); 1098 } 1099 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1100 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 1101 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1102 pos += 1103 scnprintf(buf + pos, bufsz - pos, " %u", 1104 data->delta_gain_code[cnt]); 1105 } 1106 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1107 pos += 1108 scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 1109 data->radio_write); 1110 pos += 1111 scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 1112 data->state); 1113 1114 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1115 kfree(buf); 1116 return ret; 1117} 1118 1119static ssize_t 1120il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, 1121 size_t count, loff_t *ppos) 1122{ 1123 struct il_priv *il = file->private_data; 1124 char buf[60]; 1125 int pos = 0; 1126 const size_t bufsz = sizeof(buf); 1127 u32 pwrsave_status; 1128 1129 pwrsave_status = 1130 _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; 1131 1132 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 1133 pos += 1134 scnprintf(buf + pos, bufsz - pos, "%s\n", 1135 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 1136 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 1137 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 1138 "error"); 1139 1140 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1141} 1142 1143static ssize_t 1144il_dbgfs_clear_ucode_stats_write(struct file *file, 1145 const char __user *user_buf, size_t count, 1146 loff_t *ppos) 1147{ 1148 struct il_priv *il = file->private_data; 1149 char buf[8]; 1150 int buf_size; 1151 int clear; 1152 1153 memset(buf, 0, sizeof(buf)); 1154 buf_size = min(count, sizeof(buf) - 1); 1155 if (copy_from_user(buf, user_buf, buf_size)) 1156 return -EFAULT; 1157 if (sscanf(buf, "%d", &clear) != 1) 1158 return -EFAULT; 1159 1160 /* make request to uCode to retrieve stats information */ 1161 mutex_lock(&il->mutex); 1162 il_send_stats_request(il, CMD_SYNC, true); 1163 mutex_unlock(&il->mutex); 1164 1165 return count; 1166} 1167 1168static ssize_t 1169il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, 1170 size_t count, loff_t *ppos) 1171{ 1172 1173 struct il_priv *il = file->private_data; 1174 int len = 0; 1175 char buf[20]; 1176 1177 len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); 1178 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1179} 1180 1181static ssize_t 1182il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, 1183 size_t count, loff_t *ppos) 1184{ 1185 1186 struct il_priv *il = file->private_data; 1187 int len = 0; 1188 char buf[20]; 1189 1190 len = 1191 sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); 1192 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1193} 1194 1195static ssize_t 1196il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, 1197 loff_t *ppos) 1198{ 1199 struct il_priv *il = file->private_data; 1200 char *buf; 1201 int pos = 0; 1202 ssize_t ret = -EFAULT; 1203 1204 if (il->ops->dump_fh) { 1205 ret = pos = il->ops->dump_fh(il, &buf, true); 1206 if (buf) { 1207 ret = 1208 simple_read_from_buffer(user_buf, count, ppos, buf, 1209 pos); 1210 kfree(buf); 1211 } 1212 } 1213 1214 return ret; 1215} 1216 1217static ssize_t 1218il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, 1219 size_t count, loff_t *ppos) 1220{ 1221 1222 struct il_priv *il = file->private_data; 1223 int pos = 0; 1224 char buf[12]; 1225 const size_t bufsz = sizeof(buf); 1226 1227 pos += 1228 scnprintf(buf + pos, bufsz - pos, "%d\n", 1229 il->missed_beacon_threshold); 1230 1231 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1232} 1233 1234static ssize_t 1235il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf, 1236 size_t count, loff_t *ppos) 1237{ 1238 struct il_priv *il = file->private_data; 1239 char buf[8]; 1240 int buf_size; 1241 int missed; 1242 1243 memset(buf, 0, sizeof(buf)); 1244 buf_size = min(count, sizeof(buf) - 1); 1245 if (copy_from_user(buf, user_buf, buf_size)) 1246 return -EFAULT; 1247 if (sscanf(buf, "%d", &missed) != 1) 1248 return -EINVAL; 1249 1250 if (missed < IL_MISSED_BEACON_THRESHOLD_MIN || 1251 missed > IL_MISSED_BEACON_THRESHOLD_MAX) 1252 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF; 1253 else 1254 il->missed_beacon_threshold = missed; 1255 1256 return count; 1257} 1258 1259static ssize_t 1260il_dbgfs_force_reset_read(struct file *file, char __user *user_buf, 1261 size_t count, loff_t *ppos) 1262{ 1263 1264 struct il_priv *il = file->private_data; 1265 int pos = 0; 1266 char buf[300]; 1267 const size_t bufsz = sizeof(buf); 1268 struct il_force_reset *force_reset; 1269 1270 force_reset = &il->force_reset; 1271 1272 pos += 1273 scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n", 1274 force_reset->reset_request_count); 1275 pos += 1276 scnprintf(buf + pos, bufsz - pos, 1277 "\tnumber of reset request success: %d\n", 1278 force_reset->reset_success_count); 1279 pos += 1280 scnprintf(buf + pos, bufsz - pos, 1281 "\tnumber of reset request reject: %d\n", 1282 force_reset->reset_reject_count); 1283 pos += 1284 scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n", 1285 force_reset->reset_duration); 1286 1287 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1288} 1289 1290static ssize_t 1291il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf, 1292 size_t count, loff_t *ppos) 1293{ 1294 1295 int ret; 1296 struct il_priv *il = file->private_data; 1297 1298 ret = il_force_reset(il, true); 1299 1300 return ret ? ret : count; 1301} 1302 1303static ssize_t 1304il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, 1305 size_t count, loff_t *ppos) 1306{ 1307 1308 struct il_priv *il = file->private_data; 1309 char buf[8]; 1310 int buf_size; 1311 int timeout; 1312 1313 memset(buf, 0, sizeof(buf)); 1314 buf_size = min(count, sizeof(buf) - 1); 1315 if (copy_from_user(buf, user_buf, buf_size)) 1316 return -EFAULT; 1317 if (sscanf(buf, "%d", &timeout) != 1) 1318 return -EINVAL; 1319 if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) 1320 timeout = IL_DEF_WD_TIMEOUT; 1321 1322 il->cfg->wd_timeout = timeout; 1323 il_setup_watchdog(il); 1324 return count; 1325} 1326 1327DEBUGFS_READ_FILE_OPS(rx_stats); 1328DEBUGFS_READ_FILE_OPS(tx_stats); 1329DEBUGFS_READ_FILE_OPS(rx_queue); 1330DEBUGFS_READ_FILE_OPS(tx_queue); 1331DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 1332DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 1333DEBUGFS_READ_FILE_OPS(ucode_general_stats); 1334DEBUGFS_READ_FILE_OPS(sensitivity); 1335DEBUGFS_READ_FILE_OPS(chain_noise); 1336DEBUGFS_READ_FILE_OPS(power_save_status); 1337DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats); 1338DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats); 1339DEBUGFS_READ_FILE_OPS(fh_reg); 1340DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 1341DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1342DEBUGFS_READ_FILE_OPS(rxon_flags); 1343DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1344DEBUGFS_WRITE_FILE_OPS(wd_timeout); 1345 1346/* 1347 * Create the debugfs files and directories 1348 * 1349 */ 1350int 1351il_dbgfs_register(struct il_priv *il, const char *name) 1352{ 1353 struct dentry *phyd = il->hw->wiphy->debugfsdir; 1354 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 1355 1356 dir_drv = debugfs_create_dir(name, phyd); 1357 if (!dir_drv) 1358 return -ENOMEM; 1359 1360 il->debugfs_dir = dir_drv; 1361 1362 dir_data = debugfs_create_dir("data", dir_drv); 1363 if (!dir_data) 1364 goto err; 1365 dir_rf = debugfs_create_dir("rf", dir_drv); 1366 if (!dir_rf) 1367 goto err; 1368 dir_debug = debugfs_create_dir("debug", dir_drv); 1369 if (!dir_debug) 1370 goto err; 1371 1372 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 1373 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 1374 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 1375 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 1376 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1377 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1378 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1379 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 1380 DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); 1381 DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); 1382 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 1383 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 1384 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 1385 DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR); 1386 DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR); 1387 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 1388 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 1389 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 1390 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 1391 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 1392 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 1393 1394 if (il->cfg->sensitivity_calib_by_driver) 1395 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 1396 if (il->cfg->chain_noise_calib_by_driver) 1397 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 1398 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1399 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1400 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 1401 if (il->cfg->sensitivity_calib_by_driver) 1402 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 1403 &il->disable_sens_cal); 1404 if (il->cfg->chain_noise_calib_by_driver) 1405 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 1406 &il->disable_chain_noise_cal); 1407 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); 1408 return 0; 1409 1410err: 1411 IL_ERR("Can't create the debugfs directory\n"); 1412 il_dbgfs_unregister(il); 1413 return -ENOMEM; 1414} 1415EXPORT_SYMBOL(il_dbgfs_register); 1416 1417/** 1418 * Remove the debugfs files and directories 1419 * 1420 */ 1421void 1422il_dbgfs_unregister(struct il_priv *il) 1423{ 1424 if (!il->debugfs_dir) 1425 return; 1426 1427 debugfs_remove_recursive(il->debugfs_dir); 1428 il->debugfs_dir = NULL; 1429} 1430EXPORT_SYMBOL(il_dbgfs_unregister); 1431