From 590bfd7f0a634b99fe3e3c4ff9634768d34dae7c Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 8 Apr 2026 15:00:45 +0530 Subject: [PATCH] wifi: ath12k: fix context switch in panic notifier issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call Stack: Voluntary context switch within RCU read-side critical section! WARNING: kernel/rcu/tree_plugin.h:332 at rcu_note_context_switch+0x4c4/0x508, CPU#1: bash/817 CPU: 1 UID: 0 PID: 817 Comm: bash Tainted: G W 7.0.0-rc3 #1 PREEMPT Tainted: [W]=WARN Hardware name: Qualcomm Technologies, Inc. Hamoa IoT EVK (DT) pstate: 614000c5 (nZCv daIF +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : rcu_note_context_switch+0x4c4/0x508 lr : rcu_note_context_switch+0x4c4/0x508 sp : ffff800085eeb7f0 x29: ffff800085eeb7f0 x28: ffff0008044fd640 x27: 0000000000000000 x26: 0000000000000000 x25: ffffd83dbc89c100 x24: ffff00081e668000 x23: 0000000000000000 x22: ffff0008044fd640 x21: ffffd83dbd9a6760 x20: 0000000000000000 x19: ffff008f386a2040 x18: 0000000000003fb8 x17: 2020202020202020 x16: ffffd83dbb6147b0 x15: 00000000000006a7 x14: 0000000000000001 x13: 00000000000006a6 x12: 00000000fffff6a5 x11: ffffd83dbd3b2a90 x10: ffffd83dbd414a88 x9 : ffffd83dbd3b2b10 x8 : ffffd83dbd40ab10 x7 : 0000000000003f70 x6 : 00000000000006a5 x5 : ffff008f3868d448 x4 : 80000000fffff6a5 x3 : ffff28517be05000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0008044fd640 Call trace: rcu_note_context_switch+0x4c4/0x508 (P) __schedule+0xbc/0x1204 schedule+0x34/0x110 schedule_timeout+0x84/0x11c __mhi_device_get_sync+0x164/0x228 [mhi] mhi_device_get_sync+0x1c/0x3c [mhi] ath12k_wifi7_pci_bus_wake_up+0x20/0x2c [ath12k_wifi7] ath12k_pci_read32+0x58/0x350 [ath12k] ath12k_pci_clear_dbg_registers+0x28/0xb8 [ath12k] ath12k_pci_panic_handler+0x20/0x44 [ath12k] ath12k_core_panic_handler+0x28/0x3c [ath12k] notifier_call_chain+0x78/0x1c0 atomic_notifier_call_chain+0x3c/0x5c In ath12k_pci_panic_handler() many reset related registers need to be read/written. Since Q6 can be in a power‑saving mode (M1/M2), the common PCI read/write APIs in ath12k explicitly wake up Q6 and wait until it reaches the M0 state before issuing the read/write. The wait may result in a context switch. Panic handler is in a atomic RCU read process, we need to avoid context switch in this process. Add a flag to avoid waking up Q6 in panic handler process. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Yingying Tang --- drivers/net/wireless/ath/ath12k/core.c | 2 ++ drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/pci.c | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 4ed608ba3c304..e86dcc6ddbb86 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1770,6 +1770,8 @@ static int ath12k_core_panic_handler(struct notifier_block *nb, struct ath12k_base *ab = container_of(nb, struct ath12k_base, panic_nb); + set_bit(ATH12K_FLAG_PANIC_PROCESSING, &ab->dev_flags); + return ath12k_hif_panic_handler(ab); } diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 990934ec92fca..490c8a20028fa 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -279,6 +279,7 @@ enum ath12k_dev_flags { ATH12K_FLAG_QMI_FW_READY_COMPLETE, ATH12K_FLAG_FTM_SEGMENTED, ATH12K_FLAG_FIXED_MEM_REGION, + ATH12K_FLAG_PANIC_PROCESSING, }; struct ath12k_tx_conf { diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 375277ca2b892..9efc9396c90b7 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1157,7 +1157,8 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset) * need to wakeup MHI to access. */ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && - offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup) + offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup && + !test_bit(ATH12K_FLAG_PANIC_PROCESSING, &ab->dev_flags)) ret = ab_pci->pci_ops->wakeup(ab); if (offset < WINDOW_START) { @@ -1205,7 +1206,8 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value) * need to wakeup MHI to access. */ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && - offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup) + offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup && + !test_bit(ATH12K_FLAG_PANIC_PROCESSING, &ab->dev_flags)) ret = ab_pci->pci_ops->wakeup(ab); if (offset < WINDOW_START) {