iwl-debugfs.c revision 08960dea6c736280a03cb947f445fdb94fdaa2ee
1/****************************************************************************** 2 * 3 * GPL LICENSE SUMMARY 4 * 5 * Copyright(c) 2008 - 2010 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_INIT) 230 priv->dbgfs_sram_len = priv->ucode_init_data.len; 231 else 232 priv->dbgfs_sram_len = priv->ucode_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 = priv->cfg->ops->lib->dump_nic_event_log( 441 priv, true, &buf, true); 442 if (buf) { 443 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 444 kfree(buf); 445 } 446 return ret; 447} 448 449static ssize_t iwl_dbgfs_log_event_write(struct file *file, 450 const char __user *user_buf, 451 size_t count, loff_t *ppos) 452{ 453 struct iwl_priv *priv = file->private_data; 454 u32 event_log_flag; 455 char buf[8]; 456 int buf_size; 457 458 memset(buf, 0, sizeof(buf)); 459 buf_size = min(count, sizeof(buf) - 1); 460 if (copy_from_user(buf, user_buf, buf_size)) 461 return -EFAULT; 462 if (sscanf(buf, "%d", &event_log_flag) != 1) 463 return -EFAULT; 464 if (event_log_flag == 1) 465 priv->cfg->ops->lib->dump_nic_event_log(priv, true, 466 NULL, false); 467 468 return count; 469} 470 471 472 473static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, 474 size_t count, loff_t *ppos) 475{ 476 struct iwl_priv *priv = file->private_data; 477 struct ieee80211_channel *channels = NULL; 478 const struct ieee80211_supported_band *supp_band = NULL; 479 int pos = 0, i, bufsz = PAGE_SIZE; 480 char *buf; 481 ssize_t ret; 482 483 if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) 484 return -EAGAIN; 485 486 buf = kzalloc(bufsz, GFP_KERNEL); 487 if (!buf) { 488 IWL_ERR(priv, "Can not allocate Buffer\n"); 489 return -ENOMEM; 490 } 491 492 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); 493 if (supp_band) { 494 channels = supp_band->channels; 495 496 pos += scnprintf(buf + pos, bufsz - pos, 497 "Displaying %d channels in 2.4GHz band 802.11bg):\n", 498 supp_band->n_channels); 499 500 for (i = 0; i < supp_band->n_channels; i++) 501 pos += scnprintf(buf + pos, bufsz - pos, 502 "%d: %ddBm: BSS%s%s, %s.\n", 503 channels[i].hw_value, 504 channels[i].max_power, 505 channels[i].flags & IEEE80211_CHAN_RADAR ? 506 " (IEEE 802.11h required)" : "", 507 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 508 || (channels[i].flags & 509 IEEE80211_CHAN_RADAR)) ? "" : 510 ", IBSS", 511 channels[i].flags & 512 IEEE80211_CHAN_PASSIVE_SCAN ? 513 "passive only" : "active/passive"); 514 } 515 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); 516 if (supp_band) { 517 channels = supp_band->channels; 518 519 pos += scnprintf(buf + pos, bufsz - pos, 520 "Displaying %d channels in 5.2GHz band (802.11a)\n", 521 supp_band->n_channels); 522 523 for (i = 0; i < supp_band->n_channels; i++) 524 pos += scnprintf(buf + pos, bufsz - pos, 525 "%d: %ddBm: BSS%s%s, %s.\n", 526 channels[i].hw_value, 527 channels[i].max_power, 528 channels[i].flags & IEEE80211_CHAN_RADAR ? 529 " (IEEE 802.11h required)" : "", 530 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 531 || (channels[i].flags & 532 IEEE80211_CHAN_RADAR)) ? "" : 533 ", IBSS", 534 channels[i].flags & 535 IEEE80211_CHAN_PASSIVE_SCAN ? 536 "passive only" : "active/passive"); 537 } 538 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 539 kfree(buf); 540 return ret; 541} 542 543static ssize_t iwl_dbgfs_status_read(struct file *file, 544 char __user *user_buf, 545 size_t count, loff_t *ppos) { 546 547 struct iwl_priv *priv = file->private_data; 548 char buf[512]; 549 int pos = 0; 550 const size_t bufsz = sizeof(buf); 551 552 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", 553 test_bit(STATUS_HCMD_ACTIVE, &priv->status)); 554 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", 555 test_bit(STATUS_INT_ENABLED, &priv->status)); 556 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", 557 test_bit(STATUS_RF_KILL_HW, &priv->status)); 558 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", 559 test_bit(STATUS_CT_KILL, &priv->status)); 560 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", 561 test_bit(STATUS_INIT, &priv->status)); 562 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", 563 test_bit(STATUS_ALIVE, &priv->status)); 564 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", 565 test_bit(STATUS_READY, &priv->status)); 566 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", 567 test_bit(STATUS_TEMPERATURE, &priv->status)); 568 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", 569 test_bit(STATUS_GEO_CONFIGURED, &priv->status)); 570 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", 571 test_bit(STATUS_EXIT_PENDING, &priv->status)); 572 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", 573 test_bit(STATUS_STATISTICS, &priv->status)); 574 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", 575 test_bit(STATUS_SCANNING, &priv->status)); 576 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", 577 test_bit(STATUS_SCAN_ABORTING, &priv->status)); 578 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", 579 test_bit(STATUS_SCAN_HW, &priv->status)); 580 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", 581 test_bit(STATUS_POWER_PMI, &priv->status)); 582 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", 583 test_bit(STATUS_FW_ERROR, &priv->status)); 584 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 585} 586 587static ssize_t iwl_dbgfs_interrupt_read(struct file *file, 588 char __user *user_buf, 589 size_t count, loff_t *ppos) { 590 591 struct iwl_priv *priv = file->private_data; 592 int pos = 0; 593 int cnt = 0; 594 char *buf; 595 int bufsz = 24 * 64; /* 24 items * 64 char per item */ 596 ssize_t ret; 597 598 buf = kzalloc(bufsz, GFP_KERNEL); 599 if (!buf) { 600 IWL_ERR(priv, "Can not allocate Buffer\n"); 601 return -ENOMEM; 602 } 603 604 pos += scnprintf(buf + pos, bufsz - pos, 605 "Interrupt Statistics Report:\n"); 606 607 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 608 priv->isr_stats.hw); 609 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 610 priv->isr_stats.sw); 611 if (priv->isr_stats.sw || priv->isr_stats.hw) { 612 pos += scnprintf(buf + pos, bufsz - pos, 613 "\tLast Restarting Code: 0x%X\n", 614 priv->isr_stats.err_code); 615 } 616#ifdef CONFIG_IWLWIFI_DEBUG 617 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 618 priv->isr_stats.sch); 619 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 620 priv->isr_stats.alive); 621#endif 622 pos += scnprintf(buf + pos, bufsz - pos, 623 "HW RF KILL switch toggled:\t %u\n", 624 priv->isr_stats.rfkill); 625 626 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 627 priv->isr_stats.ctkill); 628 629 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 630 priv->isr_stats.wakeup); 631 632 pos += scnprintf(buf + pos, bufsz - pos, 633 "Rx command responses:\t\t %u\n", 634 priv->isr_stats.rx); 635 for (cnt = 0; cnt < REPLY_MAX; cnt++) { 636 if (priv->isr_stats.rx_handlers[cnt] > 0) 637 pos += scnprintf(buf + pos, bufsz - pos, 638 "\tRx handler[%36s]:\t\t %u\n", 639 get_cmd_string(cnt), 640 priv->isr_stats.rx_handlers[cnt]); 641 } 642 643 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 644 priv->isr_stats.tx); 645 646 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 647 priv->isr_stats.unhandled); 648 649 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 650 kfree(buf); 651 return ret; 652} 653 654static ssize_t iwl_dbgfs_interrupt_write(struct file *file, 655 const char __user *user_buf, 656 size_t count, loff_t *ppos) 657{ 658 struct iwl_priv *priv = file->private_data; 659 char buf[8]; 660 int buf_size; 661 u32 reset_flag; 662 663 memset(buf, 0, sizeof(buf)); 664 buf_size = min(count, sizeof(buf) - 1); 665 if (copy_from_user(buf, user_buf, buf_size)) 666 return -EFAULT; 667 if (sscanf(buf, "%x", &reset_flag) != 1) 668 return -EFAULT; 669 if (reset_flag == 0) 670 iwl_clear_isr_stats(priv); 671 672 return count; 673} 674 675static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, 676 size_t count, loff_t *ppos) 677{ 678 struct iwl_priv *priv = file->private_data; 679 struct iwl_rxon_context *ctx; 680 int pos = 0, i; 681 char buf[256 * NUM_IWL_RXON_CTX]; 682 const size_t bufsz = sizeof(buf); 683 684 for_each_context(priv, ctx) { 685 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", 686 ctx->ctxid); 687 for (i = 0; i < AC_NUM; i++) { 688 pos += scnprintf(buf + pos, bufsz - pos, 689 "\tcw_min\tcw_max\taifsn\ttxop\n"); 690 pos += scnprintf(buf + pos, bufsz - pos, 691 "AC[%d]\t%u\t%u\t%u\t%u\n", i, 692 ctx->qos_data.def_qos_parm.ac[i].cw_min, 693 ctx->qos_data.def_qos_parm.ac[i].cw_max, 694 ctx->qos_data.def_qos_parm.ac[i].aifsn, 695 ctx->qos_data.def_qos_parm.ac[i].edca_txop); 696 } 697 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 698 } 699 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 700} 701 702static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, 703 char __user *user_buf, 704 size_t count, loff_t *ppos) 705{ 706 struct iwl_priv *priv = file->private_data; 707 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 708 struct iwl_tt_restriction *restriction; 709 char buf[100]; 710 int pos = 0; 711 const size_t bufsz = sizeof(buf); 712 713 pos += scnprintf(buf + pos, bufsz - pos, 714 "Thermal Throttling Mode: %s\n", 715 tt->advanced_tt ? "Advance" : "Legacy"); 716 pos += scnprintf(buf + pos, bufsz - pos, 717 "Thermal Throttling State: %d\n", 718 tt->state); 719 if (tt->advanced_tt) { 720 restriction = tt->restriction + tt->state; 721 pos += scnprintf(buf + pos, bufsz - pos, 722 "Tx mode: %d\n", 723 restriction->tx_stream); 724 pos += scnprintf(buf + pos, bufsz - pos, 725 "Rx mode: %d\n", 726 restriction->rx_stream); 727 pos += scnprintf(buf + pos, bufsz - pos, 728 "HT mode: %d\n", 729 restriction->is_ht); 730 } 731 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 732} 733 734static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, 735 const char __user *user_buf, 736 size_t count, loff_t *ppos) 737{ 738 struct iwl_priv *priv = file->private_data; 739 char buf[8]; 740 int buf_size; 741 int ht40; 742 743 memset(buf, 0, sizeof(buf)); 744 buf_size = min(count, sizeof(buf) - 1); 745 if (copy_from_user(buf, user_buf, buf_size)) 746 return -EFAULT; 747 if (sscanf(buf, "%d", &ht40) != 1) 748 return -EFAULT; 749 if (!iwl_is_any_associated(priv)) 750 priv->disable_ht40 = ht40 ? true : false; 751 else { 752 IWL_ERR(priv, "Sta associated with AP - " 753 "Change to 40MHz channel support is not allowed\n"); 754 return -EINVAL; 755 } 756 757 return count; 758} 759 760static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, 761 char __user *user_buf, 762 size_t count, loff_t *ppos) 763{ 764 struct iwl_priv *priv = file->private_data; 765 char buf[100]; 766 int pos = 0; 767 const size_t bufsz = sizeof(buf); 768 769 pos += scnprintf(buf + pos, bufsz - pos, 770 "11n 40MHz Mode: %s\n", 771 priv->disable_ht40 ? "Disabled" : "Enabled"); 772 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 773} 774 775static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, 776 const char __user *user_buf, 777 size_t count, loff_t *ppos) 778{ 779 struct iwl_priv *priv = file->private_data; 780 char buf[8]; 781 int buf_size; 782 int value; 783 784 memset(buf, 0, sizeof(buf)); 785 buf_size = min(count, sizeof(buf) - 1); 786 if (copy_from_user(buf, user_buf, buf_size)) 787 return -EFAULT; 788 789 if (sscanf(buf, "%d", &value) != 1) 790 return -EINVAL; 791 792 /* 793 * Our users expect 0 to be "CAM", but 0 isn't actually 794 * valid here. However, let's not confuse them and present 795 * IWL_POWER_INDEX_1 as "1", not "0". 796 */ 797 if (value == 0) 798 return -EINVAL; 799 else if (value > 0) 800 value -= 1; 801 802 if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) 803 return -EINVAL; 804 805 if (!iwl_is_ready_rf(priv)) 806 return -EAGAIN; 807 808 priv->power_data.debug_sleep_level_override = value; 809 810 mutex_lock(&priv->mutex); 811 iwl_power_update_mode(priv, true); 812 mutex_unlock(&priv->mutex); 813 814 return count; 815} 816 817static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, 818 char __user *user_buf, 819 size_t count, loff_t *ppos) 820{ 821 struct iwl_priv *priv = file->private_data; 822 char buf[10]; 823 int pos, value; 824 const size_t bufsz = sizeof(buf); 825 826 /* see the write function */ 827 value = priv->power_data.debug_sleep_level_override; 828 if (value >= 0) 829 value += 1; 830 831 pos = scnprintf(buf, bufsz, "%d\n", value); 832 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 833} 834 835static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, 836 char __user *user_buf, 837 size_t count, loff_t *ppos) 838{ 839 struct iwl_priv *priv = file->private_data; 840 char buf[200]; 841 int pos = 0, i; 842 const size_t bufsz = sizeof(buf); 843 struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd; 844 845 pos += scnprintf(buf + pos, bufsz - pos, 846 "flags: %#.2x\n", le16_to_cpu(cmd->flags)); 847 pos += scnprintf(buf + pos, bufsz - pos, 848 "RX/TX timeout: %d/%d usec\n", 849 le32_to_cpu(cmd->rx_data_timeout), 850 le32_to_cpu(cmd->tx_data_timeout)); 851 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 852 pos += scnprintf(buf + pos, bufsz - pos, 853 "sleep_interval[%d]: %d\n", i, 854 le32_to_cpu(cmd->sleep_interval[i])); 855 856 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 857} 858 859DEBUGFS_READ_WRITE_FILE_OPS(sram); 860DEBUGFS_READ_WRITE_FILE_OPS(log_event); 861DEBUGFS_READ_FILE_OPS(nvm); 862DEBUGFS_READ_FILE_OPS(stations); 863DEBUGFS_READ_FILE_OPS(channels); 864DEBUGFS_READ_FILE_OPS(status); 865DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 866DEBUGFS_READ_FILE_OPS(qos); 867DEBUGFS_READ_FILE_OPS(thermal_throttling); 868DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 869DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); 870DEBUGFS_READ_FILE_OPS(current_sleep_command); 871 872static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, 873 char __user *user_buf, 874 size_t count, loff_t *ppos) 875{ 876 struct iwl_priv *priv = file->private_data; 877 int pos = 0, ofs = 0; 878 int cnt = 0, entry; 879 struct iwl_tx_queue *txq; 880 struct iwl_queue *q; 881 struct iwl_rx_queue *rxq = &priv->rxq; 882 char *buf; 883 int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + 884 (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; 885 const u8 *ptr; 886 ssize_t ret; 887 888 if (!priv->txq) { 889 IWL_ERR(priv, "txq not ready\n"); 890 return -EAGAIN; 891 } 892 buf = kzalloc(bufsz, GFP_KERNEL); 893 if (!buf) { 894 IWL_ERR(priv, "Can not allocate buffer\n"); 895 return -ENOMEM; 896 } 897 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); 898 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 899 txq = &priv->txq[cnt]; 900 q = &txq->q; 901 pos += scnprintf(buf + pos, bufsz - pos, 902 "q[%d]: read_ptr: %u, write_ptr: %u\n", 903 cnt, q->read_ptr, q->write_ptr); 904 } 905 if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { 906 ptr = priv->tx_traffic; 907 pos += scnprintf(buf + pos, bufsz - pos, 908 "Tx Traffic idx: %u\n", priv->tx_traffic_idx); 909 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { 910 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; 911 entry++, ofs += 16) { 912 pos += scnprintf(buf + pos, bufsz - pos, 913 "0x%.4x ", ofs); 914 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, 915 buf + pos, bufsz - pos, 0); 916 pos += strlen(buf + pos); 917 if (bufsz - pos > 0) 918 buf[pos++] = '\n'; 919 } 920 } 921 } 922 923 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); 924 pos += scnprintf(buf + pos, bufsz - pos, 925 "read: %u, write: %u\n", 926 rxq->read, rxq->write); 927 928 if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { 929 ptr = priv->rx_traffic; 930 pos += scnprintf(buf + pos, bufsz - pos, 931 "Rx Traffic idx: %u\n", priv->rx_traffic_idx); 932 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { 933 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; 934 entry++, ofs += 16) { 935 pos += scnprintf(buf + pos, bufsz - pos, 936 "0x%.4x ", ofs); 937 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, 938 buf + pos, bufsz - pos, 0); 939 pos += strlen(buf + pos); 940 if (bufsz - pos > 0) 941 buf[pos++] = '\n'; 942 } 943 } 944 } 945 946 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 947 kfree(buf); 948 return ret; 949} 950 951static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, 952 const char __user *user_buf, 953 size_t count, loff_t *ppos) 954{ 955 struct iwl_priv *priv = file->private_data; 956 char buf[8]; 957 int buf_size; 958 int traffic_log; 959 960 memset(buf, 0, sizeof(buf)); 961 buf_size = min(count, sizeof(buf) - 1); 962 if (copy_from_user(buf, user_buf, buf_size)) 963 return -EFAULT; 964 if (sscanf(buf, "%d", &traffic_log) != 1) 965 return -EFAULT; 966 if (traffic_log == 0) 967 iwl_reset_traffic_log(priv); 968 969 return count; 970} 971 972static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, 973 char __user *user_buf, 974 size_t count, loff_t *ppos) { 975 976 struct iwl_priv *priv = file->private_data; 977 struct iwl_tx_queue *txq; 978 struct iwl_queue *q; 979 char *buf; 980 int pos = 0; 981 int cnt; 982 int ret; 983 const size_t bufsz = sizeof(char) * 64 * 984 priv->cfg->base_params->num_of_queues; 985 986 if (!priv->txq) { 987 IWL_ERR(priv, "txq not ready\n"); 988 return -EAGAIN; 989 } 990 buf = kzalloc(bufsz, GFP_KERNEL); 991 if (!buf) 992 return -ENOMEM; 993 994 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 995 txq = &priv->txq[cnt]; 996 q = &txq->q; 997 pos += scnprintf(buf + pos, bufsz - pos, 998 "hwq %.2d: read=%u write=%u stop=%d" 999 " swq_id=%#.2x (ac %d/hwq %d)\n", 1000 cnt, q->read_ptr, q->write_ptr, 1001 !!test_bit(cnt, priv->queue_stopped), 1002 txq->swq_id, txq->swq_id & 3, 1003 (txq->swq_id >> 2) & 0x1f); 1004 if (cnt >= 4) 1005 continue; 1006 /* for the ACs, display the stop count too */ 1007 pos += scnprintf(buf + pos, bufsz - pos, 1008 " stop-count: %d\n", 1009 atomic_read(&priv->queue_stop_count[cnt])); 1010 } 1011 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1012 kfree(buf); 1013 return ret; 1014} 1015 1016static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, 1017 char __user *user_buf, 1018 size_t count, loff_t *ppos) { 1019 1020 struct iwl_priv *priv = file->private_data; 1021 struct iwl_rx_queue *rxq = &priv->rxq; 1022 char buf[256]; 1023 int pos = 0; 1024 const size_t bufsz = sizeof(buf); 1025 1026 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", 1027 rxq->read); 1028 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", 1029 rxq->write); 1030 pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 1031 rxq->free_count); 1032 if (rxq->rb_stts) { 1033 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 1034 le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); 1035 } else { 1036 pos += scnprintf(buf + pos, bufsz - pos, 1037 "closed_rb_num: Not Allocated\n"); 1038 } 1039 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1040} 1041 1042static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, 1043 char __user *user_buf, 1044 size_t count, loff_t *ppos) 1045{ 1046 struct iwl_priv *priv = file->private_data; 1047 return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, 1048 user_buf, count, ppos); 1049} 1050 1051static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, 1052 char __user *user_buf, 1053 size_t count, loff_t *ppos) 1054{ 1055 struct iwl_priv *priv = file->private_data; 1056 return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, 1057 user_buf, count, ppos); 1058} 1059 1060static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, 1061 char __user *user_buf, 1062 size_t count, loff_t *ppos) 1063{ 1064 struct iwl_priv *priv = file->private_data; 1065 return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, 1066 user_buf, count, ppos); 1067} 1068 1069static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, 1070 char __user *user_buf, 1071 size_t count, loff_t *ppos) { 1072 1073 struct iwl_priv *priv = file->private_data; 1074 int pos = 0; 1075 int cnt = 0; 1076 char *buf; 1077 int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100; 1078 ssize_t ret; 1079 struct iwl_sensitivity_data *data; 1080 1081 data = &priv->sensitivity_data; 1082 buf = kzalloc(bufsz, GFP_KERNEL); 1083 if (!buf) { 1084 IWL_ERR(priv, "Can not allocate Buffer\n"); 1085 return -ENOMEM; 1086 } 1087 1088 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 1089 data->auto_corr_ofdm); 1090 pos += scnprintf(buf + pos, bufsz - pos, 1091 "auto_corr_ofdm_mrc:\t\t %u\n", 1092 data->auto_corr_ofdm_mrc); 1093 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 1094 data->auto_corr_ofdm_x1); 1095 pos += scnprintf(buf + pos, bufsz - pos, 1096 "auto_corr_ofdm_mrc_x1:\t\t %u\n", 1097 data->auto_corr_ofdm_mrc_x1); 1098 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 1099 data->auto_corr_cck); 1100 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 1101 data->auto_corr_cck_mrc); 1102 pos += scnprintf(buf + pos, bufsz - pos, 1103 "last_bad_plcp_cnt_ofdm:\t\t %u\n", 1104 data->last_bad_plcp_cnt_ofdm); 1105 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 1106 data->last_fa_cnt_ofdm); 1107 pos += scnprintf(buf + pos, bufsz - pos, 1108 "last_bad_plcp_cnt_cck:\t\t %u\n", 1109 data->last_bad_plcp_cnt_cck); 1110 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 1111 data->last_fa_cnt_cck); 1112 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 1113 data->nrg_curr_state); 1114 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 1115 data->nrg_prev_state); 1116 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 1117 for (cnt = 0; cnt < 10; cnt++) { 1118 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1119 data->nrg_value[cnt]); 1120 } 1121 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1122 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 1123 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 1124 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1125 data->nrg_silence_rssi[cnt]); 1126 } 1127 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1128 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 1129 data->nrg_silence_ref); 1130 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 1131 data->nrg_energy_idx); 1132 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 1133 data->nrg_silence_idx); 1134 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 1135 data->nrg_th_cck); 1136 pos += scnprintf(buf + pos, bufsz - pos, 1137 "nrg_auto_corr_silence_diff:\t %u\n", 1138 data->nrg_auto_corr_silence_diff); 1139 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 1140 data->num_in_cck_no_fa); 1141 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 1142 data->nrg_th_ofdm); 1143 1144 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1145 kfree(buf); 1146 return ret; 1147} 1148 1149 1150static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, 1151 char __user *user_buf, 1152 size_t count, loff_t *ppos) { 1153 1154 struct iwl_priv *priv = file->private_data; 1155 int pos = 0; 1156 int cnt = 0; 1157 char *buf; 1158 int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100; 1159 ssize_t ret; 1160 struct iwl_chain_noise_data *data; 1161 1162 data = &priv->chain_noise_data; 1163 buf = kzalloc(bufsz, GFP_KERNEL); 1164 if (!buf) { 1165 IWL_ERR(priv, "Can not allocate Buffer\n"); 1166 return -ENOMEM; 1167 } 1168 1169 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 1170 data->active_chains); 1171 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 1172 data->chain_noise_a); 1173 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 1174 data->chain_noise_b); 1175 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 1176 data->chain_noise_c); 1177 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 1178 data->chain_signal_a); 1179 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 1180 data->chain_signal_b); 1181 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 1182 data->chain_signal_c); 1183 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 1184 data->beacon_count); 1185 1186 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 1187 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1188 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1189 data->disconn_array[cnt]); 1190 } 1191 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1192 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 1193 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1194 pos += scnprintf(buf + pos, bufsz - pos, " %u", 1195 data->delta_gain_code[cnt]); 1196 } 1197 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1198 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 1199 data->radio_write); 1200 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 1201 data->state); 1202 1203 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1204 kfree(buf); 1205 return ret; 1206} 1207 1208static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, 1209 char __user *user_buf, 1210 size_t count, loff_t *ppos) 1211{ 1212 struct iwl_priv *priv = file->private_data; 1213 char buf[60]; 1214 int pos = 0; 1215 const size_t bufsz = sizeof(buf); 1216 u32 pwrsave_status; 1217 1218 pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & 1219 CSR_GP_REG_POWER_SAVE_STATUS_MSK; 1220 1221 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 1222 pos += scnprintf(buf + pos, bufsz - pos, "%s\n", 1223 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 1224 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 1225 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 1226 "error"); 1227 1228 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1229} 1230 1231static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, 1232 const char __user *user_buf, 1233 size_t count, loff_t *ppos) 1234{ 1235 struct iwl_priv *priv = file->private_data; 1236 char buf[8]; 1237 int buf_size; 1238 int clear; 1239 1240 memset(buf, 0, sizeof(buf)); 1241 buf_size = min(count, sizeof(buf) - 1); 1242 if (copy_from_user(buf, user_buf, buf_size)) 1243 return -EFAULT; 1244 if (sscanf(buf, "%d", &clear) != 1) 1245 return -EFAULT; 1246 1247 /* make request to uCode to retrieve statistics information */ 1248 mutex_lock(&priv->mutex); 1249 iwl_send_statistics_request(priv, CMD_SYNC, true); 1250 mutex_unlock(&priv->mutex); 1251 1252 return count; 1253} 1254 1255static ssize_t iwl_dbgfs_csr_write(struct file *file, 1256 const char __user *user_buf, 1257 size_t count, loff_t *ppos) 1258{ 1259 struct iwl_priv *priv = file->private_data; 1260 char buf[8]; 1261 int buf_size; 1262 int csr; 1263 1264 memset(buf, 0, sizeof(buf)); 1265 buf_size = min(count, sizeof(buf) - 1); 1266 if (copy_from_user(buf, user_buf, buf_size)) 1267 return -EFAULT; 1268 if (sscanf(buf, "%d", &csr) != 1) 1269 return -EFAULT; 1270 1271 if (priv->cfg->ops->lib->dump_csr) 1272 priv->cfg->ops->lib->dump_csr(priv); 1273 1274 return count; 1275} 1276 1277static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, 1278 char __user *user_buf, 1279 size_t count, loff_t *ppos) { 1280 1281 struct iwl_priv *priv = file->private_data; 1282 int pos = 0; 1283 char buf[128]; 1284 const size_t bufsz = sizeof(buf); 1285 1286 pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", 1287 priv->event_log.ucode_trace ? "On" : "Off"); 1288 pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", 1289 priv->event_log.non_wraps_count); 1290 pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", 1291 priv->event_log.wraps_once_count); 1292 pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", 1293 priv->event_log.wraps_more_count); 1294 1295 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1296} 1297 1298static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, 1299 const char __user *user_buf, 1300 size_t count, loff_t *ppos) 1301{ 1302 struct iwl_priv *priv = file->private_data; 1303 char buf[8]; 1304 int buf_size; 1305 int trace; 1306 1307 memset(buf, 0, sizeof(buf)); 1308 buf_size = min(count, sizeof(buf) - 1); 1309 if (copy_from_user(buf, user_buf, buf_size)) 1310 return -EFAULT; 1311 if (sscanf(buf, "%d", &trace) != 1) 1312 return -EFAULT; 1313 1314 if (trace) { 1315 priv->event_log.ucode_trace = true; 1316 /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ 1317 mod_timer(&priv->ucode_trace, 1318 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); 1319 } else { 1320 priv->event_log.ucode_trace = false; 1321 del_timer_sync(&priv->ucode_trace); 1322 } 1323 1324 return count; 1325} 1326 1327static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, 1328 char __user *user_buf, 1329 size_t count, loff_t *ppos) { 1330 1331 struct iwl_priv *priv = file->private_data; 1332 int len = 0; 1333 char buf[20]; 1334 1335 len = sprintf(buf, "0x%04X\n", 1336 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags)); 1337 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1338} 1339 1340static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, 1341 char __user *user_buf, 1342 size_t count, loff_t *ppos) { 1343 1344 struct iwl_priv *priv = file->private_data; 1345 int len = 0; 1346 char buf[20]; 1347 1348 len = sprintf(buf, "0x%04X\n", 1349 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags)); 1350 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1351} 1352 1353static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, 1354 char __user *user_buf, 1355 size_t count, loff_t *ppos) 1356{ 1357 struct iwl_priv *priv = file->private_data; 1358 char *buf; 1359 int pos = 0; 1360 ssize_t ret = -EFAULT; 1361 1362 if (priv->cfg->ops->lib->dump_fh) { 1363 ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); 1364 if (buf) { 1365 ret = simple_read_from_buffer(user_buf, 1366 count, ppos, buf, pos); 1367 kfree(buf); 1368 } 1369 } 1370 1371 return ret; 1372} 1373 1374static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, 1375 char __user *user_buf, 1376 size_t count, loff_t *ppos) { 1377 1378 struct iwl_priv *priv = file->private_data; 1379 int pos = 0; 1380 char buf[12]; 1381 const size_t bufsz = sizeof(buf); 1382 1383 pos += scnprintf(buf + pos, bufsz - pos, "%d\n", 1384 priv->missed_beacon_threshold); 1385 1386 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1387} 1388 1389static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, 1390 const char __user *user_buf, 1391 size_t count, loff_t *ppos) 1392{ 1393 struct iwl_priv *priv = file->private_data; 1394 char buf[8]; 1395 int buf_size; 1396 int missed; 1397 1398 memset(buf, 0, sizeof(buf)); 1399 buf_size = min(count, sizeof(buf) - 1); 1400 if (copy_from_user(buf, user_buf, buf_size)) 1401 return -EFAULT; 1402 if (sscanf(buf, "%d", &missed) != 1) 1403 return -EINVAL; 1404 1405 if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || 1406 missed > IWL_MISSED_BEACON_THRESHOLD_MAX) 1407 priv->missed_beacon_threshold = 1408 IWL_MISSED_BEACON_THRESHOLD_DEF; 1409 else 1410 priv->missed_beacon_threshold = missed; 1411 1412 return count; 1413} 1414 1415static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, 1416 char __user *user_buf, 1417 size_t count, loff_t *ppos) { 1418 1419 struct iwl_priv *priv = file->private_data; 1420 int pos = 0; 1421 char buf[12]; 1422 const size_t bufsz = sizeof(buf); 1423 1424 pos += scnprintf(buf + pos, bufsz - pos, "%u\n", 1425 priv->cfg->base_params->plcp_delta_threshold); 1426 1427 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1428} 1429 1430static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, 1431 const char __user *user_buf, 1432 size_t count, loff_t *ppos) { 1433 1434 struct iwl_priv *priv = file->private_data; 1435 char buf[8]; 1436 int buf_size; 1437 int plcp; 1438 1439 memset(buf, 0, sizeof(buf)); 1440 buf_size = min(count, sizeof(buf) - 1); 1441 if (copy_from_user(buf, user_buf, buf_size)) 1442 return -EFAULT; 1443 if (sscanf(buf, "%d", &plcp) != 1) 1444 return -EINVAL; 1445 if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || 1446 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) 1447 priv->cfg->base_params->plcp_delta_threshold = 1448 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; 1449 else 1450 priv->cfg->base_params->plcp_delta_threshold = plcp; 1451 return count; 1452} 1453 1454static ssize_t iwl_dbgfs_force_reset_read(struct file *file, 1455 char __user *user_buf, 1456 size_t count, loff_t *ppos) { 1457 1458 struct iwl_priv *priv = file->private_data; 1459 int i, pos = 0; 1460 char buf[300]; 1461 const size_t bufsz = sizeof(buf); 1462 struct iwl_force_reset *force_reset; 1463 1464 for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { 1465 force_reset = &priv->force_reset[i]; 1466 pos += scnprintf(buf + pos, bufsz - pos, 1467 "Force reset method %d\n", i); 1468 pos += scnprintf(buf + pos, bufsz - pos, 1469 "\tnumber of reset request: %d\n", 1470 force_reset->reset_request_count); 1471 pos += scnprintf(buf + pos, bufsz - pos, 1472 "\tnumber of reset request success: %d\n", 1473 force_reset->reset_success_count); 1474 pos += scnprintf(buf + pos, bufsz - pos, 1475 "\tnumber of reset request reject: %d\n", 1476 force_reset->reset_reject_count); 1477 pos += scnprintf(buf + pos, bufsz - pos, 1478 "\treset duration: %lu\n", 1479 force_reset->reset_duration); 1480 } 1481 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1482} 1483 1484static ssize_t iwl_dbgfs_force_reset_write(struct file *file, 1485 const char __user *user_buf, 1486 size_t count, loff_t *ppos) { 1487 1488 struct iwl_priv *priv = file->private_data; 1489 char buf[8]; 1490 int buf_size; 1491 int reset, ret; 1492 1493 memset(buf, 0, sizeof(buf)); 1494 buf_size = min(count, sizeof(buf) - 1); 1495 if (copy_from_user(buf, user_buf, buf_size)) 1496 return -EFAULT; 1497 if (sscanf(buf, "%d", &reset) != 1) 1498 return -EINVAL; 1499 switch (reset) { 1500 case IWL_RF_RESET: 1501 case IWL_FW_RESET: 1502 ret = iwl_force_reset(priv, reset, true); 1503 break; 1504 default: 1505 return -EINVAL; 1506 } 1507 return ret ? ret : count; 1508} 1509 1510static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, 1511 const char __user *user_buf, 1512 size_t count, loff_t *ppos) { 1513 1514 struct iwl_priv *priv = file->private_data; 1515 char buf[8]; 1516 int buf_size; 1517 int flush; 1518 1519 memset(buf, 0, sizeof(buf)); 1520 buf_size = min(count, sizeof(buf) - 1); 1521 if (copy_from_user(buf, user_buf, buf_size)) 1522 return -EFAULT; 1523 if (sscanf(buf, "%d", &flush) != 1) 1524 return -EINVAL; 1525 1526 if (iwl_is_rfkill(priv)) 1527 return -EFAULT; 1528 1529 priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL); 1530 1531 return count; 1532} 1533 1534static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, 1535 char __user *user_buf, 1536 size_t count, loff_t *ppos) 1537{ 1538 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1539 1540 return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, 1541 user_buf, count, ppos); 1542} 1543 1544static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, 1545 const char __user *user_buf, 1546 size_t count, loff_t *ppos) { 1547 1548 struct iwl_priv *priv = file->private_data; 1549 char buf[8]; 1550 int buf_size; 1551 int timeout; 1552 1553 memset(buf, 0, sizeof(buf)); 1554 buf_size = min(count, sizeof(buf) - 1); 1555 if (copy_from_user(buf, user_buf, buf_size)) 1556 return -EFAULT; 1557 if (sscanf(buf, "%d", &timeout) != 1) 1558 return -EINVAL; 1559 if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) 1560 timeout = IWL_DEF_WD_TIMEOUT; 1561 1562 priv->cfg->base_params->wd_timeout = timeout; 1563 iwl_setup_watchdog(priv); 1564 return count; 1565} 1566 1567static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, 1568 char __user *user_buf, 1569 size_t count, loff_t *ppos) { 1570 1571 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1572 int pos = 0; 1573 char buf[200]; 1574 const size_t bufsz = sizeof(buf); 1575 1576 if (!priv->bt_enable_flag) { 1577 pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); 1578 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1579 } 1580 pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", 1581 priv->bt_enable_flag); 1582 pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n", 1583 priv->bt_full_concurrent ? "full concurrency" : "3-wire"); 1584 pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, " 1585 "last traffic notif: %d\n", 1586 priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); 1587 pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " 1588 "kill_ack_mask: %x, kill_cts_mask: %x\n", 1589 priv->bt_ch_announce, priv->kill_ack_mask, 1590 priv->kill_cts_mask); 1591 1592 pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); 1593 switch (priv->bt_traffic_load) { 1594 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: 1595 pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n"); 1596 break; 1597 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: 1598 pos += scnprintf(buf + pos, bufsz - pos, "High\n"); 1599 break; 1600 case IWL_BT_COEX_TRAFFIC_LOAD_LOW: 1601 pos += scnprintf(buf + pos, bufsz - pos, "Low\n"); 1602 break; 1603 case IWL_BT_COEX_TRAFFIC_LOAD_NONE: 1604 default: 1605 pos += scnprintf(buf + pos, bufsz - pos, "None\n"); 1606 break; 1607 } 1608 1609 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1610} 1611 1612static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, 1613 char __user *user_buf, 1614 size_t count, loff_t *ppos) 1615{ 1616 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 1617 1618 int pos = 0; 1619 char buf[40]; 1620 const size_t bufsz = sizeof(buf); 1621 1622 if (priv->cfg->ht_params) 1623 pos += scnprintf(buf + pos, bufsz - pos, 1624 "use %s for aggregation\n", 1625 (priv->cfg->ht_params->use_rts_for_aggregation) ? 1626 "rts/cts" : "cts-to-self"); 1627 else 1628 pos += scnprintf(buf + pos, bufsz - pos, "N/A"); 1629 1630 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1631} 1632 1633static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, 1634 const char __user *user_buf, 1635 size_t count, loff_t *ppos) { 1636 1637 struct iwl_priv *priv = file->private_data; 1638 char buf[8]; 1639 int buf_size; 1640 int rts; 1641 1642 if (!priv->cfg->ht_params) 1643 return -EINVAL; 1644 1645 memset(buf, 0, sizeof(buf)); 1646 buf_size = min(count, sizeof(buf) - 1); 1647 if (copy_from_user(buf, user_buf, buf_size)) 1648 return -EFAULT; 1649 if (sscanf(buf, "%d", &rts) != 1) 1650 return -EINVAL; 1651 if (rts) 1652 priv->cfg->ht_params->use_rts_for_aggregation = true; 1653 else 1654 priv->cfg->ht_params->use_rts_for_aggregation = false; 1655 return count; 1656} 1657 1658static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, 1659 char __user *user_buf, 1660 size_t count, loff_t *ppos) 1661{ 1662 struct iwl_priv *priv = file->private_data; 1663 1664 if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) 1665 return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( 1666 file, user_buf, count, ppos); 1667 else 1668 return -ENODATA; 1669} 1670DEBUGFS_READ_FILE_OPS(rx_statistics); 1671DEBUGFS_READ_FILE_OPS(tx_statistics); 1672DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 1673DEBUGFS_READ_FILE_OPS(rx_queue); 1674DEBUGFS_READ_FILE_OPS(tx_queue); 1675DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 1676DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 1677DEBUGFS_READ_FILE_OPS(ucode_general_stats); 1678DEBUGFS_READ_FILE_OPS(sensitivity); 1679DEBUGFS_READ_FILE_OPS(chain_noise); 1680DEBUGFS_READ_FILE_OPS(power_save_status); 1681DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); 1682DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); 1683DEBUGFS_WRITE_FILE_OPS(csr); 1684DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); 1685DEBUGFS_READ_FILE_OPS(fh_reg); 1686DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 1687DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); 1688DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1689DEBUGFS_READ_FILE_OPS(rxon_flags); 1690DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1691DEBUGFS_WRITE_FILE_OPS(txfifo_flush); 1692DEBUGFS_READ_FILE_OPS(ucode_bt_stats); 1693DEBUGFS_WRITE_FILE_OPS(wd_timeout); 1694DEBUGFS_READ_FILE_OPS(bt_traffic); 1695DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); 1696DEBUGFS_READ_FILE_OPS(reply_tx_error); 1697 1698/* 1699 * Create the debugfs files and directories 1700 * 1701 */ 1702int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 1703{ 1704 struct dentry *phyd = priv->hw->wiphy->debugfsdir; 1705 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 1706 1707 dir_drv = debugfs_create_dir(name, phyd); 1708 if (!dir_drv) 1709 return -ENOMEM; 1710 1711 priv->debugfs_dir = dir_drv; 1712 1713 dir_data = debugfs_create_dir("data", dir_drv); 1714 if (!dir_data) 1715 goto err; 1716 dir_rf = debugfs_create_dir("rf", dir_drv); 1717 if (!dir_rf) 1718 goto err; 1719 dir_debug = debugfs_create_dir("debug", dir_drv); 1720 if (!dir_debug) 1721 goto err; 1722 1723 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 1724 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 1725 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); 1726 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 1727 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 1728 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1729 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1730 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1731 if (!priv->cfg->base_params->broken_powersave) { 1732 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, 1733 S_IWUSR | S_IRUSR); 1734 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); 1735 } 1736 DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); 1737 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 1738 DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); 1739 DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); 1740 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); 1741 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 1742 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 1743 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 1744 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); 1745 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); 1746 DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); 1747 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 1748 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 1749 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); 1750 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 1751 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 1752 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 1753 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 1754 if (priv->cfg->ops->lib->dev_txfifo_flush) 1755 DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); 1756 DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); 1757 1758 if (priv->cfg->base_params->sensitivity_calib_by_driver) 1759 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 1760 if (priv->cfg->base_params->chain_noise_calib_by_driver) 1761 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 1762 if (priv->cfg->base_params->ucode_tracing) 1763 DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); 1764 if (iwl_bt_statistics(priv)) 1765 DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); 1766 DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); 1767 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1768 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1769 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 1770 if (iwl_advanced_bt_coexist(priv)) 1771 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); 1772 if (priv->cfg->base_params->sensitivity_calib_by_driver) 1773 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 1774 &priv->disable_sens_cal); 1775 if (priv->cfg->base_params->chain_noise_calib_by_driver) 1776 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 1777 &priv->disable_chain_noise_cal); 1778 if (priv->cfg->base_params->tx_power_by_driver) 1779 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, 1780 &priv->disable_tx_power_cal); 1781 return 0; 1782 1783err: 1784 IWL_ERR(priv, "Can't create the debugfs directory\n"); 1785 iwl_dbgfs_unregister(priv); 1786 return -ENOMEM; 1787} 1788 1789/** 1790 * Remove the debugfs files and directories 1791 * 1792 */ 1793void iwl_dbgfs_unregister(struct iwl_priv *priv) 1794{ 1795 if (!priv->debugfs_dir) 1796 return; 1797 1798 debugfs_remove_recursive(priv->debugfs_dir); 1799 priv->debugfs_dir = NULL; 1800} 1801 1802 1803 1804