提交 9120d94e 编写于 作者: L Luciano Coelho 提交者: Johannes Berg

mac80211: handle potential race between suspend and scan completion

If suspend starts while ieee80211_scan_completed() is running, between
the point where SCAN_COMPLETED is set and the work is queued,
ieee80211_scan_cancel() will not catch the work and we may finish
suspending before the work is actually executed, leaving the scan
running while suspended.

To fix this race, queue the scan work during resume if the
SCAN_COMPLETED flag is set and flush it immediately.
Signed-off-by: NLuciano Coelho <luciano.coelho@intel.com>
Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
上级 225b8189
...@@ -1752,7 +1752,8 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) ...@@ -1752,7 +1752,8 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) &&
!test_bit(SCAN_COMPLETED, &local->scanning),
"%s: resume with hardware scan still in progress\n", "%s: resume with hardware scan still in progress\n",
wiphy_name(hw->wiphy)); wiphy_name(hw->wiphy));
......
...@@ -2060,6 +2060,18 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -2060,6 +2060,18 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mb(); mb();
local->resuming = false; local->resuming = false;
/* It's possible that we don't handle the scan completion in
* time during suspend, so if it's still marked as completed
* here, queue the work and flush it to clean things up.
* Instead of calling the worker function directly here, we
* really queue it to avoid potential races with other flows
* scheduling the same work.
*/
if (test_bit(SCAN_COMPLETED, &local->scanning)) {
ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
flush_delayed_work(&local->scan_work);
}
if (local->open_count && !reconfig_due_to_wowlan) if (local->open_count && !reconfig_due_to_wowlan)
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册