[PATCH ath-current] wifi: ath11k: fix unbalanced IRQ enable/disable during suspend/resume

Baochen Qiang baochen.qiang at oss.qualcomm.com
Mon Sep 28 03:45:25 PDT 2026


Commit f7a74e131d3f ("wifi: ath11k: disable interrupts during firmware
crash recovery") added an unconditional ath11k_hif_irq_disable()/
ath11k_hif_ce_irq_disable() pair inside
ath11k_core_reconfigure_on_crash(), guarded by "if (!ab->is_reset)", to
stop the DP NAPI from touching rings that have just been torn down. That
fixes AHB device recovery, but breaks PCI device suspend/resume. During
suspend, IRQs are disabled once in ath11k_core_suspend_late(). Then during
resume, ath11k_core_reconfigure_on_crash() sees ab->is_reset clear and
disables them a second time. Those IRQs are enabled only once during
the following reinitialization, leaving the IRQ lines masked. As a result,
HTC control responses never arrive, and resume fails:

  failed to receive control response completion, polling..
  failed to connect to HTT: -110
  failed to reconfigure driver on crash recovery
  failed to resume core: -110

Fix this by disabling the IRQs unconditionally at the top of
ath11k_core_reconfigure_on_crash(), and instead drop the disable
calls from the two places that already disable IRQs before this
function can run: ath11k_core_suspend_late() and ath11k_core_reset().
This keeps a single disable per recovery/suspend cycle regardless of
which path (recovery or suspend) triggers it, so the refcount on
PCI parts stays balanced while AHB parts keep getting the disable
that the original commit needed.

Fixes: f7a74e131d3f ("wifi: ath11k: disable interrupts during firmware crash recovery")
Reported-by: Marek Szyprowski <m.szyprowski at samsung.com>
Closes: https://lore.kernel.org/linux-wireless/a068a857-a549-4cc2-ae0f-3ef119d3a859@samsung.com/
Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Tested-by: Julius Bairaktaris <julius at bairaktaris.de>
Signed-off-by: Baochen Qiang <baochen.qiang at oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath11k/core.c | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index d2ed6a0ea7e3..1ad0a47653de 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -1275,9 +1275,6 @@ int ath11k_core_suspend_late(struct ath11k_base *ab)
 	if (ab->actual_pm_policy == ATH11K_PM_WOW)
 		return 0;
 
-	ath11k_hif_irq_disable(ab);
-	ath11k_hif_ce_irq_disable(ab);
-
 	ath11k_hif_power_down(ab, true);
 
 	return 0;
@@ -2333,17 +2330,9 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
 	int ret;
 
 	mutex_lock(&ab->core_lock);
+	ath11k_hif_irq_disable(ab);
+	ath11k_hif_ce_irq_disable(ab);
 	ath11k_thermal_unregister(ab);
-
-	/*
-	 * ath11k_core_reset() already disabled the interrupts on the reset
-	 * path; only the firmware crash path reaches here with them live.
-	 */
-	if (!ab->is_reset) {
-		ath11k_hif_irq_disable(ab);
-		ath11k_hif_ce_irq_disable(ab);
-	}
-
 	ath11k_dp_pdev_free(ab);
 	ath11k_cfr_deinit(ab);
 	ath11k_spectral_deinit(ab);
@@ -2605,9 +2594,6 @@ static void ath11k_core_reset(struct work_struct *work)
 	time_left = wait_for_completion_timeout(&ab->recovery_start,
 						ATH11K_RECOVER_START_TIMEOUT_HZ);
 
-	ath11k_hif_irq_disable(ab);
-	ath11k_hif_ce_irq_disable(ab);
-
 	ath11k_hif_power_down(ab, false);
 	ath11k_hif_power_up(ab);
 

---
base-commit: 03dee8921448c661b06116d14967a57fbecaee6d
change-id: 20260921-ath11k-unbalanced-irq-enable-disable-4beab9a3300f

Best regards,
-- 
Baochen Qiang <baochen.qiang at oss.qualcomm.com>




More information about the ath11k mailing list