]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath11k: cancel SSR work items during PCI shutdown
authorWei Zhang <wei.zhang@oss.qualcomm.com>
Sat, 4 Apr 2026 04:30:50 +0000 (21:30 -0700)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 30 Apr 2026 21:24:08 +0000 (14:24 -0700)
A reboot can crash the kernel if it overlaps with WLAN firmware crash
recovery (SSR). The crash is a NULL pointer dereference in the MHI teardown
path while freeing DMA-backed MHI contexts.

Simplified trace:
  dma_free_attrs
  mhi_deinit_dev_ctxt [mhi]
  ath11k_pci_power_down [ath11k_pci]
  ath11k_pci_shutdown [ath11k_pci]
  device_shutdown
  kernel_restart

On the host side, SSR is driven by the MHI RDDM callback, which queues
reset_work to perform device recovery. reset_work power-cycles the device
by calling ath11k_hif_power_down() followed by ath11k_hif_power_up(). The
power-down phase deinitializes MHI and frees DMA resources.

Shutdown/reboot runs fully asynchronously with this RDDM-driven SSR
recovery flow. As a result, the shutdown path
(ath11k_pci_shutdown() -> ath11k_pci_power_down()) can race with the SSR
recovery sequence.

Fix this by canceling SSR-related work items during PCI shutdown, marking
the device as unregistering, and serializing the RDDM callback path that
checks and queues reset_work. This ensures that no new SSR recovery work
can be queued once teardown has started, and that any in-flight recovery
work is fully synchronized before device power-down, preventing MHI
teardown and DMA resource freeing from running more than once.

Note: This issue only affects PCI/MHI-based devices. AHB-based ath11k
devices do not queue reset_work in normal SSR flows.

Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04866.5-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1

Fixes: 13da397f884d ("ath11k: add support for device recovery for QCA6390/WCN6855")
Fixes: 5edbb148bc57 ("wifi: ath11k: Add firmware coredump collection support")
Signed-off-by: Wei Zhang <wei.zhang@oss.qualcomm.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20260404043050.3433754-1-wei.zhang@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath11k/mhi.c
drivers/net/wireless/ath/ath11k/pci.c

index f994233df2bb94e9717b4280130fb2d0dfd414eb..a6c9ff112c68f4fe4e14f44f1f5fb73515719fe4 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause-Clear
 /*
  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 
 #include <linux/msi.h>
@@ -282,8 +282,10 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
                        break;
                }
 
+               spin_lock_bh(&ab->base_lock);
                if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
                        queue_work(ab->workqueue_aux, &ab->reset_work);
+               spin_unlock_bh(&ab->base_lock);
 
                break;
        default:
index 7114eca8810dbfac895eebfefe2e48673d065347..35bb9e7a63a20759a4d5f78b9e3e1a9d17f1889f 100644 (file)
@@ -1210,6 +1210,14 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
 
        ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
+
+       spin_lock_bh(&ab->base_lock);
+       set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
+       spin_unlock_bh(&ab->base_lock);
+
+       cancel_work_sync(&ab->reset_work);
+       cancel_work_sync(&ab->dump_work);
+
        ath11k_pci_power_down(ab, false);
 }