diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-debugfs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 193 |
1 files changed, 144 insertions, 49 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 64eb585f1578..11e08c068917 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -172,7 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
172 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 172 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
173 | const size_t bufsz = sizeof(buf); | 173 | const size_t bufsz = sizeof(buf); |
174 | 174 | ||
175 | iwl_grab_nic_access(priv); | ||
176 | for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { | 175 | for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { |
177 | val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ | 176 | val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ |
178 | priv->dbgfs->sram_len - i); | 177 | priv->dbgfs->sram_len - i); |
@@ -192,7 +191,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
192 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | 191 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); |
193 | } | 192 | } |
194 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 193 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
195 | iwl_release_nic_access(priv); | ||
196 | 194 | ||
197 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 195 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
198 | return ret; | 196 | return ret; |
@@ -292,7 +290,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
292 | return ret; | 290 | return ret; |
293 | } | 291 | } |
294 | 292 | ||
295 | static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | 293 | static ssize_t iwl_dbgfs_nvm_read(struct file *file, |
296 | char __user *user_buf, | 294 | char __user *user_buf, |
297 | size_t count, | 295 | size_t count, |
298 | loff_t *ppos) | 296 | loff_t *ppos) |
@@ -306,7 +304,7 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | |||
306 | buf_size = 4 * eeprom_len + 256; | 304 | buf_size = 4 * eeprom_len + 256; |
307 | 305 | ||
308 | if (eeprom_len % 16) { | 306 | if (eeprom_len % 16) { |
309 | IWL_ERR(priv, "EEPROM size is not multiple of 16.\n"); | 307 | IWL_ERR(priv, "NVM size is not multiple of 16.\n"); |
310 | return -ENODATA; | 308 | return -ENODATA; |
311 | } | 309 | } |
312 | 310 | ||
@@ -318,6 +316,13 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, | |||
318 | } | 316 | } |
319 | 317 | ||
320 | ptr = priv->eeprom; | 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"); | ||
321 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 326 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
322 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 327 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
323 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 328 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -375,51 +380,53 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
375 | } | 380 | } |
376 | 381 | ||
377 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); | 382 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); |
378 | channels = supp_band->channels; | 383 | if (supp_band) { |
379 | 384 | channels = supp_band->channels; | |
380 | pos += scnprintf(buf + pos, bufsz - pos, | ||
381 | "Displaying %d channels in 2.4GHz band 802.11bg):\n", | ||
382 | supp_band->n_channels); | ||
383 | 385 | ||
384 | for (i = 0; i < supp_band->n_channels; i++) | ||
385 | pos += scnprintf(buf + pos, bufsz - pos, | 386 | pos += scnprintf(buf + pos, bufsz - pos, |
386 | "%d: %ddBm: BSS%s%s, %s.\n", | 387 | "Displaying %d channels in 2.4GHz band 802.11bg):\n", |
387 | ieee80211_frequency_to_channel( | 388 | supp_band->n_channels); |
388 | channels[i].center_freq), | ||
389 | channels[i].max_power, | ||
390 | channels[i].flags & IEEE80211_CHAN_RADAR ? | ||
391 | " (IEEE 802.11h required)" : "", | ||
392 | (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS) | ||
393 | || (channels[i].flags & | ||
394 | IEEE80211_CHAN_RADAR)) ? "" : | ||
395 | ", IBSS", | ||
396 | channels[i].flags & | ||
397 | IEEE80211_CHAN_PASSIVE_SCAN ? | ||
398 | "passive only" : "active/passive"); | ||
399 | 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 | } | ||
400 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); | 406 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); |
401 | channels = supp_band->channels; | 407 | if (supp_band) { |
402 | 408 | channels = supp_band->channels; | |
403 | pos += scnprintf(buf + pos, bufsz - pos, | ||
404 | "Displaying %d channels in 5.2GHz band (802.11a)\n", | ||
405 | supp_band->n_channels); | ||
406 | 409 | ||
407 | for (i = 0; i < supp_band->n_channels; i++) | ||
408 | pos += scnprintf(buf + pos, bufsz - pos, | 410 | pos += scnprintf(buf + pos, bufsz - pos, |
409 | "%d: %ddBm: BSS%s%s, %s.\n", | 411 | "Displaying %d channels in 5.2GHz band (802.11a)\n", |
410 | ieee80211_frequency_to_channel( | 412 | supp_band->n_channels); |
411 | channels[i].center_freq), | ||
412 | channels[i].max_power, | ||
413 | channels[i].flags & IEEE80211_CHAN_RADAR ? | ||
414 | " (IEEE 802.11h required)" : "", | ||
415 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | ||
416 | || (channels[i].flags & | ||
417 | IEEE80211_CHAN_RADAR)) ? "" : | ||
418 | ", IBSS", | ||
419 | channels[i].flags & | ||
420 | IEEE80211_CHAN_PASSIVE_SCAN ? | ||
421 | "passive only" : "active/passive"); | ||
422 | 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 | } | ||
423 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 430 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
424 | kfree(buf); | 431 | kfree(buf); |
425 | return ret; | 432 | return ret; |
@@ -442,8 +449,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
442 | test_bit(STATUS_INT_ENABLED, &priv->status)); | 449 | test_bit(STATUS_INT_ENABLED, &priv->status)); |
443 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 450 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
444 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 451 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
445 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n", | ||
446 | test_bit(STATUS_RF_KILL_SW, &priv->status)); | ||
447 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", | 452 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", |
448 | test_bit(STATUS_INIT, &priv->status)); | 453 | test_bit(STATUS_INIT, &priv->status)); |
449 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", | 454 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", |
@@ -456,8 +461,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
456 | test_bit(STATUS_GEO_CONFIGURED, &priv->status)); | 461 | test_bit(STATUS_GEO_CONFIGURED, &priv->status)); |
457 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 462 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", |
458 | test_bit(STATUS_EXIT_PENDING, &priv->status)); | 463 | test_bit(STATUS_EXIT_PENDING, &priv->status)); |
459 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n", | ||
460 | test_bit(STATUS_IN_SUSPEND, &priv->status)); | ||
461 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 464 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", |
462 | test_bit(STATUS_STATISTICS, &priv->status)); | 465 | test_bit(STATUS_STATISTICS, &priv->status)); |
463 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", | 466 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", |
@@ -475,14 +478,104 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
475 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 478 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
476 | } | 479 | } |
477 | 480 | ||
481 | static 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 | |||
548 | static 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 | |||
478 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 570 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
479 | DEBUGFS_WRITE_FILE_OPS(log_event); | 571 | DEBUGFS_WRITE_FILE_OPS(log_event); |
480 | DEBUGFS_READ_FILE_OPS(eeprom); | 572 | DEBUGFS_READ_FILE_OPS(nvm); |
481 | DEBUGFS_READ_FILE_OPS(stations); | 573 | DEBUGFS_READ_FILE_OPS(stations); |
482 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 574 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
483 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 575 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
484 | DEBUGFS_READ_FILE_OPS(channels); | 576 | DEBUGFS_READ_FILE_OPS(channels); |
485 | DEBUGFS_READ_FILE_OPS(status); | 577 | DEBUGFS_READ_FILE_OPS(status); |
578 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | ||
486 | 579 | ||
487 | /* | 580 | /* |
488 | * Create the debugfs files and directories | 581 | * Create the debugfs files and directories |
@@ -510,7 +603,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
510 | 603 | ||
511 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 604 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); |
512 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 605 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); |
513 | DEBUGFS_ADD_FILE(eeprom, data); | 606 | DEBUGFS_ADD_FILE(nvm, data); |
514 | DEBUGFS_ADD_FILE(sram, data); | 607 | DEBUGFS_ADD_FILE(sram, data); |
515 | DEBUGFS_ADD_FILE(log_event, data); | 608 | DEBUGFS_ADD_FILE(log_event, data); |
516 | DEBUGFS_ADD_FILE(stations, data); | 609 | DEBUGFS_ADD_FILE(stations, data); |
@@ -518,6 +611,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
518 | DEBUGFS_ADD_FILE(tx_statistics, data); | 611 | DEBUGFS_ADD_FILE(tx_statistics, data); |
519 | DEBUGFS_ADD_FILE(channels, data); | 612 | DEBUGFS_ADD_FILE(channels, data); |
520 | DEBUGFS_ADD_FILE(status, data); | 613 | DEBUGFS_ADD_FILE(status, data); |
614 | DEBUGFS_ADD_FILE(interrupt, data); | ||
521 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 615 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); |
522 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 616 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, |
523 | &priv->disable_chain_noise_cal); | 617 | &priv->disable_chain_noise_cal); |
@@ -540,7 +634,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
540 | if (!priv->dbgfs) | 634 | if (!priv->dbgfs) |
541 | return; | 635 | return; |
542 | 636 | ||
543 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); | 637 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); |
544 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); | 638 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); |
545 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); | 639 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); |
546 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); | 640 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); |
@@ -548,6 +642,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
548 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); | 642 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); |
549 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); | 643 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); |
550 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); | 644 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); |
645 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); | ||
551 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | 646 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); |
552 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | 647 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); |
553 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); | 648 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); |