aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-25 10:33:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-28 14:40:45 -0400
commit15db0b7fd872b0312033666d3a82e1214a227ec0 (patch)
tree0c853f69292d085fac68e0cf5098b484fde9d13c /net/mac80211
parent6bd5f5208fac04d00325b458355e4a4abda76595 (diff)
mac80211: fix scan cancel on ifdown
When an interface is taken down while a scan is pending -- i.e. a scan request was accepted but not yet acted upon due to other work being in progress -- we currently do not properly cancel that scan and end up getting stuck. Fix this by doing better checks when an interface is taken down. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/iface.c26
-rw-r--r--net/mac80211/scan.c9
2 files changed, 8 insertions, 27 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d134bd79972f..f6005adcbf90 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -497,30 +497,8 @@ static int ieee80211_stop(struct net_device *dev)
497 } 497 }
498 /* fall through */ 498 /* fall through */
499 default: 499 default:
500 if (local->scan_sdata == sdata) { 500 if (local->scan_sdata == sdata)
501 if (!local->ops->hw_scan) 501 ieee80211_scan_cancel(local);
502 cancel_delayed_work_sync(&local->scan_work);
503 /*
504 * The software scan can no longer run now, so we can
505 * clear out the scan_sdata reference. However, the
506 * hardware scan may still be running. The complete
507 * function must be prepared to handle a NULL value.
508 */
509 local->scan_sdata = NULL;
510 /*
511 * The memory barrier guarantees that another CPU
512 * that is hardware-scanning will now see the fact
513 * that this interface is gone.
514 */
515 smp_mb();
516 /*
517 * If software scanning, complete the scan but since
518 * the scan_sdata is NULL already don't send out a
519 * scan event to userspace -- the scan is incomplete.
520 */
521 if (test_bit(SCAN_SW_SCANNING, &local->scanning))
522 ieee80211_scan_completed(&local->hw, true);
523 }
524 502
525 /* 503 /*
526 * Disable beaconing for AP and mesh, IBSS can't 504 * Disable beaconing for AP and mesh, IBSS can't
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 1e04be6b9129..039901109fa1 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -280,6 +280,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
280 if (local->scan_req != local->int_scan_req) 280 if (local->scan_req != local->int_scan_req)
281 cfg80211_scan_done(local->scan_req, aborted); 281 cfg80211_scan_done(local->scan_req, aborted);
282 local->scan_req = NULL; 282 local->scan_req = NULL;
283 local->scan_sdata = NULL;
283 284
284 was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); 285 was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
285 local->scanning = 0; 286 local->scanning = 0;
@@ -660,6 +661,7 @@ void ieee80211_scan_work(struct work_struct *work)
660 int rc; 661 int rc;
661 662
662 local->scan_req = NULL; 663 local->scan_req = NULL;
664 local->scan_sdata = NULL;
663 665
664 rc = __ieee80211_start_scan(sdata, req); 666 rc = __ieee80211_start_scan(sdata, req);
665 mutex_unlock(&local->scan_mtx); 667 mutex_unlock(&local->scan_mtx);
@@ -742,7 +744,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
742 744
743void ieee80211_scan_cancel(struct ieee80211_local *local) 745void ieee80211_scan_cancel(struct ieee80211_local *local)
744{ 746{
745 bool swscan; 747 bool abortscan;
746 748
747 cancel_delayed_work_sync(&local->scan_work); 749 cancel_delayed_work_sync(&local->scan_work);
748 750
@@ -751,9 +753,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
751 * queued -- mostly at suspend under RTNL. 753 * queued -- mostly at suspend under RTNL.
752 */ 754 */
753 mutex_lock(&local->scan_mtx); 755 mutex_lock(&local->scan_mtx);
754 swscan = test_bit(SCAN_SW_SCANNING, &local->scanning); 756 abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
757 (!local->scanning && local->scan_req);
755 mutex_unlock(&local->scan_mtx); 758 mutex_unlock(&local->scan_mtx);
756 759
757 if (swscan) 760 if (abortscan)
758 ieee80211_scan_completed(&local->hw, true); 761 ieee80211_scan_completed(&local->hw, true);
759} 762}