diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-05-06 02:24:54 -0400 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-05-13 13:44:28 -0400 |
commit | b2e640d4851abfe6b03fc91597d0b8378c629907 (patch) | |
tree | 8b61a49d6d9332f3a6ea35fd02eb691231e7d06c /drivers | |
parent | 9c5ac091b269912cd30fade987f4bc615ef3be90 (diff) |
iwlagn: use firmware event/error log information
In order to debug problems before the ALIVE
notification is received, new firmware files
contain the event/error log information in
the file. Use that information.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 102 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 9 |
2 files changed, 99 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f62a345d71dc..845d0eeb0c86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1543,6 +1543,9 @@ struct iwlagn_firmware_pieces { | |||
1543 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | 1543 | size_t inst_size, data_size, init_size, init_data_size, boot_size; |
1544 | 1544 | ||
1545 | u32 build; | 1545 | u32 build; |
1546 | |||
1547 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1548 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1546 | }; | 1549 | }; |
1547 | 1550 | ||
1548 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | 1551 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, |
@@ -1720,6 +1723,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1720 | capa->max_probe_length = | 1723 | capa->max_probe_length = |
1721 | le32_to_cpup((__le32 *)tlv_data); | 1724 | le32_to_cpup((__le32 *)tlv_data); |
1722 | break; | 1725 | break; |
1726 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
1727 | if (tlv_len != 4) | ||
1728 | return -EINVAL; | ||
1729 | pieces->init_evtlog_ptr = | ||
1730 | le32_to_cpup((__le32 *)tlv_data); | ||
1731 | break; | ||
1732 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
1733 | if (tlv_len != 4) | ||
1734 | return -EINVAL; | ||
1735 | pieces->init_evtlog_size = | ||
1736 | le32_to_cpup((__le32 *)tlv_data); | ||
1737 | break; | ||
1738 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
1739 | if (tlv_len != 4) | ||
1740 | return -EINVAL; | ||
1741 | pieces->init_errlog_ptr = | ||
1742 | le32_to_cpup((__le32 *)tlv_data); | ||
1743 | break; | ||
1744 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
1745 | if (tlv_len != 4) | ||
1746 | return -EINVAL; | ||
1747 | pieces->inst_evtlog_ptr = | ||
1748 | le32_to_cpup((__le32 *)tlv_data); | ||
1749 | break; | ||
1750 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
1751 | if (tlv_len != 4) | ||
1752 | return -EINVAL; | ||
1753 | pieces->inst_evtlog_size = | ||
1754 | le32_to_cpup((__le32 *)tlv_data); | ||
1755 | break; | ||
1756 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
1757 | if (tlv_len != 4) | ||
1758 | return -EINVAL; | ||
1759 | pieces->inst_errlog_ptr = | ||
1760 | le32_to_cpup((__le32 *)tlv_data); | ||
1761 | break; | ||
1723 | default: | 1762 | default: |
1724 | break; | 1763 | break; |
1725 | } | 1764 | } |
@@ -1912,6 +1951,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1912 | goto err_pci_alloc; | 1951 | goto err_pci_alloc; |
1913 | } | 1952 | } |
1914 | 1953 | ||
1954 | /* Now that we can no longer fail, copy information */ | ||
1955 | |||
1956 | /* | ||
1957 | * The (size - 16) / 12 formula is based on the information recorded | ||
1958 | * for each event, which is of mode 1 (including timestamp) for all | ||
1959 | * new microcodes that include this information. | ||
1960 | */ | ||
1961 | priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
1962 | if (pieces.init_evtlog_size) | ||
1963 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
1964 | else | ||
1965 | priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; | ||
1966 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; | ||
1967 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
1968 | if (pieces.inst_evtlog_size) | ||
1969 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
1970 | else | ||
1971 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | ||
1972 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
1973 | |||
1915 | /* Copy images into buffers for card's bus-master reads ... */ | 1974 | /* Copy images into buffers for card's bus-master reads ... */ |
1916 | 1975 | ||
1917 | /* Runtime instructions (first block of data in file) */ | 1976 | /* Runtime instructions (first block of data in file) */ |
@@ -2037,10 +2096,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2037 | u32 blink1, blink2, ilink1, ilink2; | 2096 | u32 blink1, blink2, ilink1, ilink2; |
2038 | u32 pc, hcmd; | 2097 | u32 pc, hcmd; |
2039 | 2098 | ||
2040 | if (priv->ucode_type == UCODE_INIT) | 2099 | if (priv->ucode_type == UCODE_INIT) { |
2041 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 2100 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
2042 | else | 2101 | if (!base) |
2102 | base = priv->_agn.init_errlog_ptr; | ||
2103 | } else { | ||
2043 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 2104 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
2105 | if (!base) | ||
2106 | base = priv->_agn.inst_errlog_ptr; | ||
2107 | } | ||
2044 | 2108 | ||
2045 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2109 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2046 | IWL_ERR(priv, | 2110 | IWL_ERR(priv, |
@@ -2100,10 +2164,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
2100 | 2164 | ||
2101 | if (num_events == 0) | 2165 | if (num_events == 0) |
2102 | return pos; | 2166 | return pos; |
2103 | if (priv->ucode_type == UCODE_INIT) | 2167 | |
2168 | if (priv->ucode_type == UCODE_INIT) { | ||
2104 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2169 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2105 | else | 2170 | if (!base) |
2171 | base = priv->_agn.init_evtlog_ptr; | ||
2172 | } else { | ||
2106 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2173 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2174 | if (!base) | ||
2175 | base = priv->_agn.inst_evtlog_ptr; | ||
2176 | } | ||
2107 | 2177 | ||
2108 | if (mode == 0) | 2178 | if (mode == 0) |
2109 | event_size = 2 * sizeof(u32); | 2179 | event_size = 2 * sizeof(u32); |
@@ -2205,13 +2275,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2205 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 2275 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
2206 | u32 next_entry; /* index of next entry to be written by uCode */ | 2276 | u32 next_entry; /* index of next entry to be written by uCode */ |
2207 | u32 size; /* # entries that we'll print */ | 2277 | u32 size; /* # entries that we'll print */ |
2278 | u32 logsize; | ||
2208 | int pos = 0; | 2279 | int pos = 0; |
2209 | size_t bufsz = 0; | 2280 | size_t bufsz = 0; |
2210 | 2281 | ||
2211 | if (priv->ucode_type == UCODE_INIT) | 2282 | if (priv->ucode_type == UCODE_INIT) { |
2212 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2283 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2213 | else | 2284 | logsize = priv->_agn.init_evtlog_size; |
2285 | if (!base) | ||
2286 | base = priv->_agn.init_evtlog_ptr; | ||
2287 | } else { | ||
2214 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2288 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2289 | logsize = priv->_agn.inst_evtlog_size; | ||
2290 | if (!base) | ||
2291 | base = priv->_agn.inst_evtlog_ptr; | ||
2292 | } | ||
2215 | 2293 | ||
2216 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2294 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2217 | IWL_ERR(priv, | 2295 | IWL_ERR(priv, |
@@ -2226,16 +2304,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2226 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2304 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
2227 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2305 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
2228 | 2306 | ||
2229 | if (capacity > priv->cfg->max_event_log_size) { | 2307 | if (capacity > logsize) { |
2230 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2308 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
2231 | capacity, priv->cfg->max_event_log_size); | 2309 | capacity, logsize); |
2232 | capacity = priv->cfg->max_event_log_size; | 2310 | capacity = logsize; |
2233 | } | 2311 | } |
2234 | 2312 | ||
2235 | if (next_entry > priv->cfg->max_event_log_size) { | 2313 | if (next_entry > logsize) { |
2236 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2314 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
2237 | next_entry, priv->cfg->max_event_log_size); | 2315 | next_entry, logsize); |
2238 | next_entry = priv->cfg->max_event_log_size; | 2316 | next_entry = logsize; |
2239 | } | 2317 | } |
2240 | 2318 | ||
2241 | size = num_wraps ? capacity : next_entry; | 2319 | size = num_wraps ? capacity : next_entry; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5ac03f5a4713..fdd043014ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -583,6 +583,12 @@ enum iwl_ucode_tlv_type { | |||
583 | IWL_UCODE_TLV_INIT_DATA = 4, | 583 | IWL_UCODE_TLV_INIT_DATA = 4, |
584 | IWL_UCODE_TLV_BOOT = 5, | 584 | IWL_UCODE_TLV_BOOT = 5, |
585 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | 585 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ |
586 | IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, | ||
587 | IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, | ||
588 | IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, | ||
589 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | ||
590 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | ||
591 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | ||
586 | }; | 592 | }; |
587 | 593 | ||
588 | struct iwl_ucode_tlv { | 594 | struct iwl_ucode_tlv { |
@@ -1317,6 +1323,9 @@ struct iwl_priv { | |||
1317 | struct iwl_notif_statistics delta_statistics; | 1323 | struct iwl_notif_statistics delta_statistics; |
1318 | struct iwl_notif_statistics max_delta; | 1324 | struct iwl_notif_statistics max_delta; |
1319 | #endif | 1325 | #endif |
1326 | |||
1327 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1328 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1320 | } _agn; | 1329 | } _agn; |
1321 | #endif | 1330 | #endif |
1322 | }; | 1331 | }; |