aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d4397eba5408..d1ed4aebbbb7 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
161 dev->bss_generation++; 161 dev->bss_generation++;
162} 162}
163 163
164void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) 164void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
165 bool send_message)
165{ 166{
166 struct cfg80211_scan_request *request; 167 struct cfg80211_scan_request *request;
167 struct wireless_dev *wdev; 168 struct wireless_dev *wdev;
169 struct sk_buff *msg;
168#ifdef CONFIG_CFG80211_WEXT 170#ifdef CONFIG_CFG80211_WEXT
169 union iwreq_data wrqu; 171 union iwreq_data wrqu;
170#endif 172#endif
171 173
172 ASSERT_RTNL(); 174 ASSERT_RTNL();
173 175
174 request = rdev->scan_req; 176 if (rdev->scan_msg) {
177 nl80211_send_scan_result(rdev, rdev->scan_msg);
178 rdev->scan_msg = NULL;
179 return;
180 }
175 181
182 request = rdev->scan_req;
176 if (!request) 183 if (!request)
177 return; 184 return;
178 185
@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
186 if (wdev->netdev) 193 if (wdev->netdev)
187 cfg80211_sme_scan_done(wdev->netdev); 194 cfg80211_sme_scan_done(wdev->netdev);
188 195
189 if (request->aborted) { 196 if (!request->aborted &&
190 nl80211_send_scan_aborted(rdev, wdev); 197 request->flags & NL80211_SCAN_FLAG_FLUSH) {
191 } else { 198 /* flush entries from previous scans */
192 if (request->flags & NL80211_SCAN_FLAG_FLUSH) { 199 spin_lock_bh(&rdev->bss_lock);
193 /* flush entries from previous scans */ 200 __cfg80211_bss_expire(rdev, request->scan_start);
194 spin_lock_bh(&rdev->bss_lock); 201 spin_unlock_bh(&rdev->bss_lock);
195 __cfg80211_bss_expire(rdev, request->scan_start);
196 spin_unlock_bh(&rdev->bss_lock);
197 }
198 nl80211_send_scan_done(rdev, wdev);
199 } 202 }
200 203
204 msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
205
201#ifdef CONFIG_CFG80211_WEXT 206#ifdef CONFIG_CFG80211_WEXT
202 if (wdev->netdev && !request->aborted) { 207 if (wdev->netdev && !request->aborted) {
203 memset(&wrqu, 0, sizeof(wrqu)); 208 memset(&wrqu, 0, sizeof(wrqu));
@@ -210,17 +215,12 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
210 dev_put(wdev->netdev); 215 dev_put(wdev->netdev);
211 216
212 rdev->scan_req = NULL; 217 rdev->scan_req = NULL;
218 kfree(request);
213 219
214 /* 220 if (!send_message)
215 * OK. If this is invoked with "leak" then we can't 221 rdev->scan_msg = msg;
216 * free this ... but we've cleaned it up anyway. The 222 else
217 * driver failed to call the scan_done callback, so 223 nl80211_send_scan_result(rdev, msg);
218 * all bets are off, it might still be trying to use
219 * the scan request or not ... if it accesses the dev
220 * in there (it shouldn't anyway) then it may crash.
221 */
222 if (!leak)
223 kfree(request);
224} 224}
225 225
226void __cfg80211_scan_done(struct work_struct *wk) 226void __cfg80211_scan_done(struct work_struct *wk)
@@ -231,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
231 scan_done_wk); 231 scan_done_wk);
232 232
233 rtnl_lock(); 233 rtnl_lock();
234 ___cfg80211_scan_done(rdev, false); 234 ___cfg80211_scan_done(rdev, true);
235 rtnl_unlock(); 235 rtnl_unlock();
236} 236}
237 237
@@ -1089,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1089 if (IS_ERR(rdev)) 1089 if (IS_ERR(rdev))
1090 return PTR_ERR(rdev); 1090 return PTR_ERR(rdev);
1091 1091
1092 if (rdev->scan_req) { 1092 if (rdev->scan_req || rdev->scan_msg) {
1093 err = -EBUSY; 1093 err = -EBUSY;
1094 goto out; 1094 goto out;
1095 } 1095 }
@@ -1099,11 +1099,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1099 /* Determine number of channels, needed to allocate creq */ 1099 /* Determine number of channels, needed to allocate creq */
1100 if (wreq && wreq->num_channels) 1100 if (wreq && wreq->num_channels)
1101 n_channels = wreq->num_channels; 1101 n_channels = wreq->num_channels;
1102 else { 1102 else
1103 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 1103 n_channels = ieee80211_get_num_supported_channels(wiphy);
1104 if (wiphy->bands[band])
1105 n_channels += wiphy->bands[band]->n_channels;
1106 }
1107 1104
1108 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + 1105 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
1109 n_channels * sizeof(void *), 1106 n_channels * sizeof(void *),
@@ -1494,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
1494 if (IS_ERR(rdev)) 1491 if (IS_ERR(rdev))
1495 return PTR_ERR(rdev); 1492 return PTR_ERR(rdev);
1496 1493
1497 if (rdev->scan_req) 1494 if (rdev->scan_req || rdev->scan_msg)
1498 return -EAGAIN; 1495 return -EAGAIN;
1499 1496
1500 res = ieee80211_scan_results(rdev, info, extra, data->length); 1497 res = ieee80211_scan_results(rdev, info, extra, data->length);