Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Johannes Berg <johannes.berg@intel.com>

+26 -11
+26 -11
net/mac80211/util.c
··· 1641 1641 drv_stop(local); 1642 1642 } 1643 1643 1644 + static void ieee80211_flush_completed_scan(struct ieee80211_local *local, 1645 + bool aborted) 1646 + { 1647 + /* It's possible that we don't handle the scan completion in 1648 + * time during suspend, so if it's still marked as completed 1649 + * here, queue the work and flush it to clean things up. 1650 + * Instead of calling the worker function directly here, we 1651 + * really queue it to avoid potential races with other flows 1652 + * scheduling the same work. 1653 + */ 1654 + if (test_bit(SCAN_COMPLETED, &local->scanning)) { 1655 + /* If coming from reconfiguration failure, abort the scan so 1656 + * we don't attempt to continue a partial HW scan - which is 1657 + * possible otherwise if (e.g.) the 2.4 GHz portion was the 1658 + * completed scan, and a 5 GHz portion is still pending. 1659 + */ 1660 + if (aborted) 1661 + set_bit(SCAN_ABORTED, &local->scanning); 1662 + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); 1663 + flush_delayed_work(&local->scan_work); 1664 + } 1665 + } 1666 + 1644 1667 static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) 1645 1668 { 1646 1669 struct ieee80211_sub_if_data *sdata; ··· 1682 1659 local->resuming = false; 1683 1660 local->suspended = false; 1684 1661 local->in_reconfig = false; 1662 + 1663 + ieee80211_flush_completed_scan(local, true); 1685 1664 1686 1665 /* scheduled scan clearly can't be running any more, but tell 1687 1666 * cfg80211 and clear local state ··· 2099 2074 mb(); 2100 2075 local->resuming = false; 2101 2076 2102 - /* It's possible that we don't handle the scan completion in 2103 - * time during suspend, so if it's still marked as completed 2104 - * here, queue the work and flush it to clean things up. 2105 - * Instead of calling the worker function directly here, we 2106 - * really queue it to avoid potential races with other flows 2107 - * scheduling the same work. 2108 - */ 2109 - if (test_bit(SCAN_COMPLETED, &local->scanning)) { 2110 - ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); 2111 - flush_delayed_work(&local->scan_work); 2112 - } 2077 + ieee80211_flush_completed_scan(local, false); 2113 2078 2114 2079 if (local->open_count && !reconfig_due_to_wowlan) 2115 2080 drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);