aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-02-07 13:44:14 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-07 13:44:14 -0500
commit0f96b860bc5e97d4776d0cb375c7ca1f4864f9e9 (patch)
treeef46bd077c1710a0474b5b3b31c543783197a274 /net
parentee262ad827f89e2dc7851ec2986953b5b125c6bc (diff)
parent348f7d4adee97f222e3ad9ff97956ca3793d11c6 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c44
-rw-r--r--net/mac80211/ht.c4
-rw-r--r--net/mac80211/ibss.c5
-rw-r--r--net/mac80211/iface.c27
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/wireless/core.c17
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c32
-rw-r--r--net/wireless/nl80211.h8
-rw-r--r--net/wireless/scan.c40
-rw-r--r--net/wireless/sme.c2
11 files changed, 102 insertions, 83 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f9ae9b85d4c1..453e974287d1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
1021 IEEE80211_P2P_OPPPS_ENABLE_BIT; 1021 IEEE80211_P2P_OPPPS_ENABLE_BIT;
1022 1022
1023 err = ieee80211_assign_beacon(sdata, &params->beacon); 1023 err = ieee80211_assign_beacon(sdata, &params->beacon);
1024 if (err < 0) 1024 if (err < 0) {
1025 ieee80211_vif_release_channel(sdata);
1025 return err; 1026 return err;
1027 }
1026 changed |= err; 1028 changed |= err;
1027 1029
1028 err = drv_start_ap(sdata->local, sdata); 1030 err = drv_start_ap(sdata->local, sdata);
@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
1032 if (old) 1034 if (old)
1033 kfree_rcu(old, rcu_head); 1035 kfree_rcu(old, rcu_head);
1034 RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); 1036 RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
1037 ieee80211_vif_release_channel(sdata);
1035 return err; 1038 return err;
1036 } 1039 }
1037 1040
@@ -1090,8 +1093,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1090 kfree(sdata->u.ap.next_beacon); 1093 kfree(sdata->u.ap.next_beacon);
1091 sdata->u.ap.next_beacon = NULL; 1094 sdata->u.ap.next_beacon = NULL;
1092 1095
1093 cancel_work_sync(&sdata->u.ap.request_smps_work);
1094
1095 /* turn off carrier for this interface and dependent VLANs */ 1096 /* turn off carrier for this interface and dependent VLANs */
1096 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) 1097 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
1097 netif_carrier_off(vlan->dev); 1098 netif_carrier_off(vlan->dev);
@@ -1103,6 +1104,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1103 kfree_rcu(old_beacon, rcu_head); 1104 kfree_rcu(old_beacon, rcu_head);
1104 if (old_probe_resp) 1105 if (old_probe_resp)
1105 kfree_rcu(old_probe_resp, rcu_head); 1106 kfree_rcu(old_probe_resp, rcu_head);
1107 sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
1106 1108
1107 __sta_info_flush(sdata, true); 1109 __sta_info_flush(sdata, true);
1108 ieee80211_free_keys(sdata, true); 1110 ieee80211_free_keys(sdata, true);
@@ -2638,6 +2640,24 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
2638 INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); 2640 INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
2639 INIT_LIST_HEAD(&roc->dependents); 2641 INIT_LIST_HEAD(&roc->dependents);
2640 2642
2643 /*
2644 * cookie is either the roc cookie (for normal roc)
2645 * or the SKB (for mgmt TX)
2646 */
2647 if (!txskb) {
2648 /* local->mtx protects this */
2649 local->roc_cookie_counter++;
2650 roc->cookie = local->roc_cookie_counter;
2651 /* wow, you wrapped 64 bits ... more likely a bug */
2652 if (WARN_ON(roc->cookie == 0)) {
2653 roc->cookie = 1;
2654 local->roc_cookie_counter++;
2655 }
2656 *cookie = roc->cookie;
2657 } else {
2658 *cookie = (unsigned long)txskb;
2659 }
2660
2641 /* if there's one pending or we're scanning, queue this one */ 2661 /* if there's one pending or we're scanning, queue this one */
2642 if (!list_empty(&local->roc_list) || 2662 if (!list_empty(&local->roc_list) ||
2643 local->scanning || local->radar_detect_enabled) 2663 local->scanning || local->radar_detect_enabled)
@@ -2772,24 +2792,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
2772 if (!queued) 2792 if (!queued)
2773 list_add_tail(&roc->list, &local->roc_list); 2793 list_add_tail(&roc->list, &local->roc_list);
2774 2794
2775 /*
2776 * cookie is either the roc cookie (for normal roc)
2777 * or the SKB (for mgmt TX)
2778 */
2779 if (!txskb) {
2780 /* local->mtx protects this */
2781 local->roc_cookie_counter++;
2782 roc->cookie = local->roc_cookie_counter;
2783 /* wow, you wrapped 64 bits ... more likely a bug */
2784 if (WARN_ON(roc->cookie == 0)) {
2785 roc->cookie = 1;
2786 local->roc_cookie_counter++;
2787 }
2788 *cookie = roc->cookie;
2789 } else {
2790 *cookie = (unsigned long)txskb;
2791 }
2792
2793 return 0; 2795 return 0;
2794} 2796}
2795 2797
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index fab7b91923e0..70dd013de836 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(struct work_struct *work)
466 u.ap.request_smps_work); 466 u.ap.request_smps_work);
467 467
468 sdata_lock(sdata); 468 sdata_lock(sdata);
469 __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); 469 if (sdata_dereference(sdata->u.ap.beacon, sdata))
470 __ieee80211_request_smps_ap(sdata,
471 sdata->u.ap.driver_smps_mode);
470 sdata_unlock(sdata); 472 sdata_unlock(sdata);
471} 473}
472 474
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 771080ec7212..2796a198728f 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -695,12 +695,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
695 struct cfg80211_bss *cbss; 695 struct cfg80211_bss *cbss;
696 struct beacon_data *presp; 696 struct beacon_data *presp;
697 struct sta_info *sta; 697 struct sta_info *sta;
698 int active_ibss;
699 u16 capability; 698 u16 capability;
700 699
701 active_ibss = ieee80211_sta_active_ibss(sdata); 700 if (!is_zero_ether_addr(ifibss->bssid)) {
702
703 if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
704 capability = WLAN_CAPABILITY_IBSS; 701 capability = WLAN_CAPABILITY_IBSS;
705 702
706 if (ifibss->privacy) 703 if (ifibss->privacy)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 3dfd20a453ab..d6d1f1df9119 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -418,20 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
418 return ret; 418 return ret;
419 } 419 }
420 420
421 mutex_lock(&local->iflist_mtx);
422 rcu_assign_pointer(local->monitor_sdata, sdata);
423 mutex_unlock(&local->iflist_mtx);
424
421 mutex_lock(&local->mtx); 425 mutex_lock(&local->mtx);
422 ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, 426 ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
423 IEEE80211_CHANCTX_EXCLUSIVE); 427 IEEE80211_CHANCTX_EXCLUSIVE);
424 mutex_unlock(&local->mtx); 428 mutex_unlock(&local->mtx);
425 if (ret) { 429 if (ret) {
430 mutex_lock(&local->iflist_mtx);
431 rcu_assign_pointer(local->monitor_sdata, NULL);
432 mutex_unlock(&local->iflist_mtx);
433 synchronize_net();
426 drv_remove_interface(local, sdata); 434 drv_remove_interface(local, sdata);
427 kfree(sdata); 435 kfree(sdata);
428 return ret; 436 return ret;
429 } 437 }
430 438
431 mutex_lock(&local->iflist_mtx);
432 rcu_assign_pointer(local->monitor_sdata, sdata);
433 mutex_unlock(&local->iflist_mtx);
434
435 return 0; 439 return 0;
436} 440}
437 441
@@ -770,12 +774,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
770 774
771 ieee80211_roc_purge(local, sdata); 775 ieee80211_roc_purge(local, sdata);
772 776
773 if (sdata->vif.type == NL80211_IFTYPE_STATION) 777 switch (sdata->vif.type) {
778 case NL80211_IFTYPE_STATION:
774 ieee80211_mgd_stop(sdata); 779 ieee80211_mgd_stop(sdata);
775 780 break;
776 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 781 case NL80211_IFTYPE_ADHOC:
777 ieee80211_ibss_stop(sdata); 782 ieee80211_ibss_stop(sdata);
778 783 break;
784 case NL80211_IFTYPE_AP:
785 cancel_work_sync(&sdata->u.ap.request_smps_work);
786 break;
787 default:
788 break;
789 }
779 790
780 /* 791 /*
781 * Remove all stations associated with this interface. 792 * Remove all stations associated with this interface.
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 27c990bf2320..97a02d3f7d87 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -878,7 +878,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
878 } 878 }
879 879
880 /* adjust first fragment's length */ 880 /* adjust first fragment's length */
881 skb->len = hdrlen + per_fragm; 881 skb_trim(skb, hdrlen + per_fragm);
882 return 0; 882 return 0;
883} 883}
884 884
diff --git a/net/wireless/core.c b/net/wireless/core.c
index d89dee2259b5..010892b81a06 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
203 203
204 rdev->opencount--; 204 rdev->opencount--;
205 205
206 WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && 206 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
207 !rdev->scan_req->notified); 207 if (WARN_ON(!rdev->scan_req->notified))
208 rdev->scan_req->aborted = true;
209 ___cfg80211_scan_done(rdev, false);
210 }
208} 211}
209 212
210static int cfg80211_rfkill_set_block(void *data, bool blocked) 213static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -440,9 +443,6 @@ int wiphy_register(struct wiphy *wiphy)
440 int i; 443 int i;
441 u16 ifmodes = wiphy->interface_modes; 444 u16 ifmodes = wiphy->interface_modes;
442 445
443 /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
444 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
445
446 /* 446 /*
447 * There are major locking problems in nl80211/mac80211 for CSA, 447 * There are major locking problems in nl80211/mac80211 for CSA,
448 * disable for all drivers until this has been reworked. 448 * disable for all drivers until this has been reworked.
@@ -859,8 +859,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
859 break; 859 break;
860 case NETDEV_DOWN: 860 case NETDEV_DOWN:
861 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 861 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
862 WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && 862 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
863 !rdev->scan_req->notified); 863 if (WARN_ON(!rdev->scan_req->notified))
864 rdev->scan_req->aborted = true;
865 ___cfg80211_scan_done(rdev, false);
866 }
864 867
865 if (WARN_ON(rdev->sched_scan_req && 868 if (WARN_ON(rdev->sched_scan_req &&
866 rdev->sched_scan_req->dev == wdev->netdev)) { 869 rdev->sched_scan_req->dev == wdev->netdev)) {
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 7a742594916e..4fe2e6e2bc76 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1719,9 +1719,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1719 * We can then retry with the larger buffer. 1719 * We can then retry with the larger buffer.
1720 */ 1720 */
1721 if ((ret == -ENOBUFS || ret == -EMSGSIZE) && 1721 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
1722 !skb->len && 1722 !skb->len && !state->split &&
1723 cb->min_dump_alloc < 4096) { 1723 cb->min_dump_alloc < 4096) {
1724 cb->min_dump_alloc = 4096; 1724 cb->min_dump_alloc = 4096;
1725 state->split_start = 0;
1725 rtnl_unlock(); 1726 rtnl_unlock();
1726 return 1; 1727 return 1;
1727 } 1728 }
@@ -5244,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5244 if (!rdev->ops->scan) 5245 if (!rdev->ops->scan)
5245 return -EOPNOTSUPP; 5246 return -EOPNOTSUPP;
5246 5247
5247 if (rdev->scan_req) { 5248 if (rdev->scan_req || rdev->scan_msg) {
5248 err = -EBUSY; 5249 err = -EBUSY;
5249 goto unlock; 5250 goto unlock;
5250 } 5251 }
@@ -10011,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
10011 NL80211_MCGRP_SCAN, GFP_KERNEL); 10012 NL80211_MCGRP_SCAN, GFP_KERNEL);
10012} 10013}
10013 10014
10014void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, 10015struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
10015 struct wireless_dev *wdev) 10016 struct wireless_dev *wdev, bool aborted)
10016{ 10017{
10017 struct sk_buff *msg; 10018 struct sk_buff *msg;
10018 10019
10019 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 10020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10020 if (!msg) 10021 if (!msg)
10021 return; 10022 return NULL;
10022 10023
10023 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, 10024 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
10024 NL80211_CMD_NEW_SCAN_RESULTS) < 0) { 10025 aborted ? NL80211_CMD_SCAN_ABORTED :
10026 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
10025 nlmsg_free(msg); 10027 nlmsg_free(msg);
10026 return; 10028 return NULL;
10027 } 10029 }
10028 10030
10029 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10031 return msg;
10030 NL80211_MCGRP_SCAN, GFP_KERNEL);
10031} 10032}
10032 10033
10033void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, 10034void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
10034 struct wireless_dev *wdev) 10035 struct sk_buff *msg)
10035{ 10036{
10036 struct sk_buff *msg;
10037
10038 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10039 if (!msg) 10037 if (!msg)
10040 return; 10038 return;
10041 10039
10042 if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
10043 NL80211_CMD_SCAN_ABORTED) < 0) {
10044 nlmsg_free(msg);
10045 return;
10046 }
10047
10048 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10040 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
10049 NL80211_MCGRP_SCAN, GFP_KERNEL); 10041 NL80211_MCGRP_SCAN, GFP_KERNEL);
10050} 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)