cfg80211: add support for flushing old scan results
Add an NL80211_SCAN_FLAG_FLUSH flag that causes old bss cache entries to be flushed on scan completion. This is useful for collecting guaranteed fresh scan/survey result (e.g. on resume). For normal scan, flushing only happens on successful completion of a scan; i.e. it does not happen if the scan is aborted. For scheduled scan, previous scan results are flushed everytime when we get new scan results. This feature is enabled by default. Drivers can disable it by unsetting the NL80211_FEATURE_SCAN_FLUSH flag. Signed-off-by: Sam Leffler <sleffler@chromium.org> Tested-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> [invert polarity of feature flag to account for old kernels] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
b292219fa5
commit
15d6030b4b
@ -47,6 +47,27 @@ static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
|
||||
kref_put(&bss->ref, bss_release);
|
||||
}
|
||||
|
||||
/* must hold dev->bss_lock! */
|
||||
static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
|
||||
unsigned long expire_time)
|
||||
{
|
||||
struct cfg80211_internal_bss *bss, *tmp;
|
||||
bool expired = false;
|
||||
|
||||
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
|
||||
if (atomic_read(&bss->hold))
|
||||
continue;
|
||||
if (!time_after(expire_time, bss->ts))
|
||||
continue;
|
||||
|
||||
__cfg80211_unlink_bss(dev, bss);
|
||||
expired = true;
|
||||
}
|
||||
|
||||
if (expired)
|
||||
dev->bss_generation++;
|
||||
}
|
||||
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||
{
|
||||
struct cfg80211_scan_request *request;
|
||||
@ -72,10 +93,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||
if (wdev->netdev)
|
||||
cfg80211_sme_scan_done(wdev->netdev);
|
||||
|
||||
if (request->aborted)
|
||||
if (request->aborted) {
|
||||
nl80211_send_scan_aborted(rdev, wdev);
|
||||
else
|
||||
} else {
|
||||
if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
|
||||
/* flush entries from previous scans */
|
||||
spin_lock_bh(&rdev->bss_lock);
|
||||
__cfg80211_bss_expire(rdev, request->scan_start);
|
||||
spin_unlock_bh(&rdev->bss_lock);
|
||||
}
|
||||
nl80211_send_scan_done(rdev, wdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (wdev->netdev && !request->aborted) {
|
||||
@ -126,16 +154,27 @@ EXPORT_SYMBOL(cfg80211_scan_done);
|
||||
void __cfg80211_sched_scan_results(struct work_struct *wk)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct cfg80211_sched_scan_request *request;
|
||||
|
||||
rdev = container_of(wk, struct cfg80211_registered_device,
|
||||
sched_scan_results_wk);
|
||||
|
||||
request = rdev->sched_scan_req;
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
|
||||
/* we don't have sched_scan_req anymore if the scan is stopping */
|
||||
if (rdev->sched_scan_req)
|
||||
nl80211_send_sched_scan_results(rdev,
|
||||
rdev->sched_scan_req->dev);
|
||||
if (request) {
|
||||
if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
|
||||
/* flush entries from previous scans */
|
||||
spin_lock_bh(&rdev->bss_lock);
|
||||
__cfg80211_bss_expire(rdev, request->scan_start);
|
||||
spin_unlock_bh(&rdev->bss_lock);
|
||||
request->scan_start =
|
||||
jiffies + msecs_to_jiffies(request->interval);
|
||||
}
|
||||
nl80211_send_sched_scan_results(rdev, request->dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
}
|
||||
@ -197,23 +236,9 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* must hold dev->bss_lock! */
|
||||
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
|
||||
{
|
||||
struct cfg80211_internal_bss *bss, *tmp;
|
||||
bool expired = false;
|
||||
|
||||
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
|
||||
if (atomic_read(&bss->hold))
|
||||
continue;
|
||||
if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
|
||||
continue;
|
||||
__cfg80211_unlink_bss(dev, bss);
|
||||
expired = true;
|
||||
}
|
||||
|
||||
if (expired)
|
||||
dev->bss_generation++;
|
||||
__cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
|
||||
}
|
||||
|
||||
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
|
||||
@ -962,6 +987,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
creq->ssids = (void *)&creq->channels[n_channels];
|
||||
creq->n_channels = n_channels;
|
||||
creq->n_ssids = 1;
|
||||
creq->scan_start = jiffies;
|
||||
|
||||
/* translate "Scan on frequencies" request */
|
||||
i = 0;
|
||||
|
Reference in New Issue
Block a user