From: Kirtika Ruchandani <kirtika@xxxxxxxxxxxx> Commit a6d24fad00d9 ("iwlwifi: pcie: dump registers when HW becomes inaccessible") added a function to dump pcie config registers and memory mapped registers on a failure. It is currently only accessible within trans.c. Add it to struct iwl_trans_ops, so that failure cases in other files can call it. While there, add a call to this function from iwl_pcie_load_firmware_chunk in pcie/tx.c, since this is a common failure case seen on some platforms. Signed-off-by: Kirtika Ruchandani <kirtika@xxxxxxxxxxxx> [modified the commit message slightly] Signed-off-by: Luca Coelho <luciano.coelho@xxxxxxxxx> --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 11 +++++++++++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 7 ++++--- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 3138f637ab2a..ca0b5536a8a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -520,6 +520,9 @@ struct iwl_trans_txq_scd_cfg { * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last * TX'ed commands and similar. The buffer will be vfree'd by the caller. * Note that the transport must fill in the proper file headers. + * @dump_regs: dump using IWL_ERR configuration space and memory mapped + * registers of the device to diagnose failure, e.g., when HW becomes + * inaccessible. */ struct iwl_trans_ops { @@ -587,6 +590,8 @@ struct iwl_trans_ops { struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, const struct iwl_fw_dbg_trigger_tlv *trigger); + + void (*dump_regs)(struct iwl_trans *trans); }; /** @@ -865,6 +870,12 @@ iwl_trans_dump_data(struct iwl_trans *trans, return trans->ops->dump_data(trans, trigger); } +static inline void iwl_trans_dump_regs(struct iwl_trans *trans) +{ + if (trans->ops->dump_regs) + trans->ops->dump_regs(trans); +} + static inline struct iwl_device_cmd * iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 0008ea323be3..8d992d5ba064 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -88,7 +88,7 @@ #define IWL_FW_MEM_EXTENDED_START 0x40000 #define IWL_FW_MEM_EXTENDED_END 0x57FFF -static void iwl_trans_pcie_err_dump(struct iwl_trans *trans) +static void iwl_trans_pcie_dump_regs(struct iwl_trans *trans) { #define PCI_DUMP_SIZE 64 #define PREFIX_LEN 32 @@ -736,7 +736,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, trans_pcie->ucode_write_complete, 5 * HZ); if (!ret) { IWL_ERR(trans, "Failed to load firmware chunk!\n"); - iwl_trans_pcie_err_dump(trans); + iwl_trans_pcie_dump_regs(trans); return -ETIMEDOUT; } @@ -1956,7 +1956,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (unlikely(ret < 0)) { - iwl_trans_pcie_err_dump(trans); + iwl_trans_pcie_dump_regs(trans); iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); WARN_ONCE(1, "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", @@ -3021,6 +3021,7 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans) .ref = iwl_trans_pcie_ref, \ .unref = iwl_trans_pcie_unref, \ .dump_data = iwl_trans_pcie_dump_data, \ + .dump_regs = iwl_trans_pcie_dump_regs, \ .d3_suspend = iwl_trans_pcie_d3_suspend, \ .d3_resume = iwl_trans_pcie_d3_resume diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index e93c471ef9bf..b5c459cd70ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1909,6 +1909,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, } if (test_bit(STATUS_FW_ERROR, &trans->status)) { + iwl_trans_dump_regs(trans); IWL_ERR(trans, "FW error in SYNC CMD %s\n", iwl_get_cmd_string(trans, cmd->id)); dump_stack(); -- 2.14.2