Commit ab606dea authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg
Browse files

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: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250424153620.758cdfbb78dc.Ia359071e6148218c26f18e783a8130c681d77df7@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c575f537
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
/* 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)

+13 −1
Original line number Diff line number Diff line
@@ -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;
	}

+14 −4
Original line number Diff line number Diff line
@@ -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,