aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorSam Leffler <sleffler@chromium.org>2012-10-12 00:03:34 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-18 03:01:52 -0400
commit15d6030b4bec618742b8b9ccae9209c8f9e4a916 (patch)
tree97856b3f62e268880659757a85df59151958044d /net/wireless/scan.c
parentb292219fa5061e2657ecf518b48426913d0ddae6 (diff)
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>
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 20050965abca..a8d5a9a07e49 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -47,6 +47,27 @@ static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
47 kref_put(&bss->ref, bss_release); 47 kref_put(&bss->ref, bss_release);
48} 48}
49 49
50/* must hold dev->bss_lock! */
51static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
52 unsigned long expire_time)
53{
54 struct cfg80211_internal_bss *bss, *tmp;
55 bool expired = false;
56
57 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
58 if (atomic_read(&bss->hold))
59 continue;
60 if (!time_after(expire_time, bss->ts))
61 continue;
62
63 __cfg80211_unlink_bss(dev, bss);
64 expired = true;
65 }
66
67 if (expired)
68 dev->bss_generation++;
69}
70
50void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) 71void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
51{ 72{
52 struct cfg80211_scan_request *request; 73 struct cfg80211_scan_request *request;
@@ -72,10 +93,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
72 if (wdev->netdev) 93 if (wdev->netdev)
73 cfg80211_sme_scan_done(wdev->netdev); 94 cfg80211_sme_scan_done(wdev->netdev);
74 95
75 if (request->aborted) 96 if (request->aborted) {
76 nl80211_send_scan_aborted(rdev, wdev); 97 nl80211_send_scan_aborted(rdev, wdev);
77 else 98 } else {
99 if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
100 /* flush entries from previous scans */
101 spin_lock_bh(&rdev->bss_lock);
102 __cfg80211_bss_expire(rdev, request->scan_start);
103 spin_unlock_bh(&rdev->bss_lock);
104 }
78 nl80211_send_scan_done(rdev, wdev); 105 nl80211_send_scan_done(rdev, wdev);
106 }
79 107
80#ifdef CONFIG_CFG80211_WEXT 108#ifdef CONFIG_CFG80211_WEXT
81 if (wdev->netdev && !request->aborted) { 109 if (wdev->netdev && !request->aborted) {
@@ -126,16 +154,27 @@ EXPORT_SYMBOL(cfg80211_scan_done);
126void __cfg80211_sched_scan_results(struct work_struct *wk) 154void __cfg80211_sched_scan_results(struct work_struct *wk)
127{ 155{
128 struct cfg80211_registered_device *rdev; 156 struct cfg80211_registered_device *rdev;
157 struct cfg80211_sched_scan_request *request;
129 158
130 rdev = container_of(wk, struct cfg80211_registered_device, 159 rdev = container_of(wk, struct cfg80211_registered_device,
131 sched_scan_results_wk); 160 sched_scan_results_wk);
132 161
162 request = rdev->sched_scan_req;
163
133 mutex_lock(&rdev->sched_scan_mtx); 164 mutex_lock(&rdev->sched_scan_mtx);
134 165
135 /* we don't have sched_scan_req anymore if the scan is stopping */ 166 /* we don't have sched_scan_req anymore if the scan is stopping */
136 if (rdev->sched_scan_req) 167 if (request) {
137 nl80211_send_sched_scan_results(rdev, 168 if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
138 rdev->sched_scan_req->dev); 169 /* flush entries from previous scans */
170 spin_lock_bh(&rdev->bss_lock);
171 __cfg80211_bss_expire(rdev, request->scan_start);
172 spin_unlock_bh(&rdev->bss_lock);
173 request->scan_start =
174 jiffies + msecs_to_jiffies(request->interval);
175 }
176 nl80211_send_sched_scan_results(rdev, request->dev);
177 }
139 178
140 mutex_unlock(&rdev->sched_scan_mtx); 179 mutex_unlock(&rdev->sched_scan_mtx);
141} 180}
@@ -197,23 +236,9 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
197 } 236 }
198} 237}
199 238
200/* must hold dev->bss_lock! */
201void cfg80211_bss_expire(struct cfg80211_registered_device *dev) 239void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
202{ 240{
203 struct cfg80211_internal_bss *bss, *tmp; 241 __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
204 bool expired = false;
205
206 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
207 if (atomic_read(&bss->hold))
208 continue;
209 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
210 continue;
211 __cfg80211_unlink_bss(dev, bss);
212 expired = true;
213 }
214
215 if (expired)
216 dev->bss_generation++;
217} 242}
218 243
219const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) 244const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
@@ -962,6 +987,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
962 creq->ssids = (void *)&creq->channels[n_channels]; 987 creq->ssids = (void *)&creq->channels[n_channels];
963 creq->n_channels = n_channels; 988 creq->n_channels = n_channels;
964 creq->n_ssids = 1; 989 creq->n_ssids = 1;
990 creq->scan_start = jiffies;
965 991
966 /* translate "Scan on frequencies" request */ 992 /* translate "Scan on frequencies" request */
967 i = 0; 993 i = 0;