2023-07-18 02:51:42

by Wen Gong

[permalink] [raw]
Subject: [PATCH] wifi: ath12k: avoid deadlock by change ieee80211_queue_work for regd_update_work

Deadlock is easily happened while shutdown wlan interface such as run
"ifconfig wlan0 down".

The reason is because when ar->regd_update_work is ran, it will
call wiphy_lock(ar->hw->wiphy) in function ath12k_regd_update() which
is running in workqueue of ieee80211_local queued by ieee80211_queue_work().
Another thread from "ifconfig wlan0 down" will also accuqire the lock
by wiphy_lock(sdata->local->hw.wiphy) in function ieee80211_stop(), and
then it call ieee80211_stop_device() to flush_workqueue(local->workqueue),
this will wait the workqueue of ieee80211_local finished. Then deadlock
will happen easily if the two thread run meanwhile.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4

Signed-off-by: Wen Gong <[email protected]>
---
drivers/net/wireless/ath/ath12k/wmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 7ae0bb78b2b5..ea6de84bf5cd 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -5213,7 +5213,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
- ieee80211_queue_work(ar->hw, &ar->regd_update_work);
+ queue_work(ab->workqueue, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we

base-commit: 0a00db612b6df1fad80485e3642529d1f28ea084
--
2.40.1



2023-08-03 09:42:38

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH] wifi: ath12k: avoid deadlock by change ieee80211_queue_work for regd_update_work

Wen Gong <[email protected]> wrote:

> Deadlock is easily happened while shutdown wlan interface such as run
> "ifconfig wlan0 down".
>
> The reason is because when ar->regd_update_work is ran, it will
> call wiphy_lock(ar->hw->wiphy) in function ath12k_regd_update() which
> is running in workqueue of ieee80211_local queued by ieee80211_queue_work().
> Another thread from "ifconfig wlan0 down" will also accuqire the lock
> by wiphy_lock(sdata->local->hw.wiphy) in function ieee80211_stop(), and
> then it call ieee80211_stop_device() to flush_workqueue(local->workqueue),
> this will wait the workqueue of ieee80211_local finished. Then deadlock
> will happen easily if the two thread run meanwhile.
>
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
>
> Signed-off-by: Wen Gong <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>

Patch applied to ath-next branch of ath.git, thanks.

8198950ccb7d wifi: ath12k: avoid deadlock by change ieee80211_queue_work for regd_update_work

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches