mac80211: correctly close cancelled scans
__ieee80211_scan_completed is called from a worker. This means that the following flow is possible. * driver calls ieee80211_scan_completed * mac80211 cancels the scan (that is already complete) * __ieee80211_scan_completed runs When scan_work will finally run, it will see that the scan hasn't been aborted and might even trigger another scan on another band. This leads to a situation where cfg80211's scan is not done and no further scan can be issued. Fix this by setting a new flag when a HW scan is being cancelled so that no other scan will be triggered. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
22c4ceed01
commit
a754055a12
|
@ -893,6 +893,8 @@ struct tpt_led_trigger {
|
|||
* that the scan completed.
|
||||
* @SCAN_ABORTED: Set for our scan work function when the driver reported
|
||||
* a scan complete for an aborted scan.
|
||||
* @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being
|
||||
* cancelled.
|
||||
*/
|
||||
enum {
|
||||
SCAN_SW_SCANNING,
|
||||
|
@ -900,6 +902,7 @@ enum {
|
|||
SCAN_ONCHANNEL_SCANNING,
|
||||
SCAN_COMPLETED,
|
||||
SCAN_ABORTED,
|
||||
SCAN_HW_CANCELLED,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -238,6 +238,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
|
|||
enum ieee80211_band band;
|
||||
int i, ielen, n_chans;
|
||||
|
||||
if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
|
||||
return false;
|
||||
|
||||
do {
|
||||
if (local->hw_scan_band == IEEE80211_NUM_BANDS)
|
||||
return false;
|
||||
|
@ -940,7 +943,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
|
|||
if (!local->scan_req)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We have a scan running and the driver already reported completion,
|
||||
* but the worker hasn't run yet or is stuck on the mutex - mark it as
|
||||
* cancelled.
|
||||
*/
|
||||
if (test_bit(SCAN_HW_SCANNING, &local->scanning) &&
|
||||
test_bit(SCAN_COMPLETED, &local->scanning)) {
|
||||
set_bit(SCAN_HW_CANCELLED, &local->scanning);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
|
||||
/*
|
||||
* Make sure that __ieee80211_scan_completed doesn't trigger a
|
||||
* scan on another band.
|
||||
*/
|
||||
set_bit(SCAN_HW_CANCELLED, &local->scanning);
|
||||
if (local->ops->cancel_hw_scan)
|
||||
drv_cancel_hw_scan(local,
|
||||
rcu_dereference_protected(local->scan_sdata,
|
||||
|
|
Loading…
Reference in New Issue