wifi: iwlwifi: pcie: add support for the reset handshake in MSI

Add the proper case in the MSI interrupt handler and read the non-MSIx
interrupt cause register in case of timeout.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250424153620.758cdfbb78dc.Ia359071e6148218c26f18e783a8130c681d77df7@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Emmanuel Grumbach 2025-04-24 15:38:18 +03:00 committed by Johannes Berg
parent c575f5374b
commit ab606dea80
3 changed files with 38 additions and 14 deletions

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@ -193,6 +193,7 @@
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */
#define CSR_INT_BIT_RESET_DONE (1 << 2) /* reset handshake with firmware is done */
#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
@ -203,6 +204,7 @@
CSR_INT_BIT_RF_KILL | \
CSR_INT_BIT_SW_RX | \
CSR_INT_BIT_WAKEUP | \
CSR_INT_BIT_RESET_DONE | \
CSR_INT_BIT_ALIVE | \
CSR_INT_BIT_RX_PERIODIC)

View file

@ -1947,6 +1947,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
handled |= CSR_INT_BIT_ALIVE;
}
if (inta & CSR_INT_BIT_RESET_DONE) {
IWL_DEBUG_ISR(trans, "Reset flow completed\n");
trans_pcie->fw_reset_state = FW_RESET_OK;
handled |= CSR_INT_BIT_RESET_DONE;
wake_up(&trans_pcie->fw_reset_waitq);
}
/* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
@ -1968,7 +1975,12 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
IWL_ERR(trans, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta);
isr_stats->sw++;
if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
trans_pcie->fw_reset_state = FW_RESET_ERROR;
wake_up(&trans_pcie->fw_reset_waitq);
} else {
iwl_pcie_irq_handle_error(trans);
}
handled |= CSR_INT_BIT_SW_ERR;
}

View file

@ -117,13 +117,23 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
trans_pcie->fw_reset_state != FW_RESET_REQUESTED,
FW_RESET_TIMEOUT);
if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) {
u32 inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
bool reset_done;
u32 inta_hw;
if (trans_pcie->msix_enabled) {
inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
reset_done =
inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE;
} else {
inta_hw = iwl_read32(trans, CSR_INT_MASK);
reset_done = inta_hw & CSR_INT_BIT_RESET_DONE;
}
IWL_ERR(trans,
"timeout waiting for FW reset ACK (inta_hw=0x%x)\n",
inta_hw);
"timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",
inta_hw, reset_done);
if (!(inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE)) {
if (!reset_done) {
struct iwl_fw_error_dump_mode mode = {
.type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,
.context = IWL_ERR_CONTEXT_FROM_OPMODE,