diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-commands.h | 90 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.h | 10 |
4 files changed, 91 insertions, 54 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cdeb09eee739..f8559cc974f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1878,6 +1878,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1878 | u32 desc, time, count, base, data1; | 1878 | u32 desc, time, count, base, data1; |
1879 | u32 blink1, blink2, ilink1, ilink2; | 1879 | u32 blink1, blink2, ilink1, ilink2; |
1880 | u32 pc, hcmd; | 1880 | u32 pc, hcmd; |
1881 | struct iwl_error_event_table table; | ||
1881 | 1882 | ||
1882 | base = priv->device_pointers.error_event_table; | 1883 | base = priv->device_pointers.error_event_table; |
1883 | if (priv->ucode_type == UCODE_INIT) { | 1884 | if (priv->ucode_type == UCODE_INIT) { |
@@ -1895,7 +1896,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1895 | return; | 1896 | return; |
1896 | } | 1897 | } |
1897 | 1898 | ||
1898 | count = iwl_read_targ_mem(priv, base); | 1899 | iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); |
1900 | |||
1901 | count = table.valid; | ||
1899 | 1902 | ||
1900 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | 1903 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { |
1901 | IWL_ERR(priv, "Start IWL Error Log Dump:\n"); | 1904 | IWL_ERR(priv, "Start IWL Error Log Dump:\n"); |
@@ -1903,18 +1906,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1903 | priv->status, count); | 1906 | priv->status, count); |
1904 | } | 1907 | } |
1905 | 1908 | ||
1906 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | 1909 | desc = table.error_id; |
1907 | priv->isr_stats.err_code = desc; | 1910 | priv->isr_stats.err_code = desc; |
1908 | pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); | 1911 | pc = table.pc; |
1909 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | 1912 | blink1 = table.blink1; |
1910 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | 1913 | blink2 = table.blink2; |
1911 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); | 1914 | ilink1 = table.ilink1; |
1912 | ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); | 1915 | ilink2 = table.ilink2; |
1913 | data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); | 1916 | data1 = table.data1; |
1914 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); | 1917 | data2 = table.data2; |
1915 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | 1918 | line = table.line; |
1916 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | 1919 | time = table.tsf_low; |
1917 | hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); | 1920 | hcmd = table.hcmd; |
1918 | 1921 | ||
1919 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | 1922 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, |
1920 | blink1, blink2, ilink1, ilink2); | 1923 | blink1, blink2, ilink1, ilink2); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 0edba8a6419b..7aea7b34f36c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -422,49 +422,61 @@ struct iwl_tx_ant_config_cmd { | |||
422 | * | 422 | * |
423 | * 2) error_event_table_ptr indicates base of the error log. This contains | 423 | * 2) error_event_table_ptr indicates base of the error log. This contains |
424 | * information about any uCode error that occurs. For agn, the format | 424 | * information about any uCode error that occurs. For agn, the format |
425 | * of the error log is: | 425 | * of the error log is defined by struct iwl_error_event_table. |
426 | * | ||
427 | * __le32 valid; (nonzero) valid, (0) log is empty | ||
428 | * __le32 error_id; type of error | ||
429 | * __le32 pc; program counter | ||
430 | * __le32 blink1; branch link | ||
431 | * __le32 blink2; branch link | ||
432 | * __le32 ilink1; interrupt link | ||
433 | * __le32 ilink2; interrupt link | ||
434 | * __le32 data1; error-specific data | ||
435 | * __le32 data2; error-specific data | ||
436 | * __le32 line; source code line of error | ||
437 | * __le32 bcon_time; beacon timer | ||
438 | * __le32 tsf_low; network timestamp function timer | ||
439 | * __le32 tsf_hi; network timestamp function timer | ||
440 | * __le32 gp1; GP1 timer register | ||
441 | * __le32 gp2; GP2 timer register | ||
442 | * __le32 gp3; GP3 timer register | ||
443 | * __le32 ucode_ver; uCode version | ||
444 | * __le32 hw_ver; HW Silicon version | ||
445 | * __le32 brd_ver; HW board version | ||
446 | * __le32 log_pc; log program counter | ||
447 | * __le32 frame_ptr; frame pointer | ||
448 | * __le32 stack_ptr; stack pointer | ||
449 | * __le32 hcmd; last host command | ||
450 | * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag | ||
451 | * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag | ||
452 | * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag | ||
453 | * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag | ||
454 | * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt | ||
455 | * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT | ||
456 | * __le32 wait_event; wait event() caller address | ||
457 | * __le32 l2p_control; L2pControlField | ||
458 | * __le32 l2p_duration; L2pDurationField | ||
459 | * __le32 l2p_mhvalid; L2pMhValidBits | ||
460 | * __le32 l2p_addr_match; L2pAddrMatchStat | ||
461 | * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) | ||
462 | * __le32 u_timestamp; indicate when the date and time of the compilation | ||
463 | * __le32 reserved; | ||
464 | * | 426 | * |
465 | * The Linux driver can print both logs to the system log when a uCode error | 427 | * The Linux driver can print both logs to the system log when a uCode error |
466 | * occurs. | 428 | * occurs. |
467 | */ | 429 | */ |
430 | |||
431 | /* | ||
432 | * Note: This structure is read from the device with IO accesses, | ||
433 | * and the reading already does the endian conversion. As it is | ||
434 | * read with u32-sized accesses, any members with a different size | ||
435 | * need to be ordered correctly though! | ||
436 | */ | ||
437 | struct iwl_error_event_table { | ||
438 | u32 valid; /* (nonzero) valid, (0) log is empty */ | ||
439 | u32 error_id; /* type of error */ | ||
440 | u32 pc; /* program counter */ | ||
441 | u32 blink1; /* branch link */ | ||
442 | u32 blink2; /* branch link */ | ||
443 | u32 ilink1; /* interrupt link */ | ||
444 | u32 ilink2; /* interrupt link */ | ||
445 | u32 data1; /* error-specific data */ | ||
446 | u32 data2; /* error-specific data */ | ||
447 | u32 line; /* source code line of error */ | ||
448 | u32 bcon_time; /* beacon timer */ | ||
449 | u32 tsf_low; /* network timestamp function timer */ | ||
450 | u32 tsf_hi; /* network timestamp function timer */ | ||
451 | u32 gp1; /* GP1 timer register */ | ||
452 | u32 gp2; /* GP2 timer register */ | ||
453 | u32 gp3; /* GP3 timer register */ | ||
454 | u32 ucode_ver; /* uCode version */ | ||
455 | u32 hw_ver; /* HW Silicon version */ | ||
456 | u32 brd_ver; /* HW board version */ | ||
457 | u32 log_pc; /* log program counter */ | ||
458 | u32 frame_ptr; /* frame pointer */ | ||
459 | u32 stack_ptr; /* stack pointer */ | ||
460 | u32 hcmd; /* last host command header */ | ||
461 | #if 0 | ||
462 | /* no need to read the remainder, we don't use the values */ | ||
463 | u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */ | ||
464 | u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */ | ||
465 | u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */ | ||
466 | u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */ | ||
467 | u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */ | ||
468 | u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ | ||
469 | u32 wait_event; /* wait event() caller address */ | ||
470 | u32 l2p_control; /* L2pControlField */ | ||
471 | u32 l2p_duration; /* L2pDurationField */ | ||
472 | u32 l2p_mhvalid; /* L2pMhValidBits */ | ||
473 | u32 l2p_addr_match; /* L2pAddrMatchStat */ | ||
474 | u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */ | ||
475 | u32 u_timestamp; /* indicate when the date and time of the compilation */ | ||
476 | u32 flow_handler; /* FH read/write pointers, RX credit */ | ||
477 | #endif | ||
478 | } __packed; | ||
479 | |||
468 | struct iwl_alive_resp { | 480 | struct iwl_alive_resp { |
469 | u8 ucode_minor; | 481 | u8 ucode_minor; |
470 | u8 ucode_major; | 482 | u8 ucode_major; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 51337416e4ca..993b3df1b72b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -242,20 +242,32 @@ void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) | |||
242 | spin_unlock_irqrestore(&priv->reg_lock, flags); | 242 | spin_unlock_irqrestore(&priv->reg_lock, flags); |
243 | } | 243 | } |
244 | 244 | ||
245 | u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) | 245 | void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, |
246 | void *buf, int words) | ||
246 | { | 247 | { |
247 | unsigned long flags; | 248 | unsigned long flags; |
248 | u32 value; | 249 | int offs; |
250 | u32 *vals = buf; | ||
249 | 251 | ||
250 | spin_lock_irqsave(&priv->reg_lock, flags); | 252 | spin_lock_irqsave(&priv->reg_lock, flags); |
251 | iwl_grab_nic_access(priv); | 253 | iwl_grab_nic_access(priv); |
252 | 254 | ||
253 | iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); | 255 | iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); |
254 | rmb(); | 256 | rmb(); |
255 | value = iwl_read32(priv, HBUS_TARG_MEM_RDAT); | 257 | |
258 | for (offs = 0; offs < words; offs++) | ||
259 | vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); | ||
256 | 260 | ||
257 | iwl_release_nic_access(priv); | 261 | iwl_release_nic_access(priv); |
258 | spin_unlock_irqrestore(&priv->reg_lock, flags); | 262 | spin_unlock_irqrestore(&priv->reg_lock, flags); |
263 | } | ||
264 | |||
265 | u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) | ||
266 | { | ||
267 | u32 value; | ||
268 | |||
269 | _iwl_read_targ_mem_words(priv, addr, &value, 1); | ||
270 | |||
259 | return value; | 271 | return value; |
260 | } | 272 | } |
261 | 273 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index ab632baf49d5..262e0262496d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -76,6 +76,16 @@ void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, | |||
76 | u32 bits, u32 mask); | 76 | u32 bits, u32 mask); |
77 | void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); | 77 | void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); |
78 | 78 | ||
79 | void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, | ||
80 | void *buf, int words); | ||
81 | |||
82 | #define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ | ||
83 | do { \ | ||
84 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ | ||
85 | _iwl_read_targ_mem_words(priv, addr, buf, \ | ||
86 | (bufsize) / sizeof(u32));\ | ||
87 | } while (0) | ||
88 | |||
79 | u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); | 89 | u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); |
80 | void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); | 90 | void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); |
81 | #endif | 91 | #endif |