aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-01-15 16:43:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-19 16:25:12 -0500
commit1b3eb8236ad9369ae519216b61a3d22806370115 (patch)
tree910be6c299c9f9dbd57903d7003a6967d1e9fc38 /drivers/net/wireless
parent2a11df6ee58d1b1fc7e5ecd7593a04d7555dc522 (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.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h19
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}
3279EXPORT_SYMBOL(iwl_dump_csr); 3281EXPORT_SYMBOL(iwl_dump_csr);
3280 3282
3283const 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
3301int 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}
3344EXPORT_SYMBOL(iwl_dump_fh);
3345
3281#ifdef CONFIG_PM 3346#ifdef CONFIG_PM
3282 3347
3283int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) 3348int 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);
582int iwl_dump_nic_event_log(struct iwl_priv *priv, 583int 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);
584void iwl_dump_csr(struct iwl_priv *priv); 585void iwl_dump_csr(struct iwl_priv *priv);
586int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
585#ifdef CONFIG_IWLWIFI_DEBUG 587#ifdef CONFIG_IWLWIFI_DEBUG
586void iwl_print_rx_config_cmd(struct iwl_priv *priv); 588void 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
2154static 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
2154DEBUGFS_READ_FILE_OPS(rx_statistics); 2175DEBUGFS_READ_FILE_OPS(rx_statistics);
2155DEBUGFS_READ_FILE_OPS(tx_statistics); 2176DEBUGFS_READ_FILE_OPS(tx_statistics);
2156DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); 2177DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -2167,6 +2188,7 @@ DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
2167DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); 2188DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
2168DEBUGFS_WRITE_FILE_OPS(csr); 2189DEBUGFS_WRITE_FILE_OPS(csr);
2169DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); 2190DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
2191DEBUGFS_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