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