iwl-debugfs.c revision 030b865520c3e26f4a316852aa022a22c4948907
1/****************************************************************************** 2 * 3 * GPL LICENSE SUMMARY 4 * 5 * Copyright(c) 2008 - 2009 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/kernel.h> 30#include <linux/module.h> 31#include <linux/debugfs.h> 32 33#include <linux/ieee80211.h> 34#include <net/mac80211.h> 35 36 37#include "iwl-dev.h" 38#include "iwl-debug.h" 39#include "iwl-core.h" 40#include "iwl-io.h" 41 42 43/* create and remove of files */ 44#define DEBUGFS_ADD_DIR(name, parent) do { \ 45 dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ 46 if (!(dbgfs->dir_##name)) \ 47 goto err; \ 48} while (0) 49 50#define DEBUGFS_ADD_FILE(name, parent) do { \ 51 dbgfs->dbgfs_##parent##_files.file_##name = \ 52 debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \ 53 &iwl_dbgfs_##name##_ops); \ 54 if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ 55 goto err; \ 56} while (0) 57 58#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 59 dbgfs->dbgfs_##parent##_files.file_##name = \ 60 debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \ 61 if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ 62 || !dbgfs->dbgfs_##parent##_files.file_##name) \ 63 goto err; \ 64} while (0) 65 66#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ 67 dbgfs->dbgfs_##parent##_files.file_##name = \ 68 debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \ 69 if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ 70 || !dbgfs->dbgfs_##parent##_files.file_##name) \ 71 goto err; \ 72} while (0) 73 74#define DEBUGFS_REMOVE(name) do { \ 75 debugfs_remove(name); \ 76 name = NULL; \ 77} while (0); 78 79/* file operation */ 80#define DEBUGFS_READ_FUNC(name) \ 81static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ 82 char __user *user_buf, \ 83 size_t count, loff_t *ppos); 84 85#define DEBUGFS_WRITE_FUNC(name) \ 86static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ 87 const char __user *user_buf, \ 88 size_t count, loff_t *ppos); 89 90 91static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) 92{ 93 file->private_data = inode->i_private; 94 return 0; 95} 96 97#define DEBUGFS_READ_FILE_OPS(name) \ 98 DEBUGFS_READ_FUNC(name); \ 99static const struct file_operations iwl_dbgfs_##name##_ops = { \ 100 .read = iwl_dbgfs_##name##_read, \ 101 .open = iwl_dbgfs_open_file_generic, \ 102}; 103 104#define DEBUGFS_WRITE_FILE_OPS(name) \ 105 DEBUGFS_WRITE_FUNC(name); \ 106static const struct file_operations iwl_dbgfs_##name##_ops = { \ 107 .write = iwl_dbgfs_##name##_write, \ 108 .open = iwl_dbgfs_open_file_generic, \ 109}; 110 111 112#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 113 DEBUGFS_READ_FUNC(name); \ 114 DEBUGFS_WRITE_FUNC(name); \ 115static const struct file_operations iwl_dbgfs_##name##_ops = { \ 116 .write = iwl_dbgfs_##name##_write, \ 117 .read = iwl_dbgfs_##name##_read, \ 118 .open = iwl_dbgfs_open_file_generic, \ 119}; 120 121 122static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, 123 char __user *user_buf, 124 size_t count, loff_t *ppos) { 125 126 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 127 char buf[256]; 128 int pos = 0; 129 const size_t bufsz = sizeof(buf); 130 131 pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", 132 priv->tx_stats[0].cnt); 133 pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", 134 priv->tx_stats[1].cnt); 135 pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", 136 priv->tx_stats[2].cnt); 137 138 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 139} 140 141static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, 142 char __user *user_buf, 143 size_t count, loff_t *ppos) { 144 145 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 146 char buf[256]; 147 int pos = 0; 148 const size_t bufsz = sizeof(buf); 149 150 pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", 151 priv->rx_stats[0].cnt); 152 pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", 153 priv->rx_stats[1].cnt); 154 pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", 155 priv->rx_stats[2].cnt); 156 157 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 158} 159 160#define BYTE1_MASK 0x000000ff; 161#define BYTE2_MASK 0x0000ffff; 162#define BYTE3_MASK 0x00ffffff; 163static ssize_t iwl_dbgfs_sram_read(struct file *file, 164 char __user *user_buf, 165 size_t count, loff_t *ppos) 166{ 167 u32 val; 168 char buf[1024]; 169 ssize_t ret; 170 int i; 171 int pos = 0; 172 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 173 const size_t bufsz = sizeof(buf); 174 175 for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { 176 val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ 177 priv->dbgfs->sram_len - i); 178 if (i < 4) { 179 switch (i) { 180 case 1: 181 val &= BYTE1_MASK; 182 break; 183 case 2: 184 val &= BYTE2_MASK; 185 break; 186 case 3: 187 val &= BYTE3_MASK; 188 break; 189 } 190 } 191 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); 192 } 193 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 194 195 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 196 return ret; 197} 198 199static ssize_t iwl_dbgfs_sram_write(struct file *file, 200 const char __user *user_buf, 201 size_t count, loff_t *ppos) 202{ 203 struct iwl_priv *priv = file->private_data; 204 char buf[64]; 205 int buf_size; 206 u32 offset, len; 207 208 memset(buf, 0, sizeof(buf)); 209 buf_size = min(count, sizeof(buf) - 1); 210 if (copy_from_user(buf, user_buf, buf_size)) 211 return -EFAULT; 212 213 if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 214 priv->dbgfs->sram_offset = offset; 215 priv->dbgfs->sram_len = len; 216 } else { 217 priv->dbgfs->sram_offset = 0; 218 priv->dbgfs->sram_len = 0; 219 } 220 221 return count; 222} 223 224static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 225 size_t count, loff_t *ppos) 226{ 227 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 228 struct iwl_station_entry *station; 229 int max_sta = priv->hw_params.max_stations; 230 char *buf; 231 int i, j, pos = 0; 232 ssize_t ret; 233 /* Add 30 for initial string */ 234 const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); 235 236 buf = kmalloc(bufsz, GFP_KERNEL); 237 if (!buf) 238 return -ENOMEM; 239 240 pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", 241 priv->num_stations); 242 243 for (i = 0; i < max_sta; i++) { 244 station = &priv->stations[i]; 245 if (station->used) { 246 pos += scnprintf(buf + pos, bufsz - pos, 247 "station %d:\ngeneral data:\n", i+1); 248 pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", 249 station->sta.sta.sta_id); 250 pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", 251 station->sta.mode); 252 pos += scnprintf(buf + pos, bufsz - pos, 253 "flags: 0x%x\n", 254 station->sta.station_flags_msk); 255 pos += scnprintf(buf + pos, bufsz - pos, 256 "ps_status: %u\n", station->ps_status); 257 pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); 258 pos += scnprintf(buf + pos, bufsz - pos, 259 "seq_num\t\ttxq_id"); 260 pos += scnprintf(buf + pos, bufsz - pos, 261 "\tframe_count\twait_for_ba\t"); 262 pos += scnprintf(buf + pos, bufsz - pos, 263 "start_idx\tbitmap0\t"); 264 pos += scnprintf(buf + pos, bufsz - pos, 265 "bitmap1\trate_n_flags"); 266 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 267 268 for (j = 0; j < MAX_TID_COUNT; j++) { 269 pos += scnprintf(buf + pos, bufsz - pos, 270 "[%d]:\t\t%u", j, 271 station->tid[j].seq_number); 272 pos += scnprintf(buf + pos, bufsz - pos, 273 "\t%u\t\t%u\t\t%u\t\t", 274 station->tid[j].agg.txq_id, 275 station->tid[j].agg.frame_count, 276 station->tid[j].agg.wait_for_ba); 277 pos += scnprintf(buf + pos, bufsz - pos, 278 "%u\t%llu\t%u", 279 station->tid[j].agg.start_idx, 280 (unsigned long long)station->tid[j].agg.bitmap, 281 station->tid[j].agg.rate_n_flags); 282 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 283 } 284 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 285 } 286 } 287 288 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 289 kfree(buf); 290 return ret; 291} 292 293static ssize_t iwl_dbgfs_nvm_read(struct file *file, 294 char __user *user_buf, 295 size_t count, 296 loff_t *ppos) 297{ 298 ssize_t ret; 299 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 300 int pos = 0, ofs = 0, buf_size = 0; 301 const u8 *ptr; 302 char *buf; 303 size_t eeprom_len = priv->cfg->eeprom_size; 304 buf_size = 4 * eeprom_len + 256; 305 306 if (eeprom_len % 16) { 307 IWL_ERR(priv, "NVM size is not multiple of 16.\n"); 308 return -ENODATA; 309 } 310 311 /* 4 characters for byte 0xYY */ 312 buf = kzalloc(buf_size, GFP_KERNEL); 313 if (!buf) { 314 IWL_ERR(priv, "Can not allocate Buffer\n"); 315 return -ENOMEM; 316 } 317 318 ptr = priv->eeprom; 319 if (!ptr) { 320 IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); 321 return -ENOMEM; 322 } 323 pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", 324 (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) 325 ? "OTP" : "EEPROM"); 326 for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { 327 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); 328 hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, 329 buf_size - pos, 0); 330 pos += strlen(buf); 331 if (buf_size - pos > 0) 332 buf[pos++] = '\n'; 333 } 334 335 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 336 kfree(buf); 337 return ret; 338} 339 340static ssize_t iwl_dbgfs_log_event_write(struct file *file, 341 const char __user *user_buf, 342 size_t count, loff_t *ppos) 343{ 344 struct iwl_priv *priv = file->private_data; 345 u32 event_log_flag; 346 char buf[8]; 347 int buf_size; 348 349 memset(buf, 0, sizeof(buf)); 350 buf_size = min(count, sizeof(buf) - 1); 351 if (copy_from_user(buf, user_buf, buf_size)) 352 return -EFAULT; 353 if (sscanf(buf, "%d", &event_log_flag) != 1) 354 return -EFAULT; 355 if (event_log_flag == 1) 356 iwl_dump_nic_event_log(priv); 357 358 return count; 359} 360 361 362 363static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, 364 size_t count, loff_t *ppos) 365{ 366 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 367 struct ieee80211_channel *channels = NULL; 368 const struct ieee80211_supported_band *supp_band = NULL; 369 int pos = 0, i, bufsz = PAGE_SIZE; 370 char *buf; 371 ssize_t ret; 372 373 if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) 374 return -EAGAIN; 375 376 buf = kzalloc(bufsz, GFP_KERNEL); 377 if (!buf) { 378 IWL_ERR(priv, "Can not allocate Buffer\n"); 379 return -ENOMEM; 380 } 381 382 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); 383 if (supp_band) { 384 channels = supp_band->channels; 385 386 pos += scnprintf(buf + pos, bufsz - pos, 387 "Displaying %d channels in 2.4GHz band 802.11bg):\n", 388 supp_band->n_channels); 389 390 for (i = 0; i < supp_band->n_channels; i++) 391 pos += scnprintf(buf + pos, bufsz - pos, 392 "%d: %ddBm: BSS%s%s, %s.\n", 393 ieee80211_frequency_to_channel( 394 channels[i].center_freq), 395 channels[i].max_power, 396 channels[i].flags & IEEE80211_CHAN_RADAR ? 397 " (IEEE 802.11h required)" : "", 398 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 399 || (channels[i].flags & 400 IEEE80211_CHAN_RADAR)) ? "" : 401 ", IBSS", 402 channels[i].flags & 403 IEEE80211_CHAN_PASSIVE_SCAN ? 404 "passive only" : "active/passive"); 405 } 406 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); 407 if (supp_band) { 408 channels = supp_band->channels; 409 410 pos += scnprintf(buf + pos, bufsz - pos, 411 "Displaying %d channels in 5.2GHz band (802.11a)\n", 412 supp_band->n_channels); 413 414 for (i = 0; i < supp_band->n_channels; i++) 415 pos += scnprintf(buf + pos, bufsz - pos, 416 "%d: %ddBm: BSS%s%s, %s.\n", 417 ieee80211_frequency_to_channel( 418 channels[i].center_freq), 419 channels[i].max_power, 420 channels[i].flags & IEEE80211_CHAN_RADAR ? 421 " (IEEE 802.11h required)" : "", 422 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) 423 || (channels[i].flags & 424 IEEE80211_CHAN_RADAR)) ? "" : 425 ", IBSS", 426 channels[i].flags & 427 IEEE80211_CHAN_PASSIVE_SCAN ? 428 "passive only" : "active/passive"); 429 } 430 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 431 kfree(buf); 432 return ret; 433} 434 435static ssize_t iwl_dbgfs_status_read(struct file *file, 436 char __user *user_buf, 437 size_t count, loff_t *ppos) { 438 439 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 440 char buf[512]; 441 int pos = 0; 442 const size_t bufsz = sizeof(buf); 443 444 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", 445 test_bit(STATUS_HCMD_ACTIVE, &priv->status)); 446 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", 447 test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); 448 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", 449 test_bit(STATUS_INT_ENABLED, &priv->status)); 450 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", 451 test_bit(STATUS_RF_KILL_HW, &priv->status)); 452 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", 453 test_bit(STATUS_INIT, &priv->status)); 454 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", 455 test_bit(STATUS_ALIVE, &priv->status)); 456 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", 457 test_bit(STATUS_READY, &priv->status)); 458 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", 459 test_bit(STATUS_TEMPERATURE, &priv->status)); 460 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", 461 test_bit(STATUS_GEO_CONFIGURED, &priv->status)); 462 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", 463 test_bit(STATUS_EXIT_PENDING, &priv->status)); 464 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", 465 test_bit(STATUS_STATISTICS, &priv->status)); 466 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", 467 test_bit(STATUS_SCANNING, &priv->status)); 468 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", 469 test_bit(STATUS_SCAN_ABORTING, &priv->status)); 470 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", 471 test_bit(STATUS_SCAN_HW, &priv->status)); 472 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", 473 test_bit(STATUS_POWER_PMI, &priv->status)); 474 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", 475 test_bit(STATUS_FW_ERROR, &priv->status)); 476 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", 477 test_bit(STATUS_MODE_PENDING, &priv->status)); 478 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 479} 480 481static ssize_t iwl_dbgfs_interrupt_read(struct file *file, 482 char __user *user_buf, 483 size_t count, loff_t *ppos) { 484 485 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 486 int pos = 0; 487 int cnt = 0; 488 char *buf; 489 int bufsz = 24 * 64; /* 24 items * 64 char per item */ 490 ssize_t ret; 491 492 buf = kzalloc(bufsz, GFP_KERNEL); 493 if (!buf) { 494 IWL_ERR(priv, "Can not allocate Buffer\n"); 495 return -ENOMEM; 496 } 497 498 pos += scnprintf(buf + pos, bufsz - pos, 499 "Interrupt Statistics Report:\n"); 500 501 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 502 priv->isr_stats.hw); 503 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 504 priv->isr_stats.sw); 505 if (priv->isr_stats.sw > 0) { 506 pos += scnprintf(buf + pos, bufsz - pos, 507 "\tLast Restarting Code: 0x%X\n", 508 priv->isr_stats.sw_err); 509 } 510#ifdef CONFIG_IWLWIFI_DEBUG 511 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 512 priv->isr_stats.sch); 513 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 514 priv->isr_stats.alive); 515#endif 516 pos += scnprintf(buf + pos, bufsz - pos, 517 "HW RF KILL switch toggled:\t %u\n", 518 priv->isr_stats.rfkill); 519 520 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 521 priv->isr_stats.ctkill); 522 523 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 524 priv->isr_stats.wakeup); 525 526 pos += scnprintf(buf + pos, bufsz - pos, 527 "Rx command responses:\t\t %u\n", 528 priv->isr_stats.rx); 529 for (cnt = 0; cnt < REPLY_MAX; cnt++) { 530 if (priv->isr_stats.rx_handlers[cnt] > 0) 531 pos += scnprintf(buf + pos, bufsz - pos, 532 "\tRx handler[%36s]:\t\t %u\n", 533 get_cmd_string(cnt), 534 priv->isr_stats.rx_handlers[cnt]); 535 } 536 537 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 538 priv->isr_stats.tx); 539 540 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 541 priv->isr_stats.unhandled); 542 543 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 544 kfree(buf); 545 return ret; 546} 547 548static ssize_t iwl_dbgfs_interrupt_write(struct file *file, 549 const char __user *user_buf, 550 size_t count, loff_t *ppos) 551{ 552 struct iwl_priv *priv = file->private_data; 553 char buf[8]; 554 int buf_size; 555 u32 reset_flag; 556 557 memset(buf, 0, sizeof(buf)); 558 buf_size = min(count, sizeof(buf) - 1); 559 if (copy_from_user(buf, user_buf, buf_size)) 560 return -EFAULT; 561 if (sscanf(buf, "%x", &reset_flag) != 1) 562 return -EFAULT; 563 if (reset_flag == 0) 564 iwl_clear_isr_stats(priv); 565 566 return count; 567} 568 569 570DEBUGFS_READ_WRITE_FILE_OPS(sram); 571DEBUGFS_WRITE_FILE_OPS(log_event); 572DEBUGFS_READ_FILE_OPS(nvm); 573DEBUGFS_READ_FILE_OPS(stations); 574DEBUGFS_READ_FILE_OPS(rx_statistics); 575DEBUGFS_READ_FILE_OPS(tx_statistics); 576DEBUGFS_READ_FILE_OPS(channels); 577DEBUGFS_READ_FILE_OPS(status); 578DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 579 580/* 581 * Create the debugfs files and directories 582 * 583 */ 584int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 585{ 586 struct iwl_debugfs *dbgfs; 587 struct dentry *phyd = priv->hw->wiphy->debugfsdir; 588 int ret = 0; 589 590 dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); 591 if (!dbgfs) { 592 ret = -ENOMEM; 593 goto err; 594 } 595 596 priv->dbgfs = dbgfs; 597 dbgfs->name = name; 598 dbgfs->dir_drv = debugfs_create_dir(name, phyd); 599 if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { 600 ret = -ENOENT; 601 goto err; 602 } 603 604 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); 605 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); 606 DEBUGFS_ADD_FILE(nvm, data); 607 DEBUGFS_ADD_FILE(sram, data); 608 DEBUGFS_ADD_FILE(log_event, data); 609 DEBUGFS_ADD_FILE(stations, data); 610 DEBUGFS_ADD_FILE(rx_statistics, data); 611 DEBUGFS_ADD_FILE(tx_statistics, data); 612 DEBUGFS_ADD_FILE(channels, data); 613 DEBUGFS_ADD_FILE(status, data); 614 DEBUGFS_ADD_FILE(interrupt, data); 615 DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); 616 DEBUGFS_ADD_BOOL(disable_chain_noise, rf, 617 &priv->disable_chain_noise_cal); 618 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || 619 ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) 620 DEBUGFS_ADD_BOOL(disable_tx_power, rf, 621 &priv->disable_tx_power_cal); 622 return 0; 623 624err: 625 IWL_ERR(priv, "Can't open the debugfs directory\n"); 626 iwl_dbgfs_unregister(priv); 627 return ret; 628} 629EXPORT_SYMBOL(iwl_dbgfs_register); 630 631/** 632 * Remove the debugfs files and directories 633 * 634 */ 635void iwl_dbgfs_unregister(struct iwl_priv *priv) 636{ 637 if (!priv->dbgfs) 638 return; 639 640 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); 641 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); 642 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); 643 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); 644 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); 645 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); 646 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); 647 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); 648 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); 649 DEBUGFS_REMOVE(priv->dbgfs->dir_data); 650 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); 651 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); 652 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || 653 ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) 654 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); 655 DEBUGFS_REMOVE(priv->dbgfs->dir_rf); 656 DEBUGFS_REMOVE(priv->dbgfs->dir_drv); 657 kfree(priv->dbgfs); 658 priv->dbgfs = NULL; 659} 660EXPORT_SYMBOL(iwl_dbgfs_unregister); 661 662 663 664