iwl-debugfs.c revision dbf28e21ca391110e90ccad05dda79d2e2f60e0e
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 29#include <linux/slab.h> 30#include <linux/kernel.h> 31#include <linux/module.h> 32#include <linux/debugfs.h> 33 34#include <linux/ieee80211.h> 35#include <net/mac80211.h> 36 37 38#include "iwl-dev.h" 39#include "iwl-debug.h" 40#include "iwl-core.h" 41#include "iwl-io.h" 42 43/* create and remove of files */ 44#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 45 if (!debugfs_create_file(#name, mode, parent, priv, \ 46 &iwl_dbgfs_##name##_ops)) \ 47 goto err; \ 48} while (0) 49 50#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 51 struct dentry *__tmp; \ 52 __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ 53 parent, ptr); \ 54 if (IS_ERR(__tmp) || !__tmp) \ 55 goto err; \ 56} while (0) 57 58#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ 59 struct dentry *__tmp; \ 60 __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ 61 parent, ptr); \ 62 if (IS_ERR(__tmp) || !__tmp) \ 63 goto err; \ 64} while (0) 65 66/* file operation */ 67#define DEBUGFS_READ_FUNC(name) \ 68static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ 69 char __user *user_buf, \ 70 size_t count, loff_t *ppos); 71 72#define DEBUGFS_WRITE_FUNC(name) \ 73static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ 74 const char __user *user_buf, \ 75 size_t count, loff_t *ppos); 76 77 78static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) 79{ 80 file->private_data = inode->i_private; 81 return 0; 82} 83 84#define DEBUGFS_READ_FILE_OPS(name) \ 85 DEBUGFS_READ_FUNC(name); \ 86static const struct file_operations iwl_dbgfs_##name##_ops = { \ 87 .read = iwl_dbgfs_##name##_read, \ 88 .open = iwl_dbgfs_open_file_generic, \ 89 .llseek = generic_file_llseek, \ 90}; 91 92#define DEBUGFS_WRITE_FILE_OPS(name) \ 93 DEBUGFS_WRITE_FUNC(name); \ 94static const struct file_operations iwl_dbgfs_##name##_ops = { \ 95 .write = iwl_dbgfs_##name##_write, \ 96 .open = iwl_dbgfs_open_file_generic, \ 97 .llseek = generic_file_llseek, \ 98}; 99 100 101#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 102 DEBUGFS_READ_FUNC(name); \ 103 DEBUGFS_WRITE_FUNC(name); \ 104static const struct file_operations iwl_dbgfs_##name##_ops = { \ 105 .write = iwl_dbgfs_##name##_write, \ 106 .read = iwl_dbgfs_##name##_read, \ 107 .open = iwl_dbgfs_open_file_generic, \ 108 .llseek = generic_file_llseek, \ 109}; 110 111static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, 112 char __user *user_buf, 113 size_t count, loff_t *ppos) { 114 115 struct iwl_priv *priv = file->private_data; 116 char *buf; 117 int pos = 0; 118 119 int cnt; 120 ssize_t ret; 121 const size_t bufsz = 100 + 122 sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 123 buf = kzalloc(bufsz, GFP_KERNEL); 124 if (!buf) 125 return -ENOMEM; 126 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 127 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 128 pos += scnprintf(buf + pos, bufsz - pos, 129 "\t%25s\t\t: %u\n", 130 get_mgmt_string(cnt), 131 priv->tx_stats.mgmt[cnt]); 132 } 133 pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); 134 for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 135 pos += scnprintf(buf + pos, bufsz - pos, 136 "\t%25s\t\t: %u\n", 137 get_ctrl_string(cnt), 138 priv->tx_stats.ctrl[cnt]); 139 } 140 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 141 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 142 priv->tx_stats.data_cnt); 143 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 144 priv->tx_stats.data_bytes); 145 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 146 kfree(buf); 147 return ret; 148} 149 150static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file, 151 const char __user *user_buf, 152 size_t count, loff_t *ppos) 153{ 154 struct iwl_priv *priv = file->private_data; 155 u32 clear_flag; 156 char buf[8]; 157 int buf_size; 158 159 memset(buf, 0, sizeof(buf)); 160 buf_size = min(count, sizeof(buf) - 1); 161 if (copy_from_user(buf, user_buf, buf_size)) 162 return -EFAULT; 163 if (sscanf(buf, "%x", &clear_flag) != 1) 164 return -EFAULT; 165 iwl_clear_traffic_stats(priv); 166 167 return count; 168} 169 170static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, 171 char __user *user_buf, 172 size_t count, loff_t *ppos) { 173 174 struct iwl_priv *priv = file->private_data; 175 char *buf; 176 int pos = 0; 177 int cnt; 178 ssize_t ret; 179 const size_t bufsz = 100 + 180 sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 181 buf = kzalloc(bufsz, GFP_KERNEL); 182 if (!buf) 183 return -ENOMEM; 184 185 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 186 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 187 pos += scnprintf(buf + pos, bufsz - pos, 188 "\t%25s\t\t: %u\n", 189 get_mgmt_string(cnt), 190 priv->rx_stats.mgmt[cnt]); 191 } 192 pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); 193 for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 194 pos += scnprintf(buf + pos, bufsz - pos, 195 "\t%25s\t\t: %u\n", 196 get_ctrl_string(cnt), 197 priv->rx_stats.ctrl[cnt]); 198 } 199 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 200 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 201 priv->rx_stats.data_cnt); 202 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 203 priv->rx_stats.data_bytes); 204 205 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 206 kfree(buf); 207 return ret; 208} 209 210static ssize_t iwl_dbgfs_sram_read(struct file *file, 211 char __user *user_buf, 212 size_t count, loff_t *ppos) 213{ 214 u32 val = 0; 215 char *buf; 216 ssize_t ret; 217 int i = 0; 218 bool device_format = false; 219 int offset = 0; 220 int len = 0; 221 int pos = 0; 222 int sram; 223 struct iwl_priv *priv = file->private_data; 224 size_t bufsz; 225 226 /* default is to dump the entire data segment */ 227 if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { 228 priv->dbgfs_sram_offset = 0x800000; 229 if (priv->ucode_type == UCODE_SUBTYPE_INIT) 230 priv->dbgfs_sram_len = priv->ucode_init.data.len; 231 else 232 priv->dbgfs_sram_len = priv->ucode_rt.data.len; 233 } 234 len = priv->dbgfs_sram_len; 235 236 if (len == -4) { 237 device_format = true; 238 len = 4; 239 } 240 241 bufsz = 50 + len * 4; 242 buf = kmalloc(bufsz, GFP_KERNEL); 243 if (!buf) 244 return -ENOMEM; 245 246 pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", 247 len); 248 pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", 249 priv->dbgfs_sram_offset); 250 251 /* adjust sram address since reads are only on even u32 boundaries */ 252 offset = priv->dbgfs_sram_offset & 0x3; 253 sram = priv->dbgfs_sram_offset & ~0x3; 254 255 /* read the first u32 from sram */ 256 val = iwl_read_targ_mem(priv, sram); 257 258 for (; len; len--) { 259 /* put the address at the start of every line */ 260 if (i == 0) 261 pos += scnprintf(buf + pos, bufsz - pos, 262 "%08X: ", sram + offset); 263 264 if (device_format) 265 pos += scnprintf(buf + pos, bufsz - pos, 266 "%02x", (val >> (8 * (3 - offset))) & 0xff); 267 else 268 pos += scnprintf(buf + pos, bufsz - pos, 269 "%02x ", (val >> (8 * offset)) & 0xff); 270 271 /* if all bytes processed, read the next u32 from sram */ 272 if (++offset == 4) { 273 sram += 4; 274 offset = 0; 275 val = iwl_read_targ_mem(priv, sram); 276 } 277 278 /* put in extra spaces and split lines for human readability */ 279 if (++i == 16) { 280 i = 0; 281 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 282 } else if (!(i & 7)) { 283 pos += scnprintf(buf + pos, bufsz - pos, " "); 284 } else if (!(i & 3)) { 285 pos += scnprintf(buf + pos, bufsz - pos, " "); 286 } 287 } 288 if (i) 289 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 290 291 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 292 kfree(buf); 293 return ret; 294} 295 296static ssize_t iwl_dbgfs_sram_write(struct file *file, 297 const char __user *user_buf, 298 size_t count, loff_t *ppos) 299{ 300 struct iwl_priv *priv = file->private_data; 301 char buf[64]; 302 int buf_size; 303 u32 offset, len; 304 305 memset(buf, 0, sizeof(buf)); 306 buf_size = min(count, sizeof(buf) - 1); 307 if (copy_from_user(buf, user_buf, buf_size)) 308 return -EFAULT; 309 310 if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 311 priv->dbgfs_sram_offset = offset; 312 priv->dbgfs_sram_len = len; 313 } else if (sscanf(buf, "%x", &offset) == 1) { 314 priv->dbgfs_sram_offset = offset; 315 priv->dbgfs_sram_len = -4; 316 } else { 317 priv->dbgfs_sram_offset = 0; 318 priv->dbgfs_sram_len = 0; 319 } 320 321 return count; 322} 323 324static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 325 size_t count, loff_t *ppos) 326{ 327 struct iwl_priv *priv = file->private_data; 328 struct iwl_station_entry *station; 329 int max_sta = priv->hw_params.max_stations; 330 char *buf; 331 int i, j, pos = 0; 332 ssize_t ret; 333 /* Add 30 for initial string */ 334 const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); 335 336 buf = kmalloc(bufsz, GFP_KERNEL); 337 if (!buf) 338 return -ENOMEM; 339 340 pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", 341 priv->num_stations); 342 343 for (i = 0; i < max_sta; i++) { 344 station = &priv->stations[i]; 345 if (!station->used) 346 continue; 347 pos += scnprintf(buf + pos, bufsz - pos, 348 "station %d - addr: %pM, flags: %#x\n", 349 i, station->sta.sta.addr, 350 station->sta.station_flags_msk); 351 pos += scnprintf(buf + pos, bufsz - pos, 352 "TID\tseq_num\ttxq_id\tframes\ttfds\t"); 353 pos += scnprintf(buf + pos, bufsz - pos, 354 "start_idx\tbitmap\t\t\trate_n_flags\n"); 355 356 for (j = 0; j < MAX_TID_COUNT; j++) { 357 pos += scnprintf(buf + pos, bufsz - pos, 358 "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", 359 j, station->tid[j].seq_number, 360 station->tid[j].agg.txq_id, 361 station->tid[j].agg.frame_count, 362 station->tid[j].tfds_in_queue, 363 station->tid[j].agg.start_idx, 364 station->tid[j].agg.bitmap, 365 station->tid[j].agg.rate_n_flags); 366 367 if (station->tid[j].agg.wait_for_ba) 368 pos += scnprintf(buf + pos, bufsz - pos, 369 " - waitforba"); 370 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 371 } 372 373 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 374 } 375 376 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 377 kfree(buf); 378 return ret; 379} 380 381static ssize_t iwl_dbgfs_nvm_read(struct file *file, 382 char __user *user_buf, 383 size_t count, 384 loff_t *ppos) 385{ 386 ssize_t ret; 387 struct iwl_priv *priv = file->private_data; 388 int pos = 0, ofs = 0, buf_size = 0; 389 const u8 *ptr; 390 char *buf; 391 u16 eeprom_ver; 392 size_t eeprom_len = priv->cfg->base_params->eeprom_size; 393 buf_size = 4 * eeprom_len + 256; 394 395 if (eeprom_len % 16) { 396 IWL_ERR(priv, "NVM size is not multiple of 16.\n"); 397 return -ENODATA; 398 } 399 400 ptr = priv->eeprom; 401 if (!ptr) { 402 IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); 403 return -ENOMEM; 404 } 405 406 /* 4 characters for byte 0xYY */ 407 buf = kzalloc(buf_size, GFP_KERNEL); 408 if (!buf) { 409 IWL_ERR(priv, "Can not allocate Buffer\n"); 410 return -ENOMEM; 411 } 412 eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); 413 pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " 414 "version: 0x%x\n", 415 (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) 416 ? "OTP" : "EEPROM", eeprom_ver); 417 for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { 418 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); 419 hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, 420 buf_size - pos, 0); 421 pos += strlen(buf + pos); 422 if (buf_size - pos > 0) 423 buf[pos++] = '\n'; 424 } 425 426 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 427 kfree(buf); 428 return ret; 429} 430 431static ssize_t iwl_dbgfs_log_event_read(struct file *file, 432 char __user *user_buf, 433 size_t count, loff_t *ppos) 434{ 435 struct iwl_priv *priv = file->private_data; 436 char *buf; 437 int pos = 0; 438 ssize_t ret = -ENOMEM; 439 440 ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); 441 if (buf) { 442 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 443 kfree(buf); 444 } 445 return ret; 446} 447 448static ssize_t iwl_dbgfs_log_event_write(struct file *file, 449 const char __user *user_buf, 450 size_t count, loff_t *ppos) 451{ 452 struct iwl_priv *priv = file->private_data; 453 u32 event_log_flag; 454 char buf[8]; 455 int buf_size; 456 457 memset(buf, 0, sizeof(buf)); 458 buf_size = min(count, sizeof(buf) - 1); 459 if (copy_from_user(buf, user_buf, buf_size)) 460 return -EFAULT; 461 if (sscanf(buf, "%d", &event_log_flag) != 1) 462 return -EFAULT; 463 if (event_log_flag == 1) 464 iwl_dump_nic_event_log(priv, true, NULL, false); 465 466 return count; 467} 468 469 470 471static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, 472 size_t count, loff_t *ppos) 473{ 474 struct iwl_priv *priv = file->private_data; 475 struct ieee80211_channel *channels = NULL; 476 const struct ieee80211_supported_band *supp_band = NULL; 477 int pos = 0, i, bufsz = PAGE_SIZE; 478 char *buf; 479 ssize_t ret; 480 481 if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) 482 return -EAGAIN; 483 484 buf = kzalloc(bufsz, GFP_KERNEL); 485 if (!buf) { 486 IWL_ERR(priv, "Can not allocate Buffer\n"); 487 return -ENOMEM; 488 } 489 490 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); 491 if (supp_band) { 492 channels = supp_band->channels; 493 494 pos += scnprintf(buf + pos, bufsz - pos, 495 "Displaying %d channels in 2.4GHz band 802.11bg):\n", 496 supp_band->n_channels); 497 498 for (i = 0; i < supp_band->n_channels; i++) 499 pos += scnprintf(buf + pos, bufsz - pos, 500 "%d: %ddBm: BSS%s%s, %s.\n", 501 channels[i].hw_value, 502 channels[i].max_power, 503 channels[i].flags & IEEE80211_CHAN_RADAR ? 504 " (IEEE 802.11h required)" : "", 505 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 506 || (channels[i].flags & 507 IEEE80211_CHAN_RADAR)) ? "" : 508 ", IBSS", 509 channels[i].flags & 510 IEEE80211_CHAN_PASSIVE_SCAN ? 511 "passive only" : "active/passive"); 512 } 513 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); 514 if (supp_band) { 515 channels = supp_band->channels; 516 517 pos += scnprintf(buf + pos, bufsz - pos, 518 "Displaying %d channels in 5.2GHz band (802.11a)\n", 519 supp_band->n_channels); 520 521 for (i = 0; i < supp_band->n_channels; i++) 522 pos += scnprintf(buf + pos, bufsz - pos, 523 "%d: %ddBm: BSS%s%s, %s.\n", 524 channels[i].hw_value, 525 channels[i].max_power, 526 channels[i].flags & IEEE80211_CHAN_RADAR ? 527 " (IEEE 802.11h required)" : "", 528 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 529 || (channels[i].flags & 530 IEEE80211_CHAN_RADAR)) ? "" : 531 ", IBSS", 532 channels[i].flags & 533 IEEE80211_CHAN_PASSIVE_SCAN ? 534 "passive only" : "active/passive"); 535 } 536 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 537 kfree(buf); 538 return ret; 539} 540 541static ssize_t iwl_dbgfs_status_read(struct file *file, 542 char __user *user_buf, 543 size_t count, loff_t *ppos) { 544 545 struct iwl_priv *priv = file->private_data; 546 char buf[512]; 547 int pos = 0; 548 const size_t bufsz = sizeof(buf); 549 550 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", 551 test_bit(STATUS_HCMD_ACTIVE, &priv->status)); 552 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", 553 test_bit(STATUS_INT_ENABLED, &priv->status)); 554 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", 555 test_bit(STATUS_RF_KILL_HW, &priv->status)); 556 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", 557 test_bit(STATUS_CT_KILL, &priv->status)); 558 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", 559 test_bit(STATUS_INIT, &priv->status)); 560 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", 561 test_bit(STATUS_ALIVE, &priv->status)); 562 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", 563 test_bit(STATUS_READY, &priv->status)); 564 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", 565 test_bit(STATUS_TEMPERATURE, &priv->status)); 566 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", 567 test_bit(STATUS_GEO_CONFIGURED, &priv->status)); 568 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", 569 test_bit(STATUS_EXIT_PENDING, &priv->status)); 570 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", 571 test_bit(STATUS_STATISTICS, &priv->status)); 572 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", 573 test_bit(STATUS_SCANNING, &priv->status)); 574 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", 575 test_bit(STATUS_SCAN_ABORTING, &priv->status)); 576 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", 577 test_bit(STATUS_SCAN_HW, &priv->status)); 578 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", 579 test_bit(STATUS_POWER_PMI, &priv->status)); 580 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", 581 test_bit(STATUS_FW_ERROR, &priv->status)); 582 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 583} 584 585static ssize_t iwl_dbgfs_interrupt_read(struct file *file, 586 char __user *user_buf, 587 size_t count, loff_t *ppos) { 588 589 struct iwl_priv *priv = file->private_data; 590 int pos = 0; 591 int cnt = 0; 592 char *buf; 593 int bufsz = 24 * 64; /* 24 items * 64 char per item */ 594 ssize_t ret; 595 596 buf = kzalloc(bufsz, GFP_KERNEL); 597 if (!buf) { 598 IWL_ERR(priv, "Can not allocate Buffer\n"); 599 return -ENOMEM; 600 } 601 602 pos += scnprintf(buf + pos, bufsz - pos, 603 "Interrupt Statistics Report:\n"); 604 605 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 606 priv->isr_stats.hw); 607 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 608 priv->isr_stats.sw); 609 if (priv->isr_stats.sw || priv->isr_stats.hw) { 610 pos += scnprintf(buf + pos, bufsz - pos, 611 "\tLast Restarting Code: 0x%X\n", 612 priv->isr_stats.err_code); 613 } 614#ifdef CONFIG_IWLWIFI_DEBUG 615 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 616 priv->isr_stats.sch); 617 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 618 priv->isr_stats.alive); 619#endif 620 pos += scnprintf(buf + pos, bufsz - pos, 621 "HW RF KILL switch toggled:\t %u\n", 622 priv->isr_stats.rfkill); 623 624 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 625 priv->isr_stats.ctkill); 626 627 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 628 priv->isr_stats.wakeup); 629 630 pos += scnprintf(buf + pos, bufsz - pos, 631 "Rx command responses:\t\t %u\n", 632 priv->isr_stats.rx); 633 for (cnt = 0; cnt < REPLY_MAX; cnt++) { 634 if (priv->isr_stats.rx_handlers[cnt] > 0) 635 pos += scnprintf(buf + pos, bufsz - pos, 636 "\tRx handler[%36s]:\t\t %u\n", 637 get_cmd_string(cnt), 638 priv->isr_stats.rx_handlers[cnt]); 639 } 640 641 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 642 priv->isr_stats.tx); 643 644 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 645 priv->isr_stats.unhandled); 646 647 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 648 kfree(buf); 649 return ret; 650} 651 652static ssize_t iwl_dbgfs_interrupt_write(struct file *file, 653 const char __user *user_buf, 654 size_t count, loff_t *ppos) 655{ 656 struct iwl_priv *priv = file->private_data; 657 char buf[8]; 658 int buf_size; 659 u32 reset_flag; 660 661 memset(buf, 0, sizeof(buf)); 662 buf_size = min(count, sizeof(buf) - 1); 663 if (copy_from_user(buf, user_buf, buf_size)) 664 return -EFAULT; 665 if (sscanf(buf, "%x", &reset_flag) != 1) 666 return -EFAULT; 667 if (reset_flag == 0) 668 iwl_clear_isr_stats(priv); 669 670 return count; 671} 672 673static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, 674 size_t count, loff_t *ppos) 675{ 676 struct iwl_priv *priv = file->private_data; 677 struct iwl_rxon_context *ctx; 678 int pos = 0, i; 679 char buf[256 * NUM_IWL_RXON_CTX]; 680 const size_t bufsz = sizeof(buf); 681 682 for_each_context(priv, ctx) { 683 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", 684 ctx->ctxid); 685 for (i = 0; i < AC_NUM; i++) { 686 pos += scnprintf(buf + pos, bufsz - pos, 687 "\tcw_min\tcw_max\taifsn\ttxop\n"); 688 pos += scnprintf(buf + pos, bufsz - pos, 689 "AC[%d]\t%u\t%u\t%u\t%u\n", i, 690 ctx->qos_data.def_qos_parm.ac[i].cw_min, 691 ctx->qos_data.def_qos_parm.ac[i].cw_max, 692 ctx->qos_data.def_qos_parm.ac[i].aifsn, 693 ctx->qos_data.def_qos_parm.ac[i].edca_txop); 694 } 695 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 696 } 697 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 698} 699 700static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, 701 char __user *user_buf, 702 size_t count, loff_t *ppos) 703{ 704 struct iwl_priv *priv = file->private_data; 705 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 706 struct iwl_tt_restriction *restriction; 707 char buf[100]; 708 int pos = 0; 709 const size_t bufsz = sizeof(buf); 710 711 pos += scnprintf(buf + pos, bufsz - pos, 712 "Thermal Throttling Mode: %s\n", 713 tt->advanced_tt ? "Advance" : "Legacy"); 714 pos += scnprintf(buf + pos, bufsz - pos, 715 "Thermal Throttling State: %d\n", 716 tt->state); 717 if (tt->advanced_tt) { 718 restriction = tt->restriction + tt->state; 719 pos += scnprintf(buf + pos, bufsz - pos, 720 "Tx mode: %d\n", 721 restriction->tx_stream); 722 pos += scnprintf(buf + pos, bufsz - pos, 723 "Rx mode: %d\n", 724 restriction->rx_stream); 725 pos += scnprintf(buf + pos, bufsz - pos, 726 "HT mode: %d\n", 727 restriction->is_ht); 728 } 729 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 730} 731 732static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, 733 const char __user *user_buf, 734 size_t count, loff_t *ppos) 735{ 736 struct iwl_priv *priv = file->private_data; 737 char buf[8]; 738 int buf_size; 739 int ht40; 740 741 memset(buf, 0, sizeof(buf)); 742 buf_size = min(count, sizeof(buf) - 1); 743 if (copy_from_user(buf, user_buf, buf_size)) 744 return -EFAULT; 745 if (sscanf(buf, "%d", &ht40) != 1) 746 return -EFAULT; 747 if (!iwl_is_any_associated(priv)) 748 priv->disable_ht40 = ht40 ? true : false; 749 else { 750 IWL_ERR(priv, "Sta associated with AP - " 751 "Change to 40MHz channel support is not allowed\n"); 752 return -EINVAL; 753 } 754 755 return count; 756} 757 758static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, 759 char __user *user_buf, 760 size_t count, loff_t *ppos) 761{ 762 struct iwl_priv *priv = file->private_data; 763 char buf[100]; 764 int pos = 0; 765 const size_t bufsz = sizeof(buf); 766 767 pos += scnprintf(buf + pos, bufsz - pos, 768 "11n 40MHz Mode: %s\n", 769 priv->disable_ht40 ? "Disabled" : "Enabled"); 770 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 771} 772 773static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, 774 const char __user *user_buf, 775 size_t count, loff_t *ppos) 776{ 777 struct iwl_priv *priv = file->private_data; 778 char buf[8]; 779 int buf_size; 780 int value; 781 782 memset(buf, 0, sizeof(buf)); 783 buf_size = min(count, sizeof(buf) - 1); 784 if (copy_from_user(buf, user_buf, buf_size)) 785 return -EFAULT; 786 787 if (sscanf(buf, "%d", &value) != 1) 788 return -EINVAL; 789 790 /* 791 * Our users expect 0 to be "CAM", but 0 isn't actually 792 * valid here. However, let's not confuse them and present 793 * IWL_POWER_INDEX_1 as "1", not "0". 794 */ 795 if (value == 0) 796 return -EINVAL; 797 else if (value > 0) 798 value -= 1; 799 800 if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) 801 return -EINVAL; 802 803 if (!iwl_is_ready_rf(priv)) 804 return -EAGAIN; 805 806 priv->power_data.debug_sleep_level_override = value; 807 808 mutex_lock(&priv->mutex); 809 iwl_power_update_mode(priv, true); 810 mutex_unlock(&priv->mutex); 811 812 return count; 813} 814 815static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, 816 char __user *user_buf, 817 size_t count, loff_t *ppos) 818{ 819 struct iwl_priv *priv = file->private_data; 820 char buf[10]; 821 int pos, value; 822 const size_t bufsz = sizeof(buf); 823 824 /* see the write function */ 825 value = priv->power_data.debug_sleep_level_override; 826 if (value >= 0) 827 value += 1; 828 829 pos = scnprintf(buf, bufsz, "%d\n", value); 830 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 831} 832 833static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, 834 char __user *user_buf, 835 size_t count, loff_t *ppos) 836{ 837 struct iwl_priv *priv = file->private_data; 838 char buf[200]; 839 int pos = 0, i; 840 const size_t bufsz = sizeof(buf); 841 struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd; 842 843 pos += scnprintf(buf + pos, bufsz - pos, 844 "flags: %#.2x\n", le16_to_cpu(cmd->flags)); 845 pos += scnprintf(buf + pos, bufsz - pos, 846 "RX/TX timeout: %d/%d usec\n", 847 le32_to_cpu(cmd->rx_data_timeout), 848 le32_to_cpu(cmd->tx_data_timeout)); 849 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 850 pos += scnprintf(buf + pos, bufsz - pos, 851 "sleep_interval[%d]: %d\n", i, 852 le32_to_cpu(cmd->sleep_interval[i])); 853 854 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 855} 856 857DEBUGFS_READ_WRITE_FILE_OPS(sram); 858DEBUGFS_READ_WRITE_FILE_OPS(log_event); 859DEBUGFS_READ_FILE_OPS(nvm); 860DEBUGFS_READ_FILE_OPS(stations); 861DEBUGFS_READ_FILE_OPS(channels); 862DEBUGFS_READ_FILE_OPS(status); 863DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 864DEBUGFS_READ_FILE_OPS(qos); 865DEBUGFS_READ_FILE_OPS(thermal_throttling); 866DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 867DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); 868DEBUGFS_READ_FILE_OPS(current_sleep_command); 869 870static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, 871 char __user *user_buf, 872 size_t count, loff_t *ppos) 873{ 874 struct iwl_priv *priv = file->private_data; 875 int pos = 0, ofs = 0; 876 int cnt = 0, entry; 877 struct iwl_tx_queue *txq; 878 struct iwl_queue *q; 879 struct iwl_rx_queue *rxq = &priv->rxq; 880 char *buf; 881 int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + 882 (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; 883 const u8 *ptr; 884 ssize_t ret; 885 886 if (!priv->txq) { 887 IWL_ERR(priv, "txq not ready\n"); 888 return -EAGAIN; 889 } 890 buf = kzalloc(bufsz, GFP_KERNEL); 891 if (!buf) { 892 IWL_ERR(priv, "Can not allocate buffer\n"); 893 return -ENOMEM; 894 } 895 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); 896 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 897 txq = &priv->txq[cnt]; 898 q = &txq->q; 899 pos += scnprintf(buf + pos, bufsz - pos, 900 "q[%d]: read_ptr: %u, write_ptr: %u\n", 901 cnt, q->read_ptr, q->write_ptr); 902 } 903 if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { 904 ptr = priv->tx_traffic; 905 pos += scnprintf(buf + pos, bufsz - pos, 906 "Tx Traffic idx: %u\n", priv->tx_traffic_idx); 907 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { 908 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; 909 entry++, ofs += 16) { 910 pos += scnprintf(buf + pos, bufsz - pos, 911 "0x%.4x ", ofs); 912 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, 913 buf + pos, bufsz - pos, 0); 914 pos += strlen(buf + pos); 915 if (bufsz - pos > 0) 916 buf[pos++] = '\n'; 917 } 918 } 919 } 920 921 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); 922 pos += scnprintf(buf + pos, bufsz - pos, 923 "read: %u, write: %u\n", 924 rxq->read, rxq->write); 925 926 if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { 927 ptr = priv->rx_traffic; 928 pos += scnprintf(buf + pos, bufsz - pos, 929 "Rx Traffic idx: %u\n", priv->rx_traffic_idx); 930 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { 931 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; 932 entry++, ofs += 16) { 933 pos += scnprintf(buf + pos, bufsz - pos, 934 "0x%.4x ", ofs); 935 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, 936 buf + pos, bufsz - pos, 0); 937 pos += strlen(buf + pos); 938 if (bufsz - pos > 0) 939 buf[pos++] = '\n'; 940 } 941 } 942 } 943 944 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 945 kfree(buf); 946 return ret; 947} 948 949static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, 950 const char __user *user_buf, 951 size_t count, loff_t *ppos) 952{ 953 struct iwl_priv *priv = file->private_data; 954 char buf[8]; 955 int buf_size; 956 int traffic_log; 957 958 memset(buf, 0, sizeof(buf)); 959 buf_size = min(count, sizeof(buf) - 1); 960 if (copy_from_user(buf, user_buf, buf_size)) 961 return -EFAULT; 962 if (sscanf(buf, "%d", &traffic_log) != 1) 963 return -EFAULT; 964 if (traffic_log == 0) 965 iwl_reset_traffic_log(priv); 966 967 return count; 968} 969 970static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, 971 char __user *user_buf, 972 size_t count, loff_t *ppos) { 973 974 struct iwl_priv *priv = file->private_data; 975 struct iwl_tx_queue *txq; 976 struct iwl_queue *q; 977 char *buf; 978 int pos = 0; 979 int cnt; 980 int ret; 981 const size_t bufsz = sizeof(char) * 64 * 982 priv->cfg->base_params->num_of_queues; 983 984 if (!priv->txq) { 985 IWL_ERR(priv, "txq not ready\n"); 986 return -EAGAIN; 987 } 988 buf = kzalloc(bufsz, GFP_KERNEL); 989 if (!buf) 990 return -ENOMEM; 991 992 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 993 txq = &priv->txq[cnt]; 994 q = &txq->q; 995 pos += scnprintf(buf + pos, bufsz - pos, 996 "hwq %.2d: read=%u write=%u stop=%d" 997 " swq_id=%#.2x (ac %d/hwq %d)\n", 998 cnt, q->read_ptr, q->write_ptr, 999 !!test_bit(cnt, priv->queue_stopped), 1000 txq->swq_id, txq->swq_id & 3, 1001 (txq->swq_id >> 2) & 0x1f); 1002 if (cnt >= 4) 1003 continue; 1004 /* for the ACs, display the stop count too */ 1005 pos += scnprintf(buf + pos, bufsz - pos, 1006 " stop-count: %d\n", 1007 atomic_read(&priv->queue_stop_count[cnt])); 1008 } 1009 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1010 kfree(buf); 1011 return ret; 1012} 1013 1014static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, 1015 char __user *user_buf, 1016 size_t count, loff_t *ppos) { 1017 1018 struct iwl_priv *priv = file->private_data; 1019 struct iwl_rx_queue *rxq = &priv->rxq; 1020 char buf[256]; 1021 int pos = 0; 1022 const size_t bufsz = sizeof(buf); 1023 1024 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", 1025 rxq->read); 1026 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", 1027 rxq->write); 1028 pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 1029 rxq->free_count); 1030 if (rxq->rb_stts) { 1031 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 1032 le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); 1033 } else { 1034 pos += scnprintf(buf + pos, bufsz - pos, 1035 "closed_rb_num: Not Allocated\n"); 1036 } 1037 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1038} 1039 1040static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, 1041 char __user *user_buf, 1042 size_t count, loff_t *ppos) 1043{ 1044 struct iwl_priv *priv = file->private_data; 1045 return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, 1046 user_buf, count, ppos); 1047} 1048 1049static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, 1050 char __user *user_buf, 1051 size_t count, loff_t *ppos) 1052{ 1053 struct iwl_priv *priv = file->private_data; 1054 return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, 1055 user_buf, count, ppos); 1056} 1057 1058static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, 1059 char __user *user_buf, 1060 size_t count, loff_t *ppos) 1061{ 1062 struct iwl_priv *priv = file->private_data; 1063 return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, 1064 user_buf, count, ppos); 1065} 1066 1067static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, 1068 char __user *user_buf, 1069 size_t count, loff_t *ppos) { 1070 1071 struct iwl_priv *priv = file->private_data; 1072 int pos = 0; 1073 int cnt = 0; 1074 char *buf; 1075 int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100; 1076 ssize_t ret; 1077 struct iwl_sensitivity_data *data; 1078 1079 data = &priv->sensitivity_data; 1080 buf = kzalloc(bufsz, GFP_KERNEL); 1081 if (!buf) { 1082 IWL_ERR(priv, "Can not allocate Buffer\n"); 1083 return -ENOMEM; 1084 } 1085 1086 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 1087 data->auto_corr_ofdm); 1088 pos += scnprintf(buf + pos, bufsz - pos, 1089 "auto_corr_ofdm_mrc:\t\t %u\n", 1090 data->auto_corr_ofdm_mrc); 1091 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 1092 data->auto_corr_ofdm_x1); 1093 pos += scnprintf(buf + pos, bufsz - pos, 1094 "auto_corr_ofdm_mrc_x1:\t\t %u\n", 1095 data->auto_corr_ofdm_mrc_x1); 1096 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 1097 data->auto_corr_cck); 1098 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 1099 data->auto_corr_cck_mrc); 1100 pos += scnprintf(buf + pos, bufsz - pos, 1101 "last_bad_plcp_cnt_ofdm:\t\t %u\n", 1102 data->last_bad_plcp_cnt_ofdm); 1103 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 1104 data->last_fa_cnt_ofdm); 1105 pos += scnprintf(buf + pos, bufsz - pos, 1106 "last_bad_plcp_cnt_cck:\t\t %u\n", 1107 data->last_bad_plcp_cnt_cck); 1108 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 1109 data->last_fa_cnt_cck); 1110 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 1111 data->nrg_curr_state); 1112 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 1113 data->nrg_prev_state); 1114 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 1115 for (cnt = 0; cnt < 10; cnt++) { 1116 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1117 data->nrg_value[cnt]); 1118 } 1119 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1120 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 1121 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 1122 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1123 data->nrg_silence_rssi[cnt]); 1124 } 1125 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1126 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 1127 data->nrg_silence_ref); 1128 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 1129 data->nrg_energy_idx); 1130 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 1131 data->nrg_silence_idx); 1132 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 1133 data->nrg_th_cck); 1134 pos += scnprintf(buf + pos, bufsz - pos, 1135 "nrg_auto_corr_silence_diff:\t %u\n", 1136 data->nrg_auto_corr_silence_diff); 1137 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 1138 data->num_in_cck_no_fa); 1139 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 1140 data->nrg_th_ofdm); 1141 1142 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1143 kfree(buf); 1144 return ret; 1145} 1146 1147 1148static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, 1149 char __user *user_buf, 1150 size_t count, loff_t *ppos) { 1151 1152 struct iwl_priv *priv = file->private_data; 1153 int pos = 0; 1154 int cnt = 0; 1155 char *buf; 1156 int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100; 1157 ssize_t ret; 1158 struct iwl_chain_noise_data *data; 1159 1160 data = &priv->chain_noise_data; 1161 buf = kzalloc(bufsz, GFP_KERNEL); 1162 if (!buf) { 1163 IWL_ERR(priv, "Can not allocate Buffer\n"); 1164 return -ENOMEM; 1165 } 1166 1167 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 1168 data->active_chains); 1169 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 1170 data->chain_noise_a); 1171 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 1172 data->chain_noise_b); 1173 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 1174 data->chain_noise_c); 1175 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 1176 data->chain_signal_a); 1177 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 1178 data->chain_signal_b); 1179 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 1180 data->chain_signal_c); 1181 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 1182 data->beacon_count); 1183 1184 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 1185 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1186 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1187 data->disconn_array[cnt]); 1188 } 1189 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1190 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 1191 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1192 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1193 data->delta_gain_code[cnt]); 1194 } 1195 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1196 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 1197 data->radio_write); 1198 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 1199 data->state); 1200 1201 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1202 kfree(buf); 1203 return ret; 1204} 1205 1206static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, 1207 char __user *user_buf, 1208 size_t count, loff_t *ppos) 1209{ 1210 struct iwl_priv *priv = file->private_data; 1211 char buf[60]; 1212 int pos = 0; 1213 const size_t bufsz = sizeof(buf); 1214 u32 pwrsave_status; 1215 1216 pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & 1217 CSR_GP_REG_POWER_SAVE_STATUS_MSK; 1218 1219 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 1220 pos += scnprintf(buf + pos, bufsz - pos, "%s\n", 1221 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 1222 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 1223 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 1224 "error"); 1225 1226 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1227} 1228 1229static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, 1230 const char __user *user_buf, 1231 size_t count, loff_t *ppos) 1232{ 1233 struct iwl_priv *priv = file->private_data; 1234 char buf[8]; 1235 int buf_size; 1236 int clear; 1237 1238 memset(buf, 0, sizeof(buf)); 1239 buf_size = min(count, sizeof(buf) - 1); 1240 if (copy_from_user(buf, user_buf, buf_size)) 1241 return -EFAULT; 1242 if (sscanf(buf, "%d", &clear) != 1) 1243 return -EFAULT; 1244 1245 /* make request to uCode to retrieve statistics information */ 1246 mutex_lock(&priv->mutex); 1247 iwl_send_statistics_request(priv, CMD_SYNC, true); 1248 mutex_unlock(&priv->mutex); 1249 1250 return count; 1251} 1252 1253static ssize_t iwl_dbgfs_csr_write(struct file *file, 1254 const char __user *user_buf, 1255 size_t count, loff_t *ppos) 1256{ 1257 struct iwl_priv *priv = file->private_data; 1258 char buf[8]; 1259 int buf_size; 1260 int csr; 1261 1262 memset(buf, 0, sizeof(buf)); 1263 buf_size = min(count, sizeof(buf) - 1); 1264 if (copy_from_user(buf, user_buf, buf_size)) 1265 return -EFAULT; 1266 if (sscanf(buf, "%d", &csr) != 1) 1267 return -EFAULT; 1268 1269 iwl_dump_csr(priv); 1270 1271 return count; 1272} 1273 1274static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, 1275 char __user *user_buf, 1276 size_t count, loff_t *ppos) { 1277 1278 struct iwl_priv *priv = file->private_data; 1279 int pos = 0; 1280 char buf[128]; 1281 const size_t bufsz = sizeof(buf); 1282 1283 pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", 1284 priv->event_log.ucode_trace ? "On" : "Off"); 1285 pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", 1286 priv->event_log.non_wraps_count); 1287 pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", 1288 priv->event_log.wraps_once_count); 1289 pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", 1290 priv->event_log.wraps_more_count); 1291 1292 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1293} 1294 1295static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, 1296 const char __user *user_buf, 1297 size_t count, loff_t *ppos) 1298{ 1299 struct iwl_priv *priv = file->private_data; 1300 char buf[8]; 1301 int buf_size; 1302 int trace; 1303 1304 memset(buf, 0, sizeof(buf)); 1305 buf_size = min(count, sizeof(buf) - 1); 1306 if (copy_from_user(buf, user_buf, buf_size)) 1307 return -EFAULT; 1308 if (sscanf(buf, "%d", &trace) != 1) 1309 return -EFAULT; 1310 1311 if (trace) { 1312 priv->event_log.ucode_trace = true; 1313 /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ 1314 mod_timer(&priv->ucode_trace, 1315 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); 1316 } else { 1317 priv->event_log.ucode_trace = false; 1318 del_timer_sync(&priv->ucode_trace); 1319 } 1320 1321 return count; 1322} 1323 1324static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, 1325 char __user *user_buf, 1326 size_t count, loff_t *ppos) { 1327 1328 struct iwl_priv *priv = file->private_data; 1329 int len = 0; 1330 char buf[20]; 1331 1332 len = sprintf(buf, "0x%04X\n", 1333 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags)); 1334 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1335} 1336 1337static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, 1338 char __user *user_buf, 1339 size_t count, loff_t *ppos) { 1340 1341 struct iwl_priv *priv = file->private_data; 1342 int len = 0; 1343 char buf[20]; 1344 1345 len = sprintf(buf, "0x%04X\n", 1346 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags)); 1347 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1348} 1349 1350static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, 1351 char __user *user_buf, 1352 size_t count, loff_t *ppos) 1353{ 1354 struct iwl_priv *priv = file->private_data; 1355 char *buf; 1356 int pos = 0; 1357 ssize_t ret = -EFAULT; 1358 1359 ret = pos = iwl_dump_fh(priv, &buf, true); 1360 if (buf) { 1361 ret = simple_read_from_buffer(user_buf, 1362 count, ppos, buf, pos); 1363 kfree(buf); 1364 } 1365 1366 return ret; 1367} 1368 1369static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, 1370 char __user *user_buf, 1371 size_t count, loff_t *ppos) { 1372 1373 struct iwl_priv *priv = file->private_data; 1374 int pos = 0; 1375 char buf[12]; 1376 const size_t bufsz = sizeof(buf); 1377 1378 pos += scnprintf(buf + pos, bufsz - pos, "%d\n", 1379 priv->missed_beacon_threshold); 1380 1381 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1382} 1383 1384static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, 1385 const char __user *user_buf, 1386 size_t count, loff_t *ppos) 1387{ 1388 struct iwl_priv *priv = file->private_data; 1389 char buf[8]; 1390 int buf_size; 1391 int missed; 1392 1393 memset(buf, 0, sizeof(buf)); 1394 buf_size = min(count, sizeof(buf) - 1); 1395 if (copy_from_user(buf, user_buf, buf_size)) 1396 return -EFAULT; 1397 if (sscanf(buf, "%d", &missed) != 1) 1398 return -EINVAL; 1399 1400 if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || 1401 missed > IWL_MISSED_BEACON_THRESHOLD_MAX) 1402 priv->missed_beacon_threshold = 1403 IWL_MISSED_BEACON_THRESHOLD_DEF; 1404 else 1405 priv->missed_beacon_threshold = missed; 1406 1407 return count; 1408} 1409 1410static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, 1411 char __user *user_buf, 1412 size_t count, loff_t *ppos) { 1413 1414 struct iwl_priv *priv = file->private_data; 1415 int pos = 0; 1416 char buf[12]; 1417 const size_t bufsz = sizeof(buf); 1418 1419 pos += scnprintf(buf + pos, bufsz - pos, "%u\n", 1420 priv->cfg->base_params->plcp_delta_threshold); 1421 1422 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1423} 1424 1425static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, 1426 const char __user *user_buf, 1427 size_t count, loff_t *ppos) { 1428 1429 struct iwl_priv *priv = file->private_data; 1430 char buf[8]; 1431 int buf_size; 1432 int plcp; 1433 1434 memset(buf, 0, sizeof(buf)); 1435 buf_size = min(count, sizeof(buf) - 1); 1436 if (copy_from_user(buf, user_buf, buf_size)) 1437 return -EFAULT; 1438 if (sscanf(buf, "%d", &plcp) != 1) 1439 return -EINVAL; 1440 if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || 1441 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) 1442 priv->cfg->base_params->plcp_delta_threshold = 1443 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; 1444 else 1445 priv->cfg->base_params->plcp_delta_threshold = plcp; 1446 return count; 1447} 1448 1449static ssize_t iwl_dbgfs_force_reset_read(struct file *file, 1450 char __user *user_buf, 1451 size_t count, loff_t *ppos) { 1452 1453 struct iwl_priv *priv = file->private_data; 1454 int i, pos = 0; 1455 char buf[300]; 1456 const size_t bufsz = sizeof(buf); 1457 struct iwl_force_reset *force_reset; 1458 1459 for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { 1460 force_reset = &priv->force_reset[i]; 1461 pos += scnprintf(buf + pos, bufsz - pos, 1462 "Force reset method %d\n", i); 1463 pos += scnprintf(buf + pos, bufsz - pos, 1464 "\tnumber of reset request: %d\n", 1465 force_reset->reset_request_count); 1466 pos += scnprintf(buf + pos, bufsz - pos, 1467 "\tnumber of reset request success: %d\n", 1468 force_reset->reset_success_count); 1469 pos += scnprintf(buf + pos, bufsz - pos, 1470 "\tnumber of reset request reject: %d\n", 1471 force_reset->reset_reject_count); 1472 pos += scnprintf(buf + pos, bufsz - pos, 1473 "\treset duration: %lu\n", 1474 force_reset->reset_duration); 1475 } 1476 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1477} 1478 1479static ssize_t iwl_dbgfs_force_reset_write(struct file *file, 1480 const char __user *user_buf, 1481 size_t count, loff_t *ppos) { 1482 1483 struct iwl_priv *priv = file->private_data; 1484 char buf[8]; 1485 int buf_size; 1486 int reset, ret; 1487 1488 memset(buf, 0, sizeof(buf)); 1489 buf_size = min(count, sizeof(buf) - 1); 1490 if (copy_from_user(buf, user_buf, buf_size)) 1491 return -EFAULT; 1492 if (sscanf(buf, "%d", &reset) != 1) 1493 return -EINVAL; 1494 switch (reset) { 1495 case IWL_RF_RESET: 1496 case IWL_FW_RESET: 1497 ret = iwl_force_reset(priv, reset, true); 1498 break; 1499 default: 1500 return -EINVAL; 1501 } 1502 return ret ? ret : count; 1503} 1504 1505static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, 1506 const char __user *user_buf, 1507 size_t count, loff_t *ppos) { 1508 1509 struct iwl_priv *priv = file->private_data; 1510 char buf[8]; 1511 int buf_size; 1512 int flush; 1513 1514 memset(buf, 0, sizeof(buf)); 1515 buf_size = min(count, sizeof(buf) - 1); 1516 if (copy_from_user(buf, user_buf, buf_size)) 1517 return -EFAULT; 1518 if (sscanf(buf, "%d", &flush) != 1) 1519 return -EINVAL; 1520 1521 if (iwl_is_rfkill(priv)) 1522 return -EFAULT; 1523 1524 priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL); 1525 1526 return count; 1527} 1528 1529static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, 1530 char __user *user_buf, 1531 size_t count, loff_t *ppos) 1532{ 1533 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1534 1535 return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, 1536 user_buf, count, ppos); 1537} 1538 1539static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, 1540 const char __user *user_buf, 1541 size_t count, loff_t *ppos) { 1542 1543 struct iwl_priv *priv = file->private_data; 1544 char buf[8]; 1545 int buf_size; 1546 int timeout; 1547 1548 memset(buf, 0, sizeof(buf)); 1549 buf_size = min(count, sizeof(buf) - 1); 1550 if (copy_from_user(buf, user_buf, buf_size)) 1551 return -EFAULT; 1552 if (sscanf(buf, "%d", &timeout) != 1) 1553 return -EINVAL; 1554 if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) 1555 timeout = IWL_DEF_WD_TIMEOUT; 1556 1557 priv->cfg->base_params->wd_timeout = timeout; 1558 iwl_setup_watchdog(priv); 1559 return count; 1560} 1561 1562static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, 1563 char __user *user_buf, 1564 size_t count, loff_t *ppos) { 1565 1566 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1567 int pos = 0; 1568 char buf[200]; 1569 const size_t bufsz = sizeof(buf); 1570 1571 if (!priv->bt_enable_flag) { 1572 pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); 1573 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1574 } 1575 pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", 1576 priv->bt_enable_flag); 1577 pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n", 1578 priv->bt_full_concurrent ? "full concurrency" : "3-wire"); 1579 pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " 1580 "last traffic notif: %d\n", 1581 priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); 1582 pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " 1583 "kill_ack_mask: %x, kill_cts_mask: %x\n", 1584 priv->bt_ch_announce, priv->kill_ack_mask, 1585 priv->kill_cts_mask); 1586 1587 pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); 1588 switch (priv->bt_traffic_load) { 1589 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: 1590 pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n"); 1591 break; 1592 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: 1593 pos += scnprintf(buf + pos, bufsz - pos, "High\n"); 1594 break; 1595 case IWL_BT_COEX_TRAFFIC_LOAD_LOW: 1596 pos += scnprintf(buf + pos, bufsz - pos, "Low\n"); 1597 break; 1598 case IWL_BT_COEX_TRAFFIC_LOAD_NONE: 1599 default: 1600 pos += scnprintf(buf + pos, bufsz - pos, "None\n"); 1601 break; 1602 } 1603 1604 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1605} 1606 1607static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, 1608 char __user *user_buf, 1609 size_t count, loff_t *ppos) 1610{ 1611 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1612 1613 int pos = 0; 1614 char buf[40]; 1615 const size_t bufsz = sizeof(buf); 1616 1617 if (priv->cfg->ht_params) 1618 pos += scnprintf(buf + pos, bufsz - pos, 1619 "use %s for aggregation\n", 1620 (priv->cfg->ht_params->use_rts_for_aggregation) ? 1621 "rts/cts" : "cts-to-self"); 1622 else 1623 pos += scnprintf(buf + pos, bufsz - pos, "N/A"); 1624 1625 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1626} 1627 1628static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, 1629 const char __user *user_buf, 1630 size_t count, loff_t *ppos) { 1631 1632 struct iwl_priv *priv = file->private_data; 1633 char buf[8]; 1634 int buf_size; 1635 int rts; 1636 1637 if (!priv->cfg->ht_params) 1638 return -EINVAL; 1639 1640 memset(buf, 0, sizeof(buf)); 1641 buf_size = min(count, sizeof(buf) - 1); 1642 if (copy_from_user(buf, user_buf, buf_size)) 1643 return -EFAULT; 1644 if (sscanf(buf, "%d", &rts) != 1) 1645 return -EINVAL; 1646 if (rts) 1647 priv->cfg->ht_params->use_rts_for_aggregation = true; 1648 else 1649 priv->cfg->ht_params->use_rts_for_aggregation = false; 1650 return count; 1651} 1652 1653static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, 1654 char __user *user_buf, 1655 size_t count, loff_t *ppos) 1656{ 1657 struct iwl_priv *priv = file->private_data; 1658 1659 if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) 1660 return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( 1661 file, user_buf, count, ppos); 1662 else 1663 return -ENODATA; 1664} 1665DEBUGFS_READ_FILE_OPS(rx_statistics); 1666DEBUGFS_READ_FILE_OPS(tx_statistics); 1667DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 1668DEBUGFS_READ_FILE_OPS(rx_queue); 1669DEBUGFS_READ_FILE_OPS(tx_queue); 1670DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 1671DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 1672DEBUGFS_READ_FILE_OPS(ucode_general_stats); 1673DEBUGFS_READ_FILE_OPS(sensitivity); 1674DEBUGFS_READ_FILE_OPS(chain_noise); 1675DEBUGFS_READ_FILE_OPS(power_save_status); 1676DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); 1677DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); 1678DEBUGFS_WRITE_FILE_OPS(csr); 1679DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); 1680DEBUGFS_READ_FILE_OPS(fh_reg); 1681DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 1682DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); 1683DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1684DEBUGFS_READ_FILE_OPS(rxon_flags); 1685DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1686DEBUGFS_WRITE_FILE_OPS(txfifo_flush); 1687DEBUGFS_READ_FILE_OPS(ucode_bt_stats); 1688DEBUGFS_WRITE_FILE_OPS(wd_timeout); 1689DEBUGFS_READ_FILE_OPS(bt_traffic); 1690DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); 1691DEBUGFS_READ_FILE_OPS(reply_tx_error); 1692 1693/* 1694 * Create the debugfs files and directories 1695 * 1696 */ 1697int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 1698{ 1699 struct dentry *phyd = priv->hw->wiphy->debugfsdir; 1700 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 1701 1702 dir_drv = debugfs_create_dir(name, phyd); 1703 if (!dir_drv) 1704 return -ENOMEM; 1705 1706 priv->debugfs_dir = dir_drv; 1707 1708 dir_data = debugfs_create_dir("data", dir_drv); 1709 if (!dir_data) 1710 goto err; 1711 dir_rf = debugfs_create_dir("rf", dir_drv); 1712 if (!dir_rf) 1713 goto err; 1714 dir_debug = debugfs_create_dir("debug", dir_drv); 1715 if (!dir_debug) 1716 goto err; 1717 1718 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 1719 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 1720 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); 1721 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 1722 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 1723 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1724 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1725 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1726 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); 1727 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); 1728 DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); 1729 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 1730 DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); 1731 DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); 1732 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); 1733 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 1734 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 1735 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 1736 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); 1737 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); 1738 DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); 1739 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 1740 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 1741 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); 1742 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 1743 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 1744 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 1745 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 1746 if (priv->cfg->ops->lib->dev_txfifo_flush) 1747 DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); 1748 DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); 1749 1750 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 1751 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 1752 DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); 1753 DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); 1754 DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); 1755 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1756 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1757 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 1758 if (iwl_advanced_bt_coexist(priv)) 1759 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); 1760 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 1761 &priv->disable_sens_cal); 1762 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 1763 &priv->disable_chain_noise_cal); 1764 return 0; 1765 1766err: 1767 IWL_ERR(priv, "Can't create the debugfs directory\n"); 1768 iwl_dbgfs_unregister(priv); 1769 return -ENOMEM; 1770} 1771 1772/** 1773 * Remove the debugfs files and directories 1774 * 1775 */ 1776void iwl_dbgfs_unregister(struct iwl_priv *priv) 1777{ 1778 if (!priv->debugfs_dir) 1779 return; 1780 1781 debugfs_remove_recursive(priv->debugfs_dir); 1782 priv->debugfs_dir = NULL; 1783} 1784 1785 1786 1787