Commit 74430f94 authored by Johannes Berg's avatar Johannes Berg

mac80211: run scan completed work on reconfig failure

When reconfiguration during resume fails while a scan is pending
for completion work, that work will never run, and the scan will
be stuck forever. Factor out the code to recover this and call it
also in ieee80211_handle_reconfig_failure().
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 707554b4
...@@ -1641,6 +1641,29 @@ void ieee80211_stop_device(struct ieee80211_local *local) ...@@ -1641,6 +1641,29 @@ void ieee80211_stop_device(struct ieee80211_local *local)
drv_stop(local); drv_stop(local);
} }
static void ieee80211_flush_completed_scan(struct ieee80211_local *local,
bool aborted)
{
/* 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)) {
/* If coming from reconfiguration failure, abort the scan so
* we don't attempt to continue a partial HW scan - which is
* possible otherwise if (e.g.) the 2.4 GHz portion was the
* completed scan, and a 5 GHz portion is still pending.
*/
if (aborted)
set_bit(SCAN_ABORTED, &local->scanning);
ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
flush_delayed_work(&local->scan_work);
}
}
static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
...@@ -1660,6 +1683,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) ...@@ -1660,6 +1683,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
local->suspended = false; local->suspended = false;
local->in_reconfig = false; local->in_reconfig = false;
ieee80211_flush_completed_scan(local, true);
/* scheduled scan clearly can't be running any more, but tell /* scheduled scan clearly can't be running any more, but tell
* cfg80211 and clear local state * cfg80211 and clear local state
*/ */
...@@ -2074,17 +2099,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -2074,17 +2099,7 @@ 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 ieee80211_flush_completed_scan(local, false);
* 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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment