Commit 8198950c authored by Wen Gong's avatar Wen Gong Committed by Kalle Valo

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: default avatarWen Gong <quic_wgong@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230718024724.29120-1-quic_wgong@quicinc.com
parent 9632ea57
...@@ -5473,7 +5473,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk ...@@ -5473,7 +5473,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
ar = ab->pdevs[pdev_idx].ar; ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]); kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd; ab->new_regd[pdev_idx] = regd;
ieee80211_queue_work(ar->hw, &ar->regd_update_work); queue_work(ab->workqueue, &ar->regd_update_work);
} else { } else {
/* Multiple events for the same *ar is not expected. But we /* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we * can still clear any previously stored default_regd if we
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment