aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-08-26 02:10:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-29 15:25:34 -0400
commit1f7b6172db86e9ab2b4cd794441bb2c40ab287fc (patch)
tree3e44d755f23dddfd49abe1106f70e661dd87c474
parente4ef84d94b0dbb75b4da6628611341af5812360f (diff)
iwlagn: move isr_statistics to transport layer
It is accessed by the transport layer only, hence the move. The debugfs handlers that accessed it moved to the transport layer too. The rx_handlers part of it stayed in the upper layer and a special debugfs has been added for it Also add missing includes to iwl-commands.h. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c88
9 files changed, 140 insertions, 83 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 0016c61b3000..86b974804ead 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -69,6 +69,9 @@
69#ifndef __iwl_commands_h__ 69#ifndef __iwl_commands_h__
70#define __iwl_commands_h__ 70#define __iwl_commands_h__
71 71
72#include <linux/etherdevice.h>
73#include <linux/ieee80211.h>
74
72struct iwl_priv; 75struct iwl_priv;
73 76
74/* uCode version contains 4 values: Major/Minor/API/Serial */ 77/* uCode version contains 4 values: Major/Minor/API/Serial */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 88fc39619214..347cbec935b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1121,11 +1121,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
1121 &statistics_cmd); 1121 &statistics_cmd);
1122} 1122}
1123 1123
1124void iwl_clear_isr_stats(struct iwl_priv *priv)
1125{
1126 memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
1127}
1128
1129int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, 1124int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
1130 const struct ieee80211_tx_queue_params *params) 1125 const struct ieee80211_tx_queue_params *params)
1131{ 1126{
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index aa6211837b48..110ffaea0949 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -387,8 +387,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
387} 387}
388#endif 388#endif
389 389
390void iwl_clear_isr_stats(struct iwl_priv *priv);
391
392/***************************************************** 390/*****************************************************
393* GEOS 391* GEOS
394******************************************************/ 392******************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index fa070de2840c..787dae5fec99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -556,11 +556,12 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
556 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 556 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
557} 557}
558 558
559static ssize_t iwl_dbgfs_interrupt_read(struct file *file, 559static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
560 char __user *user_buf, 560 char __user *user_buf,
561 size_t count, loff_t *ppos) { 561 size_t count, loff_t *ppos) {
562 562
563 struct iwl_priv *priv = file->private_data; 563 struct iwl_priv *priv = file->private_data;
564
564 int pos = 0; 565 int pos = 0;
565 int cnt = 0; 566 int cnt = 0;
566 char *buf; 567 char *buf;
@@ -573,61 +574,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
573 return -ENOMEM; 574 return -ENOMEM;
574 } 575 }
575 576
576 pos += scnprintf(buf + pos, bufsz - pos,
577 "Interrupt Statistics Report:\n");
578
579 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
580 priv->isr_stats.hw);
581 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
582 priv->isr_stats.sw);
583 if (priv->isr_stats.sw || priv->isr_stats.hw) {
584 pos += scnprintf(buf + pos, bufsz - pos,
585 "\tLast Restarting Code: 0x%X\n",
586 priv->isr_stats.err_code);
587 }
588#ifdef CONFIG_IWLWIFI_DEBUG
589 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
590 priv->isr_stats.sch);
591 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
592 priv->isr_stats.alive);
593#endif
594 pos += scnprintf(buf + pos, bufsz - pos,
595 "HW RF KILL switch toggled:\t %u\n",
596 priv->isr_stats.rfkill);
597
598 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
599 priv->isr_stats.ctkill);
600
601 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
602 priv->isr_stats.wakeup);
603
604 pos += scnprintf(buf + pos, bufsz - pos,
605 "Rx command responses:\t\t %u\n",
606 priv->isr_stats.rx);
607 for (cnt = 0; cnt < REPLY_MAX; cnt++) { 577 for (cnt = 0; cnt < REPLY_MAX; cnt++) {
608 if (priv->isr_stats.rx_handlers[cnt] > 0) 578 if (priv->rx_handlers_stats[cnt] > 0)
609 pos += scnprintf(buf + pos, bufsz - pos, 579 pos += scnprintf(buf + pos, bufsz - pos,
610 "\tRx handler[%36s]:\t\t %u\n", 580 "\tRx handler[%36s]:\t\t %u\n",
611 get_cmd_string(cnt), 581 get_cmd_string(cnt),
612 priv->isr_stats.rx_handlers[cnt]); 582 priv->rx_handlers_stats[cnt]);
613 } 583 }
614 584
615 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
616 priv->isr_stats.tx);
617
618 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
619 priv->isr_stats.unhandled);
620
621 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 585 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
622 kfree(buf); 586 kfree(buf);
623 return ret; 587 return ret;
624} 588}
625 589
626static ssize_t iwl_dbgfs_interrupt_write(struct file *file, 590static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file,
627 const char __user *user_buf, 591 const char __user *user_buf,
628 size_t count, loff_t *ppos) 592 size_t count, loff_t *ppos)
629{ 593{
630 struct iwl_priv *priv = file->private_data; 594 struct iwl_priv *priv = file->private_data;
595
631 char buf[8]; 596 char buf[8];
632 int buf_size; 597 int buf_size;
633 u32 reset_flag; 598 u32 reset_flag;
@@ -639,7 +604,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
639 if (sscanf(buf, "%x", &reset_flag) != 1) 604 if (sscanf(buf, "%x", &reset_flag) != 1)
640 return -EFAULT; 605 return -EFAULT;
641 if (reset_flag == 0) 606 if (reset_flag == 0)
642 iwl_clear_isr_stats(priv); 607 memset(&priv->rx_handlers_stats[0], 0,
608 sizeof(priv->rx_handlers_stats));
643 609
644 return count; 610 return count;
645} 611}
@@ -834,7 +800,7 @@ DEBUGFS_READ_FILE_OPS(nvm);
834DEBUGFS_READ_FILE_OPS(stations); 800DEBUGFS_READ_FILE_OPS(stations);
835DEBUGFS_READ_FILE_OPS(channels); 801DEBUGFS_READ_FILE_OPS(channels);
836DEBUGFS_READ_FILE_OPS(status); 802DEBUGFS_READ_FILE_OPS(status);
837DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 803DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
838DEBUGFS_READ_FILE_OPS(qos); 804DEBUGFS_READ_FILE_OPS(qos);
839DEBUGFS_READ_FILE_OPS(thermal_throttling); 805DEBUGFS_READ_FILE_OPS(thermal_throttling);
840DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 806DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
@@ -2471,7 +2437,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
2471 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 2437 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
2472 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 2438 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
2473 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 2439 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
2474 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 2440 DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR);
2475 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 2441 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
2476 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); 2442 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
2477 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); 2443 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 40a01c0e4f30..f3852edaccf5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -810,22 +810,6 @@ enum iwl_pa_type {
810 IWL_PA_INTERNAL = 1, 810 IWL_PA_INTERNAL = 1,
811}; 811};
812 812
813/* interrupt statistics */
814struct isr_statistics {
815 u32 hw;
816 u32 sw;
817 u32 err_code;
818 u32 sch;
819 u32 alive;
820 u32 rfkill;
821 u32 ctkill;
822 u32 wakeup;
823 u32 rx;
824 u32 rx_handlers[REPLY_MAX];
825 u32 tx;
826 u32 unhandled;
827};
828
829/* reply_tx_statistics (for _agn devices) */ 813/* reply_tx_statistics (for _agn devices) */
830struct reply_tx_error_statistics { 814struct reply_tx_error_statistics {
831 u32 pp_delay; 815 u32 pp_delay;
@@ -1155,6 +1139,9 @@ struct iwl_priv {
1155 /* jiffies when last recovery from statistics was performed */ 1139 /* jiffies when last recovery from statistics was performed */
1156 unsigned long rx_statistics_jiffies; 1140 unsigned long rx_statistics_jiffies;
1157 1141
1142 /*counters */
1143 u32 rx_handlers_stats[REPLY_MAX];
1144
1158 /* force reset */ 1145 /* force reset */
1159 struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; 1146 struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
1160 1147
@@ -1258,10 +1245,6 @@ struct iwl_priv {
1258 struct traffic_stats tx_stats; 1245 struct traffic_stats tx_stats;
1259 struct traffic_stats rx_stats; 1246 struct traffic_stats rx_stats;
1260 1247
1261 /* counts interrupts */
1262 /* TODO: move to the transport layer */
1263 struct isr_statistics isr_stats;
1264
1265 struct iwl_power_mgr power_data; 1248 struct iwl_power_mgr power_data;
1266 struct iwl_tt_mgmt thermal_throttle; 1249 struct iwl_tt_mgmt thermal_throttle;
1267 1250
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index a5e4ddad2e04..d7c7c93b2daf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1020,7 +1020,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1020 * handle those that need handling via function in 1020 * handle those that need handling via function in
1021 * rx_handlers table. See iwl_setup_rx_handlers() */ 1021 * rx_handlers table. See iwl_setup_rx_handlers() */
1022 if (priv->rx_handlers[pkt->hdr.cmd]) { 1022 if (priv->rx_handlers[pkt->hdr.cmd]) {
1023 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; 1023 priv->rx_handlers_stats[pkt->hdr.cmd]++;
1024 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); 1024 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1025 } else { 1025 } else {
1026 /* No handling needed */ 1026 /* No handling needed */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
index 4694c462ed4e..f60b26f4dc7b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
@@ -33,6 +33,24 @@
33 * trans_pcie layer */ 33 * trans_pcie layer */
34 34
35/** 35/**
36 * struct isr_statistics - interrupt statistics
37 *
38 */
39struct isr_statistics {
40 u32 hw;
41 u32 sw;
42 u32 err_code;
43 u32 sch;
44 u32 alive;
45 u32 rfkill;
46 u32 ctkill;
47 u32 wakeup;
48 u32 rx;
49 u32 tx;
50 u32 unhandled;
51};
52
53/**
36 * struct iwl_rx_queue - Rx queue 54 * struct iwl_rx_queue - Rx queue
37 * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) 55 * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
38 * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) 56 * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
@@ -88,6 +106,7 @@ struct iwl_trans_pcie {
88 u32 inta; 106 u32 inta;
89 bool use_ict; 107 bool use_ict;
90 struct tasklet_struct irq_tasklet; 108 struct tasklet_struct irq_tasklet;
109 struct isr_statistics isr_stats;
91 110
92 u32 inta_mask; 111 u32 inta_mask;
93}; 112};
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
index aa7ced4324b8..b1635eee24b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
@@ -569,6 +569,9 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
569{ 569{
570 u32 base; 570 u32 base;
571 struct iwl_error_event_table table; 571 struct iwl_error_event_table table;
572 struct iwl_trans *trans = trans(priv);
573 struct iwl_trans_pcie *trans_pcie =
574 IWL_TRANS_GET_PCIE_TRANS(trans);
572 575
573 base = priv->device_pointers.error_event_table; 576 base = priv->device_pointers.error_event_table;
574 if (priv->ucode_type == IWL_UCODE_INIT) { 577 if (priv->ucode_type == IWL_UCODE_INIT) {
@@ -596,7 +599,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
596 priv->shrd->status, table.valid); 599 priv->shrd->status, table.valid);
597 } 600 }
598 601
599 priv->isr_stats.err_code = table.error_id; 602 trans_pcie->isr_stats.err_code = table.error_id;
600 603
601 trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, 604 trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
602 table.data1, table.data2, table.line, 605 table.data1, table.data2, table.line,
@@ -905,6 +908,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
905 908
906 struct iwl_trans_pcie *trans_pcie = 909 struct iwl_trans_pcie *trans_pcie =
907 IWL_TRANS_GET_PCIE_TRANS(trans); 910 IWL_TRANS_GET_PCIE_TRANS(trans);
911 struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
912
908 913
909 spin_lock_irqsave(&trans->shrd->lock, flags); 914 spin_lock_irqsave(&trans->shrd->lock, flags);
910 915
@@ -945,7 +950,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
945 /* Tell the device to stop sending interrupts */ 950 /* Tell the device to stop sending interrupts */
946 iwl_disable_interrupts(trans); 951 iwl_disable_interrupts(trans);
947 952
948 priv(trans)->isr_stats.hw++; 953 isr_stats->hw++;
949 iwl_irq_handle_error(priv(trans)); 954 iwl_irq_handle_error(priv(trans));
950 955
951 handled |= CSR_INT_BIT_HW_ERR; 956 handled |= CSR_INT_BIT_HW_ERR;
@@ -959,13 +964,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
959 if (inta & CSR_INT_BIT_SCD) { 964 if (inta & CSR_INT_BIT_SCD) {
960 IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " 965 IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
961 "the frame/frames.\n"); 966 "the frame/frames.\n");
962 priv(trans)->isr_stats.sch++; 967 isr_stats->sch++;
963 } 968 }
964 969
965 /* Alive notification via Rx interrupt will do the real work */ 970 /* Alive notification via Rx interrupt will do the real work */
966 if (inta & CSR_INT_BIT_ALIVE) { 971 if (inta & CSR_INT_BIT_ALIVE) {
967 IWL_DEBUG_ISR(trans, "Alive interrupt\n"); 972 IWL_DEBUG_ISR(trans, "Alive interrupt\n");
968 priv(trans)->isr_stats.alive++; 973 isr_stats->alive++;
969 } 974 }
970 } 975 }
971#endif 976#endif
@@ -982,7 +987,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
982 IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", 987 IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
983 hw_rf_kill ? "disable radio" : "enable radio"); 988 hw_rf_kill ? "disable radio" : "enable radio");
984 989
985 priv(trans)->isr_stats.rfkill++; 990 isr_stats->rfkill++;
986 991
987 /* driver only loads ucode once setting the interface up. 992 /* driver only loads ucode once setting the interface up.
988 * the driver allows loading the ucode even if the radio 993 * the driver allows loading the ucode even if the radio
@@ -1006,7 +1011,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1006 /* Chip got too hot and stopped itself */ 1011 /* Chip got too hot and stopped itself */
1007 if (inta & CSR_INT_BIT_CT_KILL) { 1012 if (inta & CSR_INT_BIT_CT_KILL) {
1008 IWL_ERR(trans, "Microcode CT kill error detected.\n"); 1013 IWL_ERR(trans, "Microcode CT kill error detected.\n");
1009 priv(trans)->isr_stats.ctkill++; 1014 isr_stats->ctkill++;
1010 handled |= CSR_INT_BIT_CT_KILL; 1015 handled |= CSR_INT_BIT_CT_KILL;
1011 } 1016 }
1012 1017
@@ -1014,7 +1019,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1014 if (inta & CSR_INT_BIT_SW_ERR) { 1019 if (inta & CSR_INT_BIT_SW_ERR) {
1015 IWL_ERR(trans, "Microcode SW error detected. " 1020 IWL_ERR(trans, "Microcode SW error detected. "
1016 " Restarting 0x%X.\n", inta); 1021 " Restarting 0x%X.\n", inta);
1017 priv(trans)->isr_stats.sw++; 1022 isr_stats->sw++;
1018 iwl_irq_handle_error(priv(trans)); 1023 iwl_irq_handle_error(priv(trans));
1019 handled |= CSR_INT_BIT_SW_ERR; 1024 handled |= CSR_INT_BIT_SW_ERR;
1020 } 1025 }
@@ -1027,7 +1032,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1027 iwl_txq_update_write_ptr(priv(trans), 1032 iwl_txq_update_write_ptr(priv(trans),
1028 &priv(trans)->txq[i]); 1033 &priv(trans)->txq[i]);
1029 1034
1030 priv(trans)->isr_stats.wakeup++; 1035 isr_stats->wakeup++;
1031 1036
1032 handled |= CSR_INT_BIT_WAKEUP; 1037 handled |= CSR_INT_BIT_WAKEUP;
1033 } 1038 }
@@ -1075,14 +1080,14 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1075 iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, 1080 iwl_write8(priv(trans), CSR_INT_PERIODIC_REG,
1076 CSR_INT_PERIODIC_ENA); 1081 CSR_INT_PERIODIC_ENA);
1077 1082
1078 priv(trans)->isr_stats.rx++; 1083 isr_stats->rx++;
1079 } 1084 }
1080 1085
1081 /* This "Tx" DMA channel is used only for loading uCode */ 1086 /* This "Tx" DMA channel is used only for loading uCode */
1082 if (inta & CSR_INT_BIT_FH_TX) { 1087 if (inta & CSR_INT_BIT_FH_TX) {
1083 iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); 1088 iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
1084 IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); 1089 IWL_DEBUG_ISR(trans, "uCode load interrupt\n");
1085 priv(trans)->isr_stats.tx++; 1090 isr_stats->tx++;
1086 handled |= CSR_INT_BIT_FH_TX; 1091 handled |= CSR_INT_BIT_FH_TX;
1087 /* Wake up uCode load routine, now that load is complete */ 1092 /* Wake up uCode load routine, now that load is complete */
1088 priv(trans)->ucode_write_complete = 1; 1093 priv(trans)->ucode_write_complete = 1;
@@ -1091,7 +1096,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1091 1096
1092 if (inta & ~handled) { 1097 if (inta & ~handled) {
1093 IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); 1098 IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
1094 priv(trans)->isr_stats.unhandled++; 1099 isr_stats->unhandled++;
1095 } 1100 }
1096 1101
1097 if (inta & ~(trans_pcie->inta_mask)) { 1102 if (inta & ~(trans_pcie->inta_mask)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 5926cac711b3..63a310135f76 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -1496,8 +1496,95 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
1496 return count; 1496 return count;
1497} 1497}
1498 1498
1499static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
1500 char __user *user_buf,
1501 size_t count, loff_t *ppos) {
1502
1503 struct iwl_trans *trans = file->private_data;
1504 struct iwl_trans_pcie *trans_pcie =
1505 IWL_TRANS_GET_PCIE_TRANS(trans);
1506 struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
1507
1508 int pos = 0;
1509 char *buf;
1510 int bufsz = 24 * 64; /* 24 items * 64 char per item */
1511 ssize_t ret;
1512
1513 buf = kzalloc(bufsz, GFP_KERNEL);
1514 if (!buf) {
1515 IWL_ERR(trans, "Can not allocate Buffer\n");
1516 return -ENOMEM;
1517 }
1518
1519 pos += scnprintf(buf + pos, bufsz - pos,
1520 "Interrupt Statistics Report:\n");
1521
1522 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
1523 isr_stats->hw);
1524 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
1525 isr_stats->sw);
1526 if (isr_stats->sw || isr_stats->hw) {
1527 pos += scnprintf(buf + pos, bufsz - pos,
1528 "\tLast Restarting Code: 0x%X\n",
1529 isr_stats->err_code);
1530 }
1531#ifdef CONFIG_IWLWIFI_DEBUG
1532 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
1533 isr_stats->sch);
1534 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
1535 isr_stats->alive);
1536#endif
1537 pos += scnprintf(buf + pos, bufsz - pos,
1538 "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill);
1539
1540 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
1541 isr_stats->ctkill);
1542
1543 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
1544 isr_stats->wakeup);
1545
1546 pos += scnprintf(buf + pos, bufsz - pos,
1547 "Rx command responses:\t\t %u\n", isr_stats->rx);
1548
1549 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
1550 isr_stats->tx);
1551
1552 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
1553 isr_stats->unhandled);
1554
1555 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1556 kfree(buf);
1557 return ret;
1558}
1559
1560static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
1561 const char __user *user_buf,
1562 size_t count, loff_t *ppos)
1563{
1564 struct iwl_trans *trans = file->private_data;
1565 struct iwl_trans_pcie *trans_pcie =
1566 IWL_TRANS_GET_PCIE_TRANS(trans);
1567 struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
1568
1569 char buf[8];
1570 int buf_size;
1571 u32 reset_flag;
1572
1573 memset(buf, 0, sizeof(buf));
1574 buf_size = min(count, sizeof(buf) - 1);
1575 if (copy_from_user(buf, user_buf, buf_size))
1576 return -EFAULT;
1577 if (sscanf(buf, "%x", &reset_flag) != 1)
1578 return -EFAULT;
1579 if (reset_flag == 0)
1580 memset(isr_stats, 0, sizeof(*isr_stats));
1581
1582 return count;
1583}
1584
1499DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 1585DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1500DEBUGFS_READ_WRITE_FILE_OPS(log_event); 1586DEBUGFS_READ_WRITE_FILE_OPS(log_event);
1587DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
1501DEBUGFS_READ_FILE_OPS(rx_queue); 1588DEBUGFS_READ_FILE_OPS(rx_queue);
1502DEBUGFS_READ_FILE_OPS(tx_queue); 1589DEBUGFS_READ_FILE_OPS(tx_queue);
1503 1590
@@ -1512,6 +1599,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
1512 DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); 1599 DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
1513 DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); 1600 DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
1514 DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); 1601 DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);
1602 DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
1515 return 0; 1603 return 0;
1516} 1604}
1517#else 1605#else