|
@@ -332,7 +332,7 @@ static const char *desc_lookup(u32 num)
|
|
|
* read with u32-sized accesses, any members with a different size
|
|
|
* need to be ordered correctly though!
|
|
|
*/
|
|
|
-struct iwl_error_event_table {
|
|
|
+struct iwl_error_event_table_v1 {
|
|
|
u32 valid; /* (nonzero) valid, (0) log is empty */
|
|
|
u32 error_id; /* type of error */
|
|
|
u32 pc; /* program counter */
|
|
@@ -377,7 +377,55 @@ struct iwl_error_event_table {
|
|
|
u32 u_timestamp; /* indicate when the date and time of the
|
|
|
* compilation */
|
|
|
u32 flow_handler; /* FH read/write pointers, RX credit */
|
|
|
-} __packed;
|
|
|
+} __packed /* LOG_ERROR_TABLE_API_S_VER_1 */;
|
|
|
+
|
|
|
+struct iwl_error_event_table {
|
|
|
+ u32 valid; /* (nonzero) valid, (0) log is empty */
|
|
|
+ u32 error_id; /* type of error */
|
|
|
+ u32 pc; /* program counter */
|
|
|
+ u32 blink1; /* branch link */
|
|
|
+ u32 blink2; /* branch link */
|
|
|
+ u32 ilink1; /* interrupt link */
|
|
|
+ u32 ilink2; /* interrupt link */
|
|
|
+ u32 data1; /* error-specific data */
|
|
|
+ u32 data2; /* error-specific data */
|
|
|
+ u32 data3; /* error-specific data */
|
|
|
+ u32 bcon_time; /* beacon timer */
|
|
|
+ u32 tsf_low; /* network timestamp function timer */
|
|
|
+ u32 tsf_hi; /* network timestamp function timer */
|
|
|
+ u32 gp1; /* GP1 timer register */
|
|
|
+ u32 gp2; /* GP2 timer register */
|
|
|
+ u32 gp3; /* GP3 timer register */
|
|
|
+ u32 major; /* uCode version major */
|
|
|
+ u32 minor; /* uCode version minor */
|
|
|
+ u32 hw_ver; /* HW Silicon version */
|
|
|
+ u32 brd_ver; /* HW board version */
|
|
|
+ u32 log_pc; /* log program counter */
|
|
|
+ u32 frame_ptr; /* frame pointer */
|
|
|
+ u32 stack_ptr; /* stack pointer */
|
|
|
+ u32 hcmd; /* last host command header */
|
|
|
+ u32 isr0; /* isr status register LMPM_NIC_ISR0:
|
|
|
+ * rxtx_flag */
|
|
|
+ u32 isr1; /* isr status register LMPM_NIC_ISR1:
|
|
|
+ * host_flag */
|
|
|
+ u32 isr2; /* isr status register LMPM_NIC_ISR2:
|
|
|
+ * enc_flag */
|
|
|
+ u32 isr3; /* isr status register LMPM_NIC_ISR3:
|
|
|
+ * time_flag */
|
|
|
+ u32 isr4; /* isr status register LMPM_NIC_ISR4:
|
|
|
+ * wico interrupt */
|
|
|
+ u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */
|
|
|
+ u32 wait_event; /* wait event() caller address */
|
|
|
+ u32 l2p_control; /* L2pControlField */
|
|
|
+ u32 l2p_duration; /* L2pDurationField */
|
|
|
+ u32 l2p_mhvalid; /* L2pMhValidBits */
|
|
|
+ u32 l2p_addr_match; /* L2pAddrMatchStat */
|
|
|
+ u32 lmpm_pmg_sel; /* indicate which clocks are turned on
|
|
|
+ * (LMPM_PMG_SEL) */
|
|
|
+ u32 u_timestamp; /* indicate when the date and time of the
|
|
|
+ * compilation */
|
|
|
+ u32 flow_handler; /* FH read/write pointers, RX credit */
|
|
|
+} __packed /* LOG_ERROR_TABLE_API_S_VER_2 */;
|
|
|
|
|
|
/*
|
|
|
* UMAC error struct - relevant starting from family 8000 chip.
|
|
@@ -396,11 +444,11 @@ struct iwl_umac_error_event_table {
|
|
|
u32 data1; /* error-specific data */
|
|
|
u32 data2; /* error-specific data */
|
|
|
u32 data3; /* error-specific data */
|
|
|
- u32 umac_fw_ver; /* UMAC version */
|
|
|
- u32 umac_fw_api_ver; /* UMAC FW API ver */
|
|
|
+ u32 umac_major;
|
|
|
+ u32 umac_minor;
|
|
|
u32 frame_pointer; /* core register 27*/
|
|
|
u32 stack_pointer; /* core register 28 */
|
|
|
- u32 cmd_header; /* latest host cmd sent to UMAC */
|
|
|
+ u32 cmd_header; /* latest host cmd sent to UMAC */
|
|
|
u32 nic_isr_pref; /* ISR status register */
|
|
|
} __packed;
|
|
|
|
|
@@ -441,18 +489,18 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
|
|
|
IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1);
|
|
|
IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2);
|
|
|
IWL_ERR(mvm, "0x%08X | umac data3\n", table.data3);
|
|
|
- IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_fw_ver);
|
|
|
- IWL_ERR(mvm, "0x%08X | umac api version\n", table.umac_fw_api_ver);
|
|
|
+ IWL_ERR(mvm, "0x%08X | umac major\n", table.umac_major);
|
|
|
+ IWL_ERR(mvm, "0x%08X | umac minor\n", table.umac_minor);
|
|
|
IWL_ERR(mvm, "0x%08X | frame pointer\n", table.frame_pointer);
|
|
|
IWL_ERR(mvm, "0x%08X | stack pointer\n", table.stack_pointer);
|
|
|
IWL_ERR(mvm, "0x%08X | last host cmd\n", table.cmd_header);
|
|
|
IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref);
|
|
|
}
|
|
|
|
|
|
-void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|
|
+static void iwl_mvm_dump_nic_error_log_old(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
struct iwl_trans *trans = mvm->trans;
|
|
|
- struct iwl_error_event_table table;
|
|
|
+ struct iwl_error_event_table_v1 table;
|
|
|
u32 base;
|
|
|
|
|
|
base = mvm->error_event_table;
|
|
@@ -489,7 +537,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|
|
table.data1, table.data2, table.data3,
|
|
|
table.blink1, table.blink2, table.ilink1,
|
|
|
table.ilink2, table.bcon_time, table.gp1,
|
|
|
- table.gp2, table.gp3, table.ucode_ver,
|
|
|
+ table.gp2, table.gp3, table.ucode_ver, 0,
|
|
|
table.hw_ver, table.brd_ver);
|
|
|
IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id,
|
|
|
desc_lookup(table.error_id));
|
|
@@ -530,6 +578,92 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|
|
iwl_mvm_dump_umac_error_log(mvm);
|
|
|
}
|
|
|
|
|
|
+void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|
|
+{
|
|
|
+ struct iwl_trans *trans = mvm->trans;
|
|
|
+ struct iwl_error_event_table table;
|
|
|
+ u32 base;
|
|
|
+
|
|
|
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_NEW_VERSION)) {
|
|
|
+ iwl_mvm_dump_nic_error_log_old(mvm);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ base = mvm->error_event_table;
|
|
|
+ if (mvm->cur_ucode == IWL_UCODE_INIT) {
|
|
|
+ if (!base)
|
|
|
+ base = mvm->fw->init_errlog_ptr;
|
|
|
+ } else {
|
|
|
+ if (!base)
|
|
|
+ base = mvm->fw->inst_errlog_ptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (base < 0x800000) {
|
|
|
+ IWL_ERR(mvm,
|
|
|
+ "Not valid error log pointer 0x%08X for %s uCode\n",
|
|
|
+ base,
|
|
|
+ (mvm->cur_ucode == IWL_UCODE_INIT)
|
|
|
+ ? "Init" : "RT");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
|
|
+
|
|
|
+ if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
|
|
+ IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
|
|
+ IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
|
|
|
+ mvm->status, table.valid);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Do not change this output - scripts rely on it */
|
|
|
+
|
|
|
+ IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version);
|
|
|
+
|
|
|
+ trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
|
|
|
+ table.data1, table.data2, table.data3,
|
|
|
+ table.blink1, table.blink2, table.ilink1,
|
|
|
+ table.ilink2, table.bcon_time, table.gp1,
|
|
|
+ table.gp2, table.gp3, table.major,
|
|
|
+ table.minor, table.hw_ver, table.brd_ver);
|
|
|
+ IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id,
|
|
|
+ desc_lookup(table.error_id));
|
|
|
+ IWL_ERR(mvm, "0x%08X | uPc\n", table.pc);
|
|
|
+ IWL_ERR(mvm, "0x%08X | branchlink1\n", table.blink1);
|
|
|
+ IWL_ERR(mvm, "0x%08X | branchlink2\n", table.blink2);
|
|
|
+ IWL_ERR(mvm, "0x%08X | interruptlink1\n", table.ilink1);
|
|
|
+ IWL_ERR(mvm, "0x%08X | interruptlink2\n", table.ilink2);
|
|
|
+ IWL_ERR(mvm, "0x%08X | data1\n", table.data1);
|
|
|
+ IWL_ERR(mvm, "0x%08X | data2\n", table.data2);
|
|
|
+ IWL_ERR(mvm, "0x%08X | data3\n", table.data3);
|
|
|
+ IWL_ERR(mvm, "0x%08X | beacon time\n", table.bcon_time);
|
|
|
+ IWL_ERR(mvm, "0x%08X | tsf low\n", table.tsf_low);
|
|
|
+ IWL_ERR(mvm, "0x%08X | tsf hi\n", table.tsf_hi);
|
|
|
+ IWL_ERR(mvm, "0x%08X | time gp1\n", table.gp1);
|
|
|
+ IWL_ERR(mvm, "0x%08X | time gp2\n", table.gp2);
|
|
|
+ IWL_ERR(mvm, "0x%08X | time gp3\n", table.gp3);
|
|
|
+ IWL_ERR(mvm, "0x%08X | uCode version major\n", table.major);
|
|
|
+ IWL_ERR(mvm, "0x%08X | uCode version minor\n", table.minor);
|
|
|
+ IWL_ERR(mvm, "0x%08X | hw version\n", table.hw_ver);
|
|
|
+ IWL_ERR(mvm, "0x%08X | board version\n", table.brd_ver);
|
|
|
+ IWL_ERR(mvm, "0x%08X | hcmd\n", table.hcmd);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr0\n", table.isr0);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr1\n", table.isr1);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr2\n", table.isr2);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr3\n", table.isr3);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr4\n", table.isr4);
|
|
|
+ IWL_ERR(mvm, "0x%08X | isr_pref\n", table.isr_pref);
|
|
|
+ IWL_ERR(mvm, "0x%08X | wait_event\n", table.wait_event);
|
|
|
+ IWL_ERR(mvm, "0x%08X | l2p_control\n", table.l2p_control);
|
|
|
+ IWL_ERR(mvm, "0x%08X | l2p_duration\n", table.l2p_duration);
|
|
|
+ IWL_ERR(mvm, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
|
|
|
+ IWL_ERR(mvm, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
|
|
|
+ IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
|
|
|
+ IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp);
|
|
|
+ IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
|
|
|
+
|
|
|
+ if (mvm->support_umac_log)
|
|
|
+ iwl_mvm_dump_umac_error_log(mvm);
|
|
|
+}
|
|
|
void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn,
|
|
|
const struct iwl_trans_txq_scd_cfg *cfg,
|
|
|
unsigned int wdg_timeout)
|