[PATCH ath-next v3 07/10] wifi: ath10k: trigger recovery on PCIe MMIO wake-up failures
From: Kang Yang
Date: Thu Nov 12 2026 - 06:40:52 EST
Commit 77258d409ce4 ("ath10k: enable pci soc powersaving")
introduced MMIO wake-up handling through ath10k_pci_wake().
The current code only logs an error when the target cannot be
woken for an MMIO access:
failed to wake target for read32 at 0x00036044: -110
failed to wake target for write32 of 0xfffff81f at 0x00034834: -110
When the target or PCIe link stops responding, an MMIO wake-up
failure may be the earliest indication that the device is no
longer accessible. Since it does not trigger recovery, recovery
may be delayed until another path requests it.
Trigger recovery immediately on MMIO wake-up failures while the
device is running. Also abort PCIe wake, BMI and target-
initialization waits once the device enters ATH10K_STATE_WEDGED,
because no further hardware progress is possible.
This triggers recovery earlier and avoids unnecessary timeout
delays that may lead to suspend watchdog timeouts.
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00288-QCARMSWPZ-1
Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00189
Fixes: 77258d409ce4 ("ath10k: enable pci soc powersaving")
Signed-off-by: Kang Yang <kang.yang@xxxxxxxxxxxxxxxx>
---
drivers/net/wireless/ath/ath10k/pci.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 335bc7c488e4..0c671630cfc9 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -478,6 +478,10 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
return 0;
}
+ /* The device cannot wake once it is wedged. */
+ if (ar->state == ATH10K_STATE_WEDGED)
+ return -ESHUTDOWN;
+
udelay(curr_delay);
tot_delay += curr_delay;
@@ -642,6 +646,16 @@ static void ath10k_bus_pci_write32(struct ath10k *ar, u32 offset, u32 value)
if (ret) {
ath10k_warn(ar, "failed to wake target for write32 of 0x%08x at 0x%08x: %d\n",
value, offset, ret);
+ /*
+ * wake_wait timed out; the device is unresponsive at the
+ * MMIO level. write32 returns void so the write is
+ * silently dropped -- kick recovery here instead of
+ * letting an upper WMI wait notice it seconds later.
+ * Guards confine this to runtime; cmpxchg dedups.
+ */
+ if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags) &&
+ ar->state == ATH10K_STATE_ON)
+ ath10k_core_start_recovery(ar);
return;
}
@@ -665,6 +679,9 @@ static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset)
if (ret) {
ath10k_warn(ar, "failed to wake target for read32 at 0x%08x: %d\n",
offset, ret);
+ if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags) &&
+ ar->state == ATH10K_STATE_ON)
+ ath10k_core_start_recovery(ar);
return 0xffffffff;
}
@@ -2248,6 +2265,12 @@ static int ath10k_pci_bmi_wait(struct ath10k *ar,
goto out;
}
+ /* Stop waiting once the device is wedged. */
+ if (ar->state == ATH10K_STATE_WEDGED) {
+ ret = -ESHUTDOWN;
+ goto out;
+ }
+
schedule();
}
@@ -3308,6 +3331,10 @@ int ath10k_pci_wait_for_target_init(struct ath10k *ar)
if (val & FW_IND_INITIALIZED)
break;
+ /* Stop waiting once the device is wedged. */
+ if (ar->state == ATH10K_STATE_WEDGED)
+ break;
+
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_INTX)
/* Fix potential race by repeating CORE_BASE writes */
ath10k_pci_enable_intx_irq(ar);
--
2.34.1