diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-02-03 13:11:48 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-03-01 09:55:12 -0500 |
commit | 7e1223b50089ab5901215d2fd8c61b42c7cfe034 (patch) | |
tree | db8a5926ff56da9f6bc51c2d8a955151f845c3d2 | |
parent | 33cef9256342f200a708211958cec9c44406631d (diff) |
iwlwifi: mvm: new Alive / error table API
The new API slightly changes the layout of the version of
the firmware - prepare for that.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-devtrace.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw-file.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw.c | 49 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 154 |
7 files changed, 245 insertions, 32 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index c4d6dd7402d9..234e30f498b2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -1549,7 +1549,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1549 | table.blink1, table.blink2, table.ilink1, | 1549 | table.blink1, table.blink2, table.ilink1, |
1550 | table.ilink2, table.bcon_time, table.gp1, | 1550 | table.ilink2, table.bcon_time, table.gp1, |
1551 | table.gp2, table.gp3, table.ucode_ver, | 1551 | table.gp2, table.gp3, table.ucode_ver, |
1552 | table.hw_ver, table.brd_ver); | 1552 | table.hw_ver, 0, table.brd_ver); |
1553 | IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, | 1553 | IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, |
1554 | desc_lookup(table.error_id)); | 1554 | desc_lookup(table.error_id)); |
1555 | IWL_ERR(priv, "0x%08X | uPc\n", table.pc); | 1555 | IWL_ERR(priv, "0x%08X | uPc\n", table.pc); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 78bd41bf34b0..53555a0fce56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -431,11 +431,11 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, | |||
431 | TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low, | 431 | TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low, |
432 | u32 data1, u32 data2, u32 line, u32 blink1, | 432 | u32 data1, u32 data2, u32 line, u32 blink1, |
433 | u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, | 433 | u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, |
434 | u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver, | 434 | u32 gp1, u32 gp2, u32 gp3, u32 major, u32 minor, u32 hw_ver, |
435 | u32 brd_ver), | 435 | u32 brd_ver), |
436 | TP_ARGS(dev, desc, tsf_low, data1, data2, line, | 436 | TP_ARGS(dev, desc, tsf_low, data1, data2, line, |
437 | blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2, | 437 | blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2, |
438 | gp3, ucode_ver, hw_ver, brd_ver), | 438 | gp3, major, minor, hw_ver, brd_ver), |
439 | TP_STRUCT__entry( | 439 | TP_STRUCT__entry( |
440 | DEV_ENTRY | 440 | DEV_ENTRY |
441 | __field(u32, desc) | 441 | __field(u32, desc) |
@@ -451,7 +451,8 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, | |||
451 | __field(u32, gp1) | 451 | __field(u32, gp1) |
452 | __field(u32, gp2) | 452 | __field(u32, gp2) |
453 | __field(u32, gp3) | 453 | __field(u32, gp3) |
454 | __field(u32, ucode_ver) | 454 | __field(u32, major) |
455 | __field(u32, minor) | ||
455 | __field(u32, hw_ver) | 456 | __field(u32, hw_ver) |
456 | __field(u32, brd_ver) | 457 | __field(u32, brd_ver) |
457 | ), | 458 | ), |
@@ -470,21 +471,22 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, | |||
470 | __entry->gp1 = gp1; | 471 | __entry->gp1 = gp1; |
471 | __entry->gp2 = gp2; | 472 | __entry->gp2 = gp2; |
472 | __entry->gp3 = gp3; | 473 | __entry->gp3 = gp3; |
473 | __entry->ucode_ver = ucode_ver; | 474 | __entry->major = major; |
475 | __entry->minor = minor; | ||
474 | __entry->hw_ver = hw_ver; | 476 | __entry->hw_ver = hw_ver; |
475 | __entry->brd_ver = brd_ver; | 477 | __entry->brd_ver = brd_ver; |
476 | ), | 478 | ), |
477 | TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, " | 479 | TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, " |
478 | "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X " | 480 | "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X " |
479 | "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X " | 481 | "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X major 0x%08X " |
480 | "hw 0x%08X brd 0x%08X", | 482 | "minor 0x%08X hw 0x%08X brd 0x%08X", |
481 | __get_str(dev), __entry->desc, __entry->tsf_low, | 483 | __get_str(dev), __entry->desc, __entry->tsf_low, |
482 | __entry->data1, | 484 | __entry->data1, |
483 | __entry->data2, __entry->line, __entry->blink1, | 485 | __entry->data2, __entry->line, __entry->blink1, |
484 | __entry->blink2, __entry->ilink1, __entry->ilink2, | 486 | __entry->blink2, __entry->ilink1, __entry->ilink2, |
485 | __entry->bcon_time, __entry->gp1, __entry->gp2, | 487 | __entry->bcon_time, __entry->gp1, __entry->gp2, |
486 | __entry->gp3, __entry->ucode_ver, __entry->hw_ver, | 488 | __entry->gp3, __entry->major, __entry->minor, |
487 | __entry->brd_ver) | 489 | __entry->hw_ver, __entry->brd_ver) |
488 | ); | 490 | ); |
489 | 491 | ||
490 | TRACE_EVENT(iwlwifi_dev_ucode_event, | 492 | TRACE_EVENT(iwlwifi_dev_ucode_event, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 996e7f16adf9..b608114b6b9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -842,6 +842,23 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
842 | capa->n_scan_channels = | 842 | capa->n_scan_channels = |
843 | le32_to_cpup((__le32 *)tlv_data); | 843 | le32_to_cpup((__le32 *)tlv_data); |
844 | break; | 844 | break; |
845 | case IWL_UCODE_TLV_FW_VERSION: { | ||
846 | __le32 *ptr = (void *)tlv_data; | ||
847 | u32 major, minor; | ||
848 | u8 local_comp; | ||
849 | |||
850 | if (tlv_len != sizeof(u32) * 3) | ||
851 | goto invalid_tlv_len; | ||
852 | |||
853 | major = le32_to_cpup(ptr++); | ||
854 | minor = le32_to_cpup(ptr++); | ||
855 | local_comp = le32_to_cpup(ptr); | ||
856 | |||
857 | snprintf(drv->fw.fw_version, | ||
858 | sizeof(drv->fw.fw_version), "%u.%u.%u", | ||
859 | major, minor, local_comp); | ||
860 | break; | ||
861 | } | ||
845 | case IWL_UCODE_TLV_FW_DBG_DEST: { | 862 | case IWL_UCODE_TLV_FW_DBG_DEST: { |
846 | struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data; | 863 | struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data; |
847 | 864 | ||
@@ -1107,7 +1124,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1107 | if (err) | 1124 | if (err) |
1108 | goto try_again; | 1125 | goto try_again; |
1109 | 1126 | ||
1110 | api_ver = IWL_UCODE_API(drv->fw.ucode_ver); | 1127 | if (drv->fw.ucode_capa.api[0] & IWL_UCODE_TLV_API_NEW_VERSION) |
1128 | api_ver = drv->fw.ucode_ver; | ||
1129 | else | ||
1130 | api_ver = IWL_UCODE_API(drv->fw.ucode_ver); | ||
1111 | 1131 | ||
1112 | /* | 1132 | /* |
1113 | * api_ver should match the api version forming part of the | 1133 | * api_ver should match the api version forming part of the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index be4393e2c19c..3ec32e8a3cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -133,6 +133,7 @@ enum iwl_ucode_tlv_type { | |||
133 | IWL_UCODE_TLV_N_SCAN_CHANNELS = 31, | 133 | IWL_UCODE_TLV_N_SCAN_CHANNELS = 31, |
134 | IWL_UCODE_TLV_SEC_RT_USNIFFER = 34, | 134 | IWL_UCODE_TLV_SEC_RT_USNIFFER = 34, |
135 | IWL_UCODE_TLV_SDIO_ADMA_ADDR = 35, | 135 | IWL_UCODE_TLV_SDIO_ADMA_ADDR = 35, |
136 | IWL_UCODE_TLV_FW_VERSION = 36, | ||
136 | IWL_UCODE_TLV_FW_DBG_DEST = 38, | 137 | IWL_UCODE_TLV_FW_DBG_DEST = 38, |
137 | IWL_UCODE_TLV_FW_DBG_CONF = 39, | 138 | IWL_UCODE_TLV_FW_DBG_CONF = 39, |
138 | }; | 139 | }; |
@@ -156,7 +157,8 @@ struct iwl_tlv_ucode_header { | |||
156 | __le32 zero; | 157 | __le32 zero; |
157 | __le32 magic; | 158 | __le32 magic; |
158 | u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; | 159 | u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; |
159 | __le32 ver; /* major/minor/API/serial */ | 160 | /* major/minor/API/serial or major in new format */ |
161 | __le32 ver; | ||
160 | __le32 build; | 162 | __le32 build; |
161 | __le64 ignore; | 163 | __le64 ignore; |
162 | /* | 164 | /* |
@@ -250,6 +252,7 @@ enum iwl_ucode_tlv_flag { | |||
250 | * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. | 252 | * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. |
251 | * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params | 253 | * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params |
252 | * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 | 254 | * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 |
255 | * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format | ||
253 | */ | 256 | */ |
254 | enum iwl_ucode_tlv_api { | 257 | enum iwl_ucode_tlv_api { |
255 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), | 258 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), |
@@ -263,6 +266,7 @@ enum iwl_ucode_tlv_api { | |||
263 | IWL_UCODE_TLV_API_ASYNC_DTM = BIT(17), | 266 | IWL_UCODE_TLV_API_ASYNC_DTM = BIT(17), |
264 | IWL_UCODE_TLV_API_LQ_SS_PARAMS = BIT(18), | 267 | IWL_UCODE_TLV_API_LQ_SS_PARAMS = BIT(18), |
265 | IWL_UCODE_TLV_API_STATS_V10 = BIT(19), | 268 | IWL_UCODE_TLV_API_STATS_V10 = BIT(19), |
269 | IWL_UCODE_TLV_API_NEW_VERSION = BIT(20), | ||
266 | }; | 270 | }; |
267 | 271 | ||
268 | /** | 272 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index c43e5c2bb85c..d95b47213731 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -432,7 +432,7 @@ enum { | |||
432 | 432 | ||
433 | #define IWL_ALIVE_FLG_RFKILL BIT(0) | 433 | #define IWL_ALIVE_FLG_RFKILL BIT(0) |
434 | 434 | ||
435 | struct mvm_alive_resp { | 435 | struct mvm_alive_resp_ver1 { |
436 | __le16 status; | 436 | __le16 status; |
437 | __le16 flags; | 437 | __le16 flags; |
438 | u8 ucode_minor; | 438 | u8 ucode_minor; |
@@ -483,6 +483,30 @@ struct mvm_alive_resp_ver2 { | |||
483 | __le32 dbg_print_buff_addr; | 483 | __le32 dbg_print_buff_addr; |
484 | } __packed; /* ALIVE_RES_API_S_VER_2 */ | 484 | } __packed; /* ALIVE_RES_API_S_VER_2 */ |
485 | 485 | ||
486 | struct mvm_alive_resp { | ||
487 | __le16 status; | ||
488 | __le16 flags; | ||
489 | __le32 ucode_minor; | ||
490 | __le32 ucode_major; | ||
491 | u8 ver_subtype; | ||
492 | u8 ver_type; | ||
493 | u8 mac; | ||
494 | u8 opt; | ||
495 | __le32 timestamp; | ||
496 | __le32 error_event_table_ptr; /* SRAM address for error log */ | ||
497 | __le32 log_event_table_ptr; /* SRAM address for LMAC event log */ | ||
498 | __le32 cpu_register_ptr; | ||
499 | __le32 dbgm_config_ptr; | ||
500 | __le32 alive_counter_ptr; | ||
501 | __le32 scd_base_ptr; /* SRAM address for SCD */ | ||
502 | __le32 st_fwrd_addr; /* pointer to Store and forward */ | ||
503 | __le32 st_fwrd_size; | ||
504 | __le32 umac_minor; /* UMAC version: minor */ | ||
505 | __le32 umac_major; /* UMAC version: major */ | ||
506 | __le32 error_info_addr; /* SRAM address for UMAC error log */ | ||
507 | __le32 dbg_print_buff_addr; | ||
508 | } __packed; /* ALIVE_RES_API_S_VER_3 */ | ||
509 | |||
486 | /* Error response/notification */ | 510 | /* Error response/notification */ |
487 | enum { | 511 | enum { |
488 | FW_ERR_UNKNOWN_CMD = 0x0, | 512 | FW_ERR_UNKNOWN_CMD = 0x0, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index ab81124c6029..7426bb0811be 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -112,25 +112,27 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
112 | struct iwl_mvm *mvm = | 112 | struct iwl_mvm *mvm = |
113 | container_of(notif_wait, struct iwl_mvm, notif_wait); | 113 | container_of(notif_wait, struct iwl_mvm, notif_wait); |
114 | struct iwl_mvm_alive_data *alive_data = data; | 114 | struct iwl_mvm_alive_data *alive_data = data; |
115 | struct mvm_alive_resp *palive; | 115 | struct mvm_alive_resp_ver1 *palive1; |
116 | struct mvm_alive_resp_ver2 *palive2; | 116 | struct mvm_alive_resp_ver2 *palive2; |
117 | struct mvm_alive_resp *palive; | ||
117 | 118 | ||
118 | if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { | 119 | if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive1)) { |
119 | palive = (void *)pkt->data; | 120 | palive1 = (void *)pkt->data; |
120 | 121 | ||
121 | mvm->support_umac_log = false; | 122 | mvm->support_umac_log = false; |
122 | mvm->error_event_table = | 123 | mvm->error_event_table = |
123 | le32_to_cpu(palive->error_event_table_ptr); | 124 | le32_to_cpu(palive1->error_event_table_ptr); |
124 | mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr); | 125 | mvm->log_event_table = |
125 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); | 126 | le32_to_cpu(palive1->log_event_table_ptr); |
127 | alive_data->scd_base_addr = le32_to_cpu(palive1->scd_base_ptr); | ||
126 | 128 | ||
127 | alive_data->valid = le16_to_cpu(palive->status) == | 129 | alive_data->valid = le16_to_cpu(palive1->status) == |
128 | IWL_ALIVE_STATUS_OK; | 130 | IWL_ALIVE_STATUS_OK; |
129 | IWL_DEBUG_FW(mvm, | 131 | IWL_DEBUG_FW(mvm, |
130 | "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", | 132 | "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", |
131 | le16_to_cpu(palive->status), palive->ver_type, | 133 | le16_to_cpu(palive1->status), palive1->ver_type, |
132 | palive->ver_subtype, palive->flags); | 134 | palive1->ver_subtype, palive1->flags); |
133 | } else { | 135 | } else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive2)) { |
134 | palive2 = (void *)pkt->data; | 136 | palive2 = (void *)pkt->data; |
135 | 137 | ||
136 | mvm->error_event_table = | 138 | mvm->error_event_table = |
@@ -156,6 +158,33 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
156 | IWL_DEBUG_FW(mvm, | 158 | IWL_DEBUG_FW(mvm, |
157 | "UMAC version: Major - 0x%x, Minor - 0x%x\n", | 159 | "UMAC version: Major - 0x%x, Minor - 0x%x\n", |
158 | palive2->umac_major, palive2->umac_minor); | 160 | palive2->umac_major, palive2->umac_minor); |
161 | } else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { | ||
162 | palive = (void *)pkt->data; | ||
163 | |||
164 | mvm->error_event_table = | ||
165 | le32_to_cpu(palive->error_event_table_ptr); | ||
166 | mvm->log_event_table = | ||
167 | le32_to_cpu(palive->log_event_table_ptr); | ||
168 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); | ||
169 | mvm->umac_error_event_table = | ||
170 | le32_to_cpu(palive->error_info_addr); | ||
171 | mvm->sf_space.addr = le32_to_cpu(palive->st_fwrd_addr); | ||
172 | mvm->sf_space.size = le32_to_cpu(palive->st_fwrd_size); | ||
173 | |||
174 | alive_data->valid = le16_to_cpu(palive->status) == | ||
175 | IWL_ALIVE_STATUS_OK; | ||
176 | if (mvm->umac_error_event_table) | ||
177 | mvm->support_umac_log = true; | ||
178 | |||
179 | IWL_DEBUG_FW(mvm, | ||
180 | "Alive VER3 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", | ||
181 | le16_to_cpu(palive->status), palive->ver_type, | ||
182 | palive->ver_subtype, palive->flags); | ||
183 | |||
184 | IWL_DEBUG_FW(mvm, | ||
185 | "UMAC version: Major - 0x%x, Minor - 0x%x\n", | ||
186 | le32_to_cpu(palive->umac_major), | ||
187 | le32_to_cpu(palive->umac_minor)); | ||
159 | } | 188 | } |
160 | 189 | ||
161 | return true; | 190 | return true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a50122344aac..2b9de63951e6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -332,7 +332,7 @@ static const char *desc_lookup(u32 num) | |||
332 | * read with u32-sized accesses, any members with a different size | 332 | * read with u32-sized accesses, any members with a different size |
333 | * need to be ordered correctly though! | 333 | * need to be ordered correctly though! |
334 | */ | 334 | */ |
335 | struct iwl_error_event_table { | 335 | struct iwl_error_event_table_v1 { |
336 | u32 valid; /* (nonzero) valid, (0) log is empty */ | 336 | u32 valid; /* (nonzero) valid, (0) log is empty */ |
337 | u32 error_id; /* type of error */ | 337 | u32 error_id; /* type of error */ |
338 | u32 pc; /* program counter */ | 338 | u32 pc; /* program counter */ |
@@ -377,7 +377,55 @@ struct iwl_error_event_table { | |||
377 | u32 u_timestamp; /* indicate when the date and time of the | 377 | u32 u_timestamp; /* indicate when the date and time of the |
378 | * compilation */ | 378 | * compilation */ |
379 | u32 flow_handler; /* FH read/write pointers, RX credit */ | 379 | u32 flow_handler; /* FH read/write pointers, RX credit */ |
380 | } __packed; | 380 | } __packed /* LOG_ERROR_TABLE_API_S_VER_1 */; |
381 | |||
382 | struct iwl_error_event_table { | ||
383 | u32 valid; /* (nonzero) valid, (0) log is empty */ | ||
384 | u32 error_id; /* type of error */ | ||
385 | u32 pc; /* program counter */ | ||
386 | u32 blink1; /* branch link */ | ||
387 | u32 blink2; /* branch link */ | ||
388 | u32 ilink1; /* interrupt link */ | ||
389 | u32 ilink2; /* interrupt link */ | ||
390 | u32 data1; /* error-specific data */ | ||
391 | u32 data2; /* error-specific data */ | ||
392 | u32 data3; /* error-specific data */ | ||
393 | u32 bcon_time; /* beacon timer */ | ||
394 | u32 tsf_low; /* network timestamp function timer */ | ||
395 | u32 tsf_hi; /* network timestamp function timer */ | ||
396 | u32 gp1; /* GP1 timer register */ | ||
397 | u32 gp2; /* GP2 timer register */ | ||
398 | u32 gp3; /* GP3 timer register */ | ||
399 | u32 major; /* uCode version major */ | ||
400 | u32 minor; /* uCode version minor */ | ||
401 | u32 hw_ver; /* HW Silicon version */ | ||
402 | u32 brd_ver; /* HW board version */ | ||
403 | u32 log_pc; /* log program counter */ | ||
404 | u32 frame_ptr; /* frame pointer */ | ||
405 | u32 stack_ptr; /* stack pointer */ | ||
406 | u32 hcmd; /* last host command header */ | ||
407 | u32 isr0; /* isr status register LMPM_NIC_ISR0: | ||
408 | * rxtx_flag */ | ||
409 | u32 isr1; /* isr status register LMPM_NIC_ISR1: | ||
410 | * host_flag */ | ||
411 | u32 isr2; /* isr status register LMPM_NIC_ISR2: | ||
412 | * enc_flag */ | ||
413 | u32 isr3; /* isr status register LMPM_NIC_ISR3: | ||
414 | * time_flag */ | ||
415 | u32 isr4; /* isr status register LMPM_NIC_ISR4: | ||
416 | * wico interrupt */ | ||
417 | u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ | ||
418 | u32 wait_event; /* wait event() caller address */ | ||
419 | u32 l2p_control; /* L2pControlField */ | ||
420 | u32 l2p_duration; /* L2pDurationField */ | ||
421 | u32 l2p_mhvalid; /* L2pMhValidBits */ | ||
422 | u32 l2p_addr_match; /* L2pAddrMatchStat */ | ||
423 | u32 lmpm_pmg_sel; /* indicate which clocks are turned on | ||
424 | * (LMPM_PMG_SEL) */ | ||
425 | u32 u_timestamp; /* indicate when the date and time of the | ||
426 | * compilation */ | ||
427 | u32 flow_handler; /* FH read/write pointers, RX credit */ | ||
428 | } __packed /* LOG_ERROR_TABLE_API_S_VER_2 */; | ||
381 | 429 | ||
382 | /* | 430 | /* |
383 | * UMAC error struct - relevant starting from family 8000 chip. | 431 | * UMAC error struct - relevant starting from family 8000 chip. |
@@ -396,11 +444,11 @@ struct iwl_umac_error_event_table { | |||
396 | u32 data1; /* error-specific data */ | 444 | u32 data1; /* error-specific data */ |
397 | u32 data2; /* error-specific data */ | 445 | u32 data2; /* error-specific data */ |
398 | u32 data3; /* error-specific data */ | 446 | u32 data3; /* error-specific data */ |
399 | u32 umac_fw_ver; /* UMAC version */ | 447 | u32 umac_major; |
400 | u32 umac_fw_api_ver; /* UMAC FW API ver */ | 448 | u32 umac_minor; |
401 | u32 frame_pointer; /* core register 27*/ | 449 | u32 frame_pointer; /* core register 27*/ |
402 | u32 stack_pointer; /* core register 28 */ | 450 | u32 stack_pointer; /* core register 28 */ |
403 | u32 cmd_header; /* latest host cmd sent to UMAC */ | 451 | u32 cmd_header; /* latest host cmd sent to UMAC */ |
404 | u32 nic_isr_pref; /* ISR status register */ | 452 | u32 nic_isr_pref; /* ISR status register */ |
405 | } __packed; | 453 | } __packed; |
406 | 454 | ||
@@ -441,18 +489,18 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) | |||
441 | IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1); | 489 | IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1); |
442 | IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2); | 490 | IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2); |
443 | IWL_ERR(mvm, "0x%08X | umac data3\n", table.data3); | 491 | IWL_ERR(mvm, "0x%08X | umac data3\n", table.data3); |
444 | IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_fw_ver); | 492 | IWL_ERR(mvm, "0x%08X | umac major\n", table.umac_major); |
445 | IWL_ERR(mvm, "0x%08X | umac api version\n", table.umac_fw_api_ver); | 493 | IWL_ERR(mvm, "0x%08X | umac minor\n", table.umac_minor); |
446 | IWL_ERR(mvm, "0x%08X | frame pointer\n", table.frame_pointer); | 494 | IWL_ERR(mvm, "0x%08X | frame pointer\n", table.frame_pointer); |
447 | IWL_ERR(mvm, "0x%08X | stack pointer\n", table.stack_pointer); | 495 | IWL_ERR(mvm, "0x%08X | stack pointer\n", table.stack_pointer); |
448 | IWL_ERR(mvm, "0x%08X | last host cmd\n", table.cmd_header); | 496 | IWL_ERR(mvm, "0x%08X | last host cmd\n", table.cmd_header); |
449 | IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref); | 497 | IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref); |
450 | } | 498 | } |
451 | 499 | ||
452 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | 500 | static void iwl_mvm_dump_nic_error_log_old(struct iwl_mvm *mvm) |
453 | { | 501 | { |
454 | struct iwl_trans *trans = mvm->trans; | 502 | struct iwl_trans *trans = mvm->trans; |
455 | struct iwl_error_event_table table; | 503 | struct iwl_error_event_table_v1 table; |
456 | u32 base; | 504 | u32 base; |
457 | 505 | ||
458 | base = mvm->error_event_table; | 506 | base = mvm->error_event_table; |
@@ -489,7 +537,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
489 | table.data1, table.data2, table.data3, | 537 | table.data1, table.data2, table.data3, |
490 | table.blink1, table.blink2, table.ilink1, | 538 | table.blink1, table.blink2, table.ilink1, |
491 | table.ilink2, table.bcon_time, table.gp1, | 539 | table.ilink2, table.bcon_time, table.gp1, |
492 | table.gp2, table.gp3, table.ucode_ver, | 540 | table.gp2, table.gp3, table.ucode_ver, 0, |
493 | table.hw_ver, table.brd_ver); | 541 | table.hw_ver, table.brd_ver); |
494 | IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, | 542 | IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, |
495 | desc_lookup(table.error_id)); | 543 | desc_lookup(table.error_id)); |
@@ -530,6 +578,92 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
530 | iwl_mvm_dump_umac_error_log(mvm); | 578 | iwl_mvm_dump_umac_error_log(mvm); |
531 | } | 579 | } |
532 | 580 | ||
581 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | ||
582 | { | ||
583 | struct iwl_trans *trans = mvm->trans; | ||
584 | struct iwl_error_event_table table; | ||
585 | u32 base; | ||
586 | |||
587 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_NEW_VERSION)) { | ||
588 | iwl_mvm_dump_nic_error_log_old(mvm); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | base = mvm->error_event_table; | ||
593 | if (mvm->cur_ucode == IWL_UCODE_INIT) { | ||
594 | if (!base) | ||
595 | base = mvm->fw->init_errlog_ptr; | ||
596 | } else { | ||
597 | if (!base) | ||
598 | base = mvm->fw->inst_errlog_ptr; | ||
599 | } | ||
600 | |||
601 | if (base < 0x800000) { | ||
602 | IWL_ERR(mvm, | ||
603 | "Not valid error log pointer 0x%08X for %s uCode\n", | ||
604 | base, | ||
605 | (mvm->cur_ucode == IWL_UCODE_INIT) | ||
606 | ? "Init" : "RT"); | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); | ||
611 | |||
612 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | ||
613 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | ||
614 | IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", | ||
615 | mvm->status, table.valid); | ||
616 | } | ||
617 | |||
618 | /* Do not change this output - scripts rely on it */ | ||
619 | |||
620 | IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); | ||
621 | |||
622 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | ||
623 | table.data1, table.data2, table.data3, | ||
624 | table.blink1, table.blink2, table.ilink1, | ||
625 | table.ilink2, table.bcon_time, table.gp1, | ||
626 | table.gp2, table.gp3, table.major, | ||
627 | table.minor, table.hw_ver, table.brd_ver); | ||
628 | IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, | ||
629 | desc_lookup(table.error_id)); | ||
630 | IWL_ERR(mvm, "0x%08X | uPc\n", table.pc); | ||
631 | IWL_ERR(mvm, "0x%08X | branchlink1\n", table.blink1); | ||
632 | IWL_ERR(mvm, "0x%08X | branchlink2\n", table.blink2); | ||
633 | IWL_ERR(mvm, "0x%08X | interruptlink1\n", table.ilink1); | ||
634 | IWL_ERR(mvm, "0x%08X | interruptlink2\n", table.ilink2); | ||
635 | IWL_ERR(mvm, "0x%08X | data1\n", table.data1); | ||
636 | IWL_ERR(mvm, "0x%08X | data2\n", table.data2); | ||
637 | IWL_ERR(mvm, "0x%08X | data3\n", table.data3); | ||
638 | IWL_ERR(mvm, "0x%08X | beacon time\n", table.bcon_time); | ||
639 | IWL_ERR(mvm, "0x%08X | tsf low\n", table.tsf_low); | ||
640 | IWL_ERR(mvm, "0x%08X | tsf hi\n", table.tsf_hi); | ||
641 | IWL_ERR(mvm, "0x%08X | time gp1\n", table.gp1); | ||
642 | IWL_ERR(mvm, "0x%08X | time gp2\n", table.gp2); | ||
643 | IWL_ERR(mvm, "0x%08X | time gp3\n", table.gp3); | ||
644 | IWL_ERR(mvm, "0x%08X | uCode version major\n", table.major); | ||
645 | IWL_ERR(mvm, "0x%08X | uCode version minor\n", table.minor); | ||
646 | IWL_ERR(mvm, "0x%08X | hw version\n", table.hw_ver); | ||
647 | IWL_ERR(mvm, "0x%08X | board version\n", table.brd_ver); | ||
648 | IWL_ERR(mvm, "0x%08X | hcmd\n", table.hcmd); | ||
649 | IWL_ERR(mvm, "0x%08X | isr0\n", table.isr0); | ||
650 | IWL_ERR(mvm, "0x%08X | isr1\n", table.isr1); | ||
651 | IWL_ERR(mvm, "0x%08X | isr2\n", table.isr2); | ||
652 | IWL_ERR(mvm, "0x%08X | isr3\n", table.isr3); | ||
653 | IWL_ERR(mvm, "0x%08X | isr4\n", table.isr4); | ||
654 | IWL_ERR(mvm, "0x%08X | isr_pref\n", table.isr_pref); | ||
655 | IWL_ERR(mvm, "0x%08X | wait_event\n", table.wait_event); | ||
656 | IWL_ERR(mvm, "0x%08X | l2p_control\n", table.l2p_control); | ||
657 | IWL_ERR(mvm, "0x%08X | l2p_duration\n", table.l2p_duration); | ||
658 | IWL_ERR(mvm, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); | ||
659 | IWL_ERR(mvm, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); | ||
660 | IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); | ||
661 | IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp); | ||
662 | IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); | ||
663 | |||
664 | if (mvm->support_umac_log) | ||
665 | iwl_mvm_dump_umac_error_log(mvm); | ||
666 | } | ||
533 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 667 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, |
534 | const struct iwl_trans_txq_scd_cfg *cfg, | 668 | const struct iwl_trans_txq_scd_cfg *cfg, |
535 | unsigned int wdg_timeout) | 669 | unsigned int wdg_timeout) |