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 <[email protected]> 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 <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Yunseong Kim <[email protected]> --- 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

