[PATCH 1/3] wifi: ath11k: don't free HAL SRNG memory when crash recovery fails

From: Yunseong Kim

Date: Mon Nov 02 2026 - 07:11:51 EST


During system suspend/resume (such as s2idle), the device can go through
the crash recovery path (ath11k_core_restart() ->
ath11k_core_reconfigure_on_crash()). In this path, ath11k_dp_alloc()
requests a 1 MiB order-8 allocation for tx_status. Because the PM core
restricts allocations to GFP_NOIO during suspend/resume (via
pm_restrict_gfp_mask()), direct reclaim cannot perform I/O and direct
memory compaction is disabled. If memory is fragmented, reclaim fails to
form an order-8 contiguous block, and the 1 MiB allocation fails with
-ENOMEM.

When firmware crash recovery fails due to this allocation failure (or any
other failure during ath11k_core_qmi_firmware_ready()),
ath11k_core_reconfigure_on_crash() takes the error exit path and calls
ath11k_hal_srng_deinit().

This is fatal for two reasons:
1. HAL SRNG memory is allocated at driver probe and freed at driver
remove. Freeing it during crash recovery leaves CE and DP rings
(which were already set up again, e.g. by ath11k_ce_init_pipes())
with dangling pointers into unmapped DMA coherent memory (hal->rdp).
2. ATH11K_FLAG_CRASH_FLUSH was cleared before the reconfiguration
attempt and was not set again on failure. Consequently, when the PM
framework subsequently resumes subordinate devices (e.g. wiphy via
wiphy_resume() -> drv_start() -> ath11k_mac_op_start()),
ath11k_ce_send() does not bail out. It attempts to access the CE3
source ring and calls ath11k_hal_srng_access_begin(), which dereferences
srng->u.src_ring.tp_addr (pointing to the freed rdp buffer). Under an
IOMMU this triggers an unhandled page fault in interrupt context,
panicking the kernel.

Fix this by preserving the HAL SRNG memory across failed crash recovery
and setting ATH11K_FLAG_CRASH_FLUSH so that all subsequent CE, WMI, and
DP send operations immediately bail out with -ESHUTDOWN.

Reported-by: Jeroen Trappers <jeroen.trappers@xxxxxxxxx>
Closes: https://bugs.debian.org/1152007
Fixes: 32be3ca4cf78 ("wifi: ath11k: HAL SRNG: don't deinitialize and re-initialize again")
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Cc: Jeroen Trappers <jeroen.trappers@xxxxxxxxx>
Cc: 1152007@xxxxxxxxxxxxxxx
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yunseong Kim <yunseong.kim@xxxxxxxx>
---
drivers/net/wireless/ath/ath11k/core.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 766ae27306f43..b859b26f31114 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -2349,16 +2349,24 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);

ret = ath11k_core_qmi_firmware_ready(ab);
- if (ret)
- goto err_hal_srng_deinit;
+ if (ret) {
+ /* The firmware has been stopped and the data path is gone,
+ * but mac80211 may still call into the driver (e.g. drv_start
+ * from the wiphy resume). Treat the device as crashed so that
+ * WMI, CE and DP TX bail out until a later recovery succeeds.
+ *
+ * Do not free the HAL SRNG memory here: it is allocated at
+ * probe and freed at remove, and rings that were already set
+ * up again (e.g. by ath11k_ce_init_pipes()) still point into
+ * it.
+ */
+ set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
+ return ret;
+ }

clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);

return 0;
-
-err_hal_srng_deinit:
- ath11k_hal_srng_deinit(ab);
- return ret;
}

void ath11k_core_halt(struct ath11k *ar)

--
2.47.3