[PATCH ath-next 8/8] wifi: ath10k: trigger recovery on PCIe MMIO wake-up failures
Kang Yang
kang.yang at oss.qualcomm.com
Fri Sep 25 05:26:38 PDT 2026
Commit 77258d409ce4 ("ath10k: enable pci soc powersaving")
introduced MMIO wake-up handling through ath10k_pci_wake().
Current code only logs MMIO wake-up failures and returns.
This becomes a problem when a PCIe link-down leaves MMIO
wake-up failures as the earliest indication that the device
has stopped responding, because the existing recovery
mechanism is not triggered until higher-layer timeout paths
expire, for example:
failed to wake target for read32 at 0x00036044: -110
failed to wake target for write32 of 0xfffff81f at 0x00034834: -110
Improve this by triggering recovery immediately on MMIO
wake-up failures and by aborting MMIO-driven waits once the
device enters ATH10K_STATE_WEDGED, because no further forward
progress is possible after either condition.
This shortens known-failed recovery attempts and helps avoid
suspend watchdog timeouts on systems where recovery time is
tightly constrained.
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00288-QCARMSWPZ-1
Fixes: 77258d409ce4 ("ath10k: enable pci soc powersaving")
Signed-off-by: Kang Yang <kang.yang at oss.qualcomm.com>
---
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
More information about the ath10k
mailing list