diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-01-15 16:43:39 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-19 16:25:12 -0500 |
commit | 1b3eb8236ad9369ae519216b61a3d22806370115 (patch) | |
tree | 910be6c299c9f9dbd57903d7003a6967d1e9fc38 /drivers/net/wireless | |
parent | 2a11df6ee58d1b1fc7e5ecd7593a04d7555dc522 (diff) |
iwlwifi: display flowhandler register when sw error or on-demand
Flowhandler handle the communication between driver and uCode, when any
uCode error happen, we also like to know what is the status of the
flowhandler; it can help to debug flowhandler related problem.
Also adding debugfs file to dump current value of flowhandler registers.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-1000.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debug.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fh.h | 19 |
8 files changed, 114 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0db1fda94a65..506429f00c12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -106,6 +106,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
106 | .dump_nic_event_log = iwl_dump_nic_event_log, | 106 | .dump_nic_event_log = iwl_dump_nic_event_log, |
107 | .dump_nic_error_log = iwl_dump_nic_error_log, | 107 | .dump_nic_error_log = iwl_dump_nic_error_log, |
108 | .dump_csr = iwl_dump_csr, | 108 | .dump_csr = iwl_dump_csr, |
109 | .dump_fh = iwl_dump_fh, | ||
109 | .init_alive_start = iwl5000_init_alive_start, | 110 | .init_alive_start = iwl5000_init_alive_start, |
110 | .alive_notify = iwl5000_alive_notify, | 111 | .alive_notify = iwl5000_alive_notify, |
111 | .send_tx_power = iwl5000_send_tx_power, | 112 | .send_tx_power = iwl5000_send_tx_power, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c6120f0b8f98..500c410f5242 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -1467,6 +1467,7 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1467 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1467 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1468 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1468 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1469 | .dump_csr = iwl_dump_csr, | 1469 | .dump_csr = iwl_dump_csr, |
1470 | .dump_fh = iwl_dump_fh, | ||
1470 | .load_ucode = iwl5000_load_ucode, | 1471 | .load_ucode = iwl5000_load_ucode, |
1471 | .init_alive_start = iwl5000_init_alive_start, | 1472 | .init_alive_start = iwl5000_init_alive_start, |
1472 | .alive_notify = iwl5000_alive_notify, | 1473 | .alive_notify = iwl5000_alive_notify, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a5a0ed4817a4..c5f244f3d747 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -216,6 +216,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
216 | .dump_nic_event_log = iwl_dump_nic_event_log, | 216 | .dump_nic_event_log = iwl_dump_nic_event_log, |
217 | .dump_nic_error_log = iwl_dump_nic_error_log, | 217 | .dump_nic_error_log = iwl_dump_nic_error_log, |
218 | .dump_csr = iwl_dump_csr, | 218 | .dump_csr = iwl_dump_csr, |
219 | .dump_fh = iwl_dump_fh, | ||
219 | .init_alive_start = iwl5000_init_alive_start, | 220 | .init_alive_start = iwl5000_init_alive_start, |
220 | .alive_notify = iwl5000_alive_notify, | 221 | .alive_notify = iwl5000_alive_notify, |
221 | .send_tx_power = iwl5000_send_tx_power, | 222 | .send_tx_power = iwl5000_send_tx_power, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9d6c144d0701..28d97f5f8ccf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1353,6 +1353,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1353 | priv->cfg->ops->lib->dump_nic_error_log(priv); | 1353 | priv->cfg->ops->lib->dump_nic_error_log(priv); |
1354 | if (priv->cfg->ops->lib->dump_csr) | 1354 | if (priv->cfg->ops->lib->dump_csr) |
1355 | priv->cfg->ops->lib->dump_csr(priv); | 1355 | priv->cfg->ops->lib->dump_csr(priv); |
1356 | if (priv->cfg->ops->lib->dump_fh) | ||
1357 | priv->cfg->ops->lib->dump_fh(priv, NULL, false); | ||
1356 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); | 1358 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); |
1357 | #ifdef CONFIG_IWLWIFI_DEBUG | 1359 | #ifdef CONFIG_IWLWIFI_DEBUG |
1358 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) | 1360 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
@@ -3278,6 +3280,69 @@ void iwl_dump_csr(struct iwl_priv *priv) | |||
3278 | } | 3280 | } |
3279 | EXPORT_SYMBOL(iwl_dump_csr); | 3281 | EXPORT_SYMBOL(iwl_dump_csr); |
3280 | 3282 | ||
3283 | const static char *get_fh_string(int cmd) | ||
3284 | { | ||
3285 | switch (cmd) { | ||
3286 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
3287 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
3288 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
3289 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
3290 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
3291 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
3292 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
3293 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
3294 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
3295 | default: | ||
3296 | return "UNKNOWN"; | ||
3297 | |||
3298 | } | ||
3299 | } | ||
3300 | |||
3301 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | ||
3302 | { | ||
3303 | int i; | ||
3304 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3305 | int pos = 0; | ||
3306 | size_t bufsz = 0; | ||
3307 | #endif | ||
3308 | u32 fh_tbl[] = { | ||
3309 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
3310 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
3311 | FH_RSCSR_CHNL0_WPTR, | ||
3312 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
3313 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
3314 | FH_MEM_RSSR_RX_STATUS_REG, | ||
3315 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
3316 | FH_TSSR_TX_STATUS_REG, | ||
3317 | FH_TSSR_TX_ERROR_REG | ||
3318 | }; | ||
3319 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3320 | if (display) { | ||
3321 | bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
3322 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
3323 | if (!*buf) | ||
3324 | return -ENOMEM; | ||
3325 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3326 | "FH register values:\n"); | ||
3327 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3328 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3329 | " %34s: 0X%08x\n", | ||
3330 | get_fh_string(fh_tbl[i]), | ||
3331 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3332 | } | ||
3333 | return pos; | ||
3334 | } | ||
3335 | #endif | ||
3336 | IWL_ERR(priv, "FH register values:\n"); | ||
3337 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3338 | IWL_ERR(priv, " %34s: 0X%08x\n", | ||
3339 | get_fh_string(fh_tbl[i]), | ||
3340 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3341 | } | ||
3342 | return 0; | ||
3343 | } | ||
3344 | EXPORT_SYMBOL(iwl_dump_fh); | ||
3345 | |||
3281 | #ifdef CONFIG_PM | 3346 | #ifdef CONFIG_PM |
3282 | 3347 | ||
3283 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 3348 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8deb83bfe182..666b0e0728b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -171,6 +171,7 @@ struct iwl_lib_ops { | |||
171 | bool full_log, char **buf, bool display); | 171 | bool full_log, char **buf, bool display); |
172 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 172 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
173 | void (*dump_csr)(struct iwl_priv *priv); | 173 | void (*dump_csr)(struct iwl_priv *priv); |
174 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); | ||
174 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 175 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); |
175 | /* power management */ | 176 | /* power management */ |
176 | struct iwl_apm_ops apm_ops; | 177 | struct iwl_apm_ops apm_ops; |
@@ -582,6 +583,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv); | |||
582 | int iwl_dump_nic_event_log(struct iwl_priv *priv, | 583 | int iwl_dump_nic_event_log(struct iwl_priv *priv, |
583 | bool full_log, char **buf, bool display); | 584 | bool full_log, char **buf, bool display); |
584 | void iwl_dump_csr(struct iwl_priv *priv); | 585 | void iwl_dump_csr(struct iwl_priv *priv); |
586 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); | ||
585 | #ifdef CONFIG_IWLWIFI_DEBUG | 587 | #ifdef CONFIG_IWLWIFI_DEBUG |
586 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 588 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); |
587 | #else | 589 | #else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 58e0462cafa3..1d1e655317a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -111,6 +111,7 @@ struct iwl_debugfs { | |||
111 | struct dentry *file_clear_traffic_statistics; | 111 | struct dentry *file_clear_traffic_statistics; |
112 | struct dentry *file_csr; | 112 | struct dentry *file_csr; |
113 | struct dentry *file_ucode_tracing; | 113 | struct dentry *file_ucode_tracing; |
114 | struct dentry *file_fh_reg; | ||
114 | } dbgfs_debug_files; | 115 | } dbgfs_debug_files; |
115 | u32 sram_offset; | 116 | u32 sram_offset; |
116 | u32 sram_len; | 117 | u32 sram_len; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a7ca06d21d59..a3d461ff4a9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -2151,6 +2151,27 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | |||
2151 | return count; | 2151 | return count; |
2152 | } | 2152 | } |
2153 | 2153 | ||
2154 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | ||
2155 | char __user *user_buf, | ||
2156 | size_t count, loff_t *ppos) | ||
2157 | { | ||
2158 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2159 | char *buf; | ||
2160 | int pos = 0; | ||
2161 | ssize_t ret = -EFAULT; | ||
2162 | |||
2163 | if (priv->cfg->ops->lib->dump_fh) { | ||
2164 | ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); | ||
2165 | if (buf) { | ||
2166 | ret = simple_read_from_buffer(user_buf, | ||
2167 | count, ppos, buf, pos); | ||
2168 | kfree(buf); | ||
2169 | } | ||
2170 | } | ||
2171 | |||
2172 | return ret; | ||
2173 | } | ||
2174 | |||
2154 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2175 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
2155 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2176 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
2156 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2177 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -2167,6 +2188,7 @@ DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | |||
2167 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 2188 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); |
2168 | DEBUGFS_WRITE_FILE_OPS(csr); | 2189 | DEBUGFS_WRITE_FILE_OPS(csr); |
2169 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 2190 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); |
2191 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
2170 | 2192 | ||
2171 | /* | 2193 | /* |
2172 | * Create the debugfs files and directories | 2194 | * Create the debugfs files and directories |
@@ -2218,6 +2240,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2218 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); | 2240 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); |
2219 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); | 2241 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); |
2220 | DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); | 2242 | DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); |
2243 | DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); | ||
2221 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2244 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
2222 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); | 2245 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); |
2223 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); | 2246 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); |
@@ -2277,6 +2300,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
2277 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 2300 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
2278 | file_clear_traffic_statistics); | 2301 | file_clear_traffic_statistics); |
2279 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); | 2302 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); |
2303 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); | ||
2280 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2304 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
2281 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 2305 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
2282 | file_ucode_rx_stats); | 2306 | file_ucode_rx_stats); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 65fa8a69fd5a..1342cf40297a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -379,6 +379,25 @@ | |||
379 | 379 | ||
380 | #define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) | 380 | #define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) |
381 | 381 | ||
382 | /** | ||
383 | * Bit fields for TSSR(Tx Shared Status & Control) error status register: | ||
384 | * 31: Indicates an address error when accessed to internal memory | ||
385 | * uCode/driver must write "1" in order to clear this flag | ||
386 | * 30: Indicates that Host did not send the expected number of dwords to FH | ||
387 | * uCode/driver must write "1" in order to clear this flag | ||
388 | * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA | ||
389 | * command was received from the scheduler while the TRB was already full | ||
390 | * with previous command | ||
391 | * uCode/driver must write "1" in order to clear this flag | ||
392 | * 7-0: Each status bit indicates a channel's TxCredit error. When an error | ||
393 | * bit is set, it indicates that the FH has received a full indication | ||
394 | * from the RTC TxFIFO and the current value of the TxCredit counter was | ||
395 | * not equal to zero. This mean that the credit mechanism was not | ||
396 | * synchronized to the TxFIFO status | ||
397 | * uCode/driver must write "1" in order to clear this flag | ||
398 | */ | ||
399 | #define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018) | ||
400 | |||
382 | #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) | 401 | #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) |
383 | #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) | 402 | #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) |
384 | 403 | ||