Commit 6eab0ba9 authored by Yan-Hsuan Chuang's avatar Yan-Hsuan Chuang Committed by Kalle Valo

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: default avatarYan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 398b9bda
...@@ -1904,6 +1904,9 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) ...@@ -1904,6 +1904,9 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
lockdep_assert_held(&rtwdev->mutex); lockdep_assert_held(&rtwdev->mutex);
if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
return;
coex_dm->reason = reason; coex_dm->reason = reason;
/* update wifi_link_info_ext variable */ /* update wifi_link_info_ext variable */
......
...@@ -136,6 +136,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) ...@@ -136,6 +136,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
mutex_lock(&rtwdev->mutex); mutex_lock(&rtwdev->mutex);
if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
goto unlock;
switch (c2h->id) { switch (c2h->id) {
case C2H_BT_INFO: case C2H_BT_INFO:
rtw_coex_bt_info_notify(rtwdev, c2h->payload, len); rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
...@@ -153,6 +156,7 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) ...@@ -153,6 +156,7 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
break; break;
} }
unlock:
mutex_unlock(&rtwdev->mutex); mutex_unlock(&rtwdev->mutex);
} }
......
...@@ -909,11 +909,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev) ...@@ -909,11 +909,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev)
clear_bit(RTW_FLAG_RUNNING, rtwdev->flags); clear_bit(RTW_FLAG_RUNNING, rtwdev->flags);
clear_bit(RTW_FLAG_FW_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(&rtwdev->watch_dog_work);
cancel_delayed_work_sync(&coex->bt_relink_work); cancel_delayed_work_sync(&coex->bt_relink_work);
cancel_delayed_work_sync(&coex->bt_reenable_work); cancel_delayed_work_sync(&coex->bt_reenable_work);
cancel_delayed_work_sync(&coex->defreeze_work); cancel_delayed_work_sync(&coex->defreeze_work);
mutex_lock(&rtwdev->mutex);
rtw_power_off(rtwdev); rtw_power_off(rtwdev);
} }
......
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