wifi: ath12k: fix node corruption in ar->arvifs list

[ Upstream commit 823435bd23108d6f8be89ea2d025c0e2e3769c51 ]

In current WLAN recovery code flow, ath12k_core_halt() only reinitializes
the "arvifs" list head. This will cause the list node immediately following
the list head to become an invalid list node. Because the prev of that node
still points to the list head "arvifs", but the next of the list head
"arvifs" no longer points to that list node.

When a WLAN recovery occurs during the execution of a vif removal, and it
happens before the spin_lock_bh(&ar->data_lock) in
ath12k_mac_vdev_delete(), list_del() will detect the previously mentioned
situation, thereby triggering a kernel panic.

The fix is to remove and reinitialize all vif list nodes from the list head
"arvifs" during WLAN halt. The reinitialization is to make the list nodes
valid, ensuring that the list_del() in ath12k_mac_vdev_delete() can execute
normally.

Call trace:
__list_del_entry_valid_or_report+0xd4/0x100 (P)
ath12k_mac_remove_link_interface.isra.0+0xf8/0x2e4 [ath12k]
ath12k_scan_vdev_clean_work+0x40/0x164 [ath12k]
cfg80211_wiphy_work+0xfc/0x100
process_one_work+0x164/0x2d0
worker_thread+0x254/0x380
kthread+0xfc/0x100
ret_from_fork+0x10/0x20

The change is mostly copied from the ath11k patch:
https://lore.kernel.org/all/20250320053145.3445187-1-quic_stonez@quicinc.com/

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Fixes: d889913205 ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250416021724.2162519-1-maharaja.kennadyrajan@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Maharaja Kennadyrajan
2025-04-16 07:47:24 +05:30
committed by Greg Kroah-Hartman
parent c9c9107ffa
commit be049199de

View File

@@ -657,6 +657,7 @@ err_hal_srng_deinit:
void ath12k_core_halt(struct ath12k *ar) void ath12k_core_halt(struct ath12k *ar)
{ {
struct list_head *pos, *n;
struct ath12k_base *ab = ar->ab; struct ath12k_base *ab = ar->ab;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
@@ -671,7 +672,12 @@ void ath12k_core_halt(struct ath12k *ar)
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
synchronize_rcu(); synchronize_rcu();
INIT_LIST_HEAD(&ar->arvifs);
spin_lock_bh(&ar->data_lock);
list_for_each_safe(pos, n, &ar->arvifs)
list_del_init(pos);
spin_unlock_bh(&ar->data_lock);
idr_init(&ar->txmgmt_idr); idr_init(&ar->txmgmt_idr);
} }