summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw88/main.c
diff options
context:
space:
mode:
authorYan-Hsuan Chuang <yhchuang@realtek.com>2020-02-05 08:08:56 +0100
committerKalle Valo <kvalo@codeaurora.org>2020-02-12 17:18:28 +0100
commit6eab0ba99bc2c8659ee310bbc614374ebf769ff1 (patch)
treed4b81ce5f77c738c8b5acf026395c40d53e1d6c0 /drivers/net/wireless/realtek/rtw88/main.c
parentrtw88: move rtw_enter_ips() to the last when config (diff)
downloadlinux-6eab0ba99bc2c8659ee310bbc614374ebf769ff1.tar.xz
linux-6eab0ba99bc2c8659ee310bbc614374ebf769ff1.zip
rtw88: avoid holding mutex for cancel_delayed_work_sync()
Driver could possibly be dead-locked while canceling works with *_sync() with mutex lock held. Those cancel_delayed_work_sync() functions will wait until the work is done, but if we hold the lock, they will never acquire the lock. To prevent this, simply release the lock and acquire again after the works have been canceled. And to avoid the works being queued again, check if the device is at RTW_FLAG_RUNNING state, otherwise just return and do nothing. Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/main.c')
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 2845d2838f7b..edecc7d7ea56 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -909,11 +909,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev)
clear_bit(RTW_FLAG_RUNNING, rtwdev->flags);
clear_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
+ mutex_unlock(&rtwdev->mutex);
+
+ cancel_work_sync(&rtwdev->c2h_work);
cancel_delayed_work_sync(&rtwdev->watch_dog_work);
cancel_delayed_work_sync(&coex->bt_relink_work);
cancel_delayed_work_sync(&coex->bt_reenable_work);
cancel_delayed_work_sync(&coex->defreeze_work);
+ mutex_lock(&rtwdev->mutex);
+
rtw_power_off(rtwdev);
}