aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.c4
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c29
-rw-r--r--net/wireless/nl80211.h8
-rw-r--r--net/wireless/scan.c40
-rw-r--r--net/wireless/sme.c2
6 files changed, 45 insertions, 42 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 02ed00dbf2df..010892b81a06 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -206,7 +206,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
206 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 206 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
207 if (WARN_ON(!rdev->scan_req->notified)) 207 if (WARN_ON(!rdev->scan_req->notified))
208 rdev->scan_req->aborted = true; 208 rdev->scan_req->aborted = true;
209 ___cfg80211_scan_done(rdev); 209 ___cfg80211_scan_done(rdev, false);
210 } 210 }
211} 211}
212 212
@@ -862,7 +862,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
862 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 862 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
863 if (WARN_ON(!rdev->scan_req->notified)) 863 if (WARN_ON(!rdev->scan_req->notified))
864 rdev->scan_req->aborted = true; 864 rdev->scan_req->aborted = true;
865 ___cfg80211_scan_done(rdev); 865 ___cfg80211_scan_done(rdev, false);
866 } 866 }
867 867
868 if (WARN_ON(rdev->sched_scan_req && 868 if (WARN_ON(rdev->sched_scan_req &&
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37ec16d7bb1a..f1d193b557b6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
62 struct rb_root bss_tree; 62 struct rb_root bss_tree;
63 u32 bss_generation; 63 u32 bss_generation;
64 struct cfg80211_scan_request *scan_req; /* protected by RTNL */ 64 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
65 struct sk_buff *scan_msg;
65 struct cfg80211_sched_scan_request *sched_scan_req; 66 struct cfg80211_sched_scan_request *sched_scan_req;
66 unsigned long suspend_at; 67 unsigned long suspend_at;
67 struct work_struct scan_done_wk; 68 struct work_struct scan_done_wk;
@@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
361 struct key_params *params, int key_idx, 362 struct key_params *params, int key_idx,
362 bool pairwise, const u8 *mac_addr); 363 bool pairwise, const u8 *mac_addr);
363void __cfg80211_scan_done(struct work_struct *wk); 364void __cfg80211_scan_done(struct work_struct *wk);
364void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); 365void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
366 bool send_message);
365void __cfg80211_sched_scan_results(struct work_struct *wk); 367void __cfg80211_sched_scan_results(struct work_struct *wk);
366int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, 368int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
367 bool driver_initiated); 369 bool driver_initiated);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6ea960b1a8eb..4fe2e6e2bc76 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5245,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5245 if (!rdev->ops->scan) 5245 if (!rdev->ops->scan)
5246 return -EOPNOTSUPP; 5246 return -EOPNOTSUPP;
5247 5247
5248 if (rdev->scan_req) { 5248 if (rdev->scan_req || rdev->scan_msg) {
5249 err = -EBUSY; 5249 err = -EBUSY;
5250 goto unlock; 5250 goto unlock;
5251 } 5251 }
@@ -10012,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
10012 NL80211_MCGRP_SCAN, GFP_KERNEL); 10012 NL80211_MCGRP_SCAN, GFP_KERNEL);
10013} 10013}
10014 10014
10015void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, 10015struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
10016 struct wireless_dev *wdev) 10016 struct wireless_dev *wdev, bool aborted)
10017{ 10017{
10018 struct sk_buff *msg; 10018 struct sk_buff *msg;
10019 10019
10020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 10020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10021 if (!msg) 10021 if (!msg)
10022 return; 10022 return NULL;
10023 10023
10024 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, 10024 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
10025 NL80211_CMD_NEW_SCAN_RESULTS) < 0) { 10025 aborted ? NL80211_CMD_SCAN_ABORTED :
10026 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
10026 nlmsg_free(msg); 10027 nlmsg_free(msg);
10027 return; 10028 return NULL;
10028 } 10029 }
10029 10030
10030 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10031 return msg;
10031 NL80211_MCGRP_SCAN, GFP_KERNEL);
10032} 10032}
10033 10033
10034void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, 10034void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
10035 struct wireless_dev *wdev) 10035 struct sk_buff *msg)
10036{ 10036{
10037 struct sk_buff *msg;
10038
10039 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10040 if (!msg) 10037 if (!msg)
10041 return; 10038 return;
10042 10039
10043 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
10044 NL80211_CMD_SCAN_ABORTED) < 0) {
10045 nlmsg_free(msg);
10046 return;
10047 }
10048
10049 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10040 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
10050 NL80211_MCGRP_SCAN, GFP_KERNEL); 10041 NL80211_MCGRP_SCAN, GFP_KERNEL);
10051} 10042}
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index b1b231324e10..75799746d845 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -8,10 +8,10 @@ void nl80211_exit(void);
8void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); 8void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
9void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, 9void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
10 struct wireless_dev *wdev); 10 struct wireless_dev *wdev);
11void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, 11struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
12 struct wireless_dev *wdev); 12 struct wireless_dev *wdev, bool aborted);
13void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, 13void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *wdev); 14 struct sk_buff *msg);
15void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, 15void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
16 struct net_device *netdev, u32 cmd); 16 struct net_device *netdev, u32 cmd);
17void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, 17void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index b528e31da2cf..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) 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)
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));
@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
211 216
212 rdev->scan_req = NULL; 217 rdev->scan_req = NULL;
213 kfree(request); 218 kfree(request);
219
220 if (!send_message)
221 rdev->scan_msg = msg;
222 else
223 nl80211_send_scan_result(rdev, msg);
214} 224}
215 225
216void __cfg80211_scan_done(struct work_struct *wk) 226void __cfg80211_scan_done(struct work_struct *wk)
@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
221 scan_done_wk); 231 scan_done_wk);
222 232
223 rtnl_lock(); 233 rtnl_lock();
224 ___cfg80211_scan_done(rdev); 234 ___cfg80211_scan_done(rdev, true);
225 rtnl_unlock(); 235 rtnl_unlock();
226} 236}
227 237
@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1079 if (IS_ERR(rdev)) 1089 if (IS_ERR(rdev))
1080 return PTR_ERR(rdev); 1090 return PTR_ERR(rdev);
1081 1091
1082 if (rdev->scan_req) { 1092 if (rdev->scan_req || rdev->scan_msg) {
1083 err = -EBUSY; 1093 err = -EBUSY;
1084 goto out; 1094 goto out;
1085 } 1095 }
@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
1481 if (IS_ERR(rdev)) 1491 if (IS_ERR(rdev))
1482 return PTR_ERR(rdev); 1492 return PTR_ERR(rdev);
1483 1493
1484 if (rdev->scan_req) 1494 if (rdev->scan_req || rdev->scan_msg)
1485 return -EAGAIN; 1495 return -EAGAIN;
1486 1496
1487 res = ieee80211_scan_results(rdev, info, extra, data->length); 1497 res = ieee80211_scan_results(rdev, info, extra, data->length);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a63509118508..f04d4c32e96e 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
67 ASSERT_RDEV_LOCK(rdev); 67 ASSERT_RDEV_LOCK(rdev);
68 ASSERT_WDEV_LOCK(wdev); 68 ASSERT_WDEV_LOCK(wdev);
69 69
70 if (rdev->scan_req) 70 if (rdev->scan_req || rdev->scan_msg)
71 return -EBUSY; 71 return -EBUSY;
72 72
73 if (wdev->conn->params.channel) 73 if (wdev->conn->params.channel)