diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 44 | ||||
-rw-r--r-- | net/mac80211/ht.c | 4 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 5 | ||||
-rw-r--r-- | net/mac80211/iface.c | 27 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/wireless/core.c | 17 | ||||
-rw-r--r-- | net/wireless/core.h | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 32 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 8 | ||||
-rw-r--r-- | net/wireless/scan.c | 40 | ||||
-rw-r--r-- | net/wireless/sme.c | 2 |
11 files changed, 102 insertions, 83 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6973ccdd230b..363d19b5d5c8 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, ¶ms->beacon); | 1023 | err = ieee80211_assign_beacon(sdata, ¶ms->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 | ||
@@ -1093,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1093 | kfree(sdata->u.ap.next_beacon); | 1096 | kfree(sdata->u.ap.next_beacon); |
1094 | sdata->u.ap.next_beacon = NULL; | 1097 | sdata->u.ap.next_beacon = NULL; |
1095 | 1098 | ||
1096 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
1097 | |||
1098 | /* turn off carrier for this interface and dependent VLANs */ | 1099 | /* turn off carrier for this interface and dependent VLANs */ |
1099 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1100 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
1100 | netif_carrier_off(vlan->dev); | 1101 | netif_carrier_off(vlan->dev); |
@@ -1106,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1106 | kfree_rcu(old_beacon, rcu_head); | 1107 | kfree_rcu(old_beacon, rcu_head); |
1107 | if (old_probe_resp) | 1108 | if (old_probe_resp) |
1108 | kfree_rcu(old_probe_resp, rcu_head); | 1109 | kfree_rcu(old_probe_resp, rcu_head); |
1110 | sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; | ||
1109 | 1111 | ||
1110 | __sta_info_flush(sdata, true); | 1112 | __sta_info_flush(sdata, true); |
1111 | ieee80211_free_keys(sdata, true); | 1113 | ieee80211_free_keys(sdata, true); |
@@ -2665,6 +2667,24 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2665 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2667 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
2666 | INIT_LIST_HEAD(&roc->dependents); | 2668 | INIT_LIST_HEAD(&roc->dependents); |
2667 | 2669 | ||
2670 | /* | ||
2671 | * cookie is either the roc cookie (for normal roc) | ||
2672 | * or the SKB (for mgmt TX) | ||
2673 | */ | ||
2674 | if (!txskb) { | ||
2675 | /* local->mtx protects this */ | ||
2676 | local->roc_cookie_counter++; | ||
2677 | roc->cookie = local->roc_cookie_counter; | ||
2678 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2679 | if (WARN_ON(roc->cookie == 0)) { | ||
2680 | roc->cookie = 1; | ||
2681 | local->roc_cookie_counter++; | ||
2682 | } | ||
2683 | *cookie = roc->cookie; | ||
2684 | } else { | ||
2685 | *cookie = (unsigned long)txskb; | ||
2686 | } | ||
2687 | |||
2668 | /* if there's one pending or we're scanning, queue this one */ | 2688 | /* if there's one pending or we're scanning, queue this one */ |
2669 | if (!list_empty(&local->roc_list) || | 2689 | if (!list_empty(&local->roc_list) || |
2670 | local->scanning || local->radar_detect_enabled) | 2690 | local->scanning || local->radar_detect_enabled) |
@@ -2787,24 +2807,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2787 | if (!queued) | 2807 | if (!queued) |
2788 | list_add_tail(&roc->list, &local->roc_list); | 2808 | list_add_tail(&roc->list, &local->roc_list); |
2789 | 2809 | ||
2790 | /* | ||
2791 | * cookie is either the roc cookie (for normal roc) | ||
2792 | * or the SKB (for mgmt TX) | ||
2793 | */ | ||
2794 | if (!txskb) { | ||
2795 | /* local->mtx protects this */ | ||
2796 | local->roc_cookie_counter++; | ||
2797 | roc->cookie = local->roc_cookie_counter; | ||
2798 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2799 | if (WARN_ON(roc->cookie == 0)) { | ||
2800 | roc->cookie = 1; | ||
2801 | local->roc_cookie_counter++; | ||
2802 | } | ||
2803 | *cookie = roc->cookie; | ||
2804 | } else { | ||
2805 | *cookie = (unsigned long)txskb; | ||
2806 | } | ||
2807 | |||
2808 | return 0; | 2810 | return 0; |
2809 | } | 2811 | } |
2810 | 2812 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index dc3c28002e3e..afbe2b203c3e 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 9c84b75f3de8..4453e2725e40 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -684,12 +684,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) | |||
684 | struct cfg80211_bss *cbss; | 684 | struct cfg80211_bss *cbss; |
685 | struct beacon_data *presp; | 685 | struct beacon_data *presp; |
686 | struct sta_info *sta; | 686 | struct sta_info *sta; |
687 | int active_ibss; | ||
688 | u16 capability; | 687 | u16 capability; |
689 | 688 | ||
690 | active_ibss = ieee80211_sta_active_ibss(sdata); | 689 | if (!is_zero_ether_addr(ifibss->bssid)) { |
691 | |||
692 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
693 | capability = WLAN_CAPABILITY_IBSS; | 690 | capability = WLAN_CAPABILITY_IBSS; |
694 | 691 | ||
695 | if (ifibss->privacy) | 692 | if (ifibss->privacy) |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8880bc8fce0d..96518ad200c4 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 5476a69b45c9..722151fa5dce 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -874,7 +874,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, | |||
874 | } | 874 | } |
875 | 875 | ||
876 | /* adjust first fragment's length */ | 876 | /* adjust first fragment's length */ |
877 | skb->len = hdrlen + per_fragm; | 877 | skb_trim(skb, hdrlen + per_fragm); |
878 | return 0; | 878 | return 0; |
879 | } | 879 | } |
880 | 880 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index b5ff39a6f6ed..76ae6a605abb 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 | ||
210 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 213 | static 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 9895ab16c051..40683004d523 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; |
@@ -363,7 +364,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
363 | struct key_params *params, int key_idx, | 364 | struct key_params *params, int key_idx, |
364 | bool pairwise, const u8 *mac_addr); | 365 | bool pairwise, const u8 *mac_addr); |
365 | void __cfg80211_scan_done(struct work_struct *wk); | 366 | void __cfg80211_scan_done(struct work_struct *wk); |
366 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); | 367 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
368 | bool send_message); | ||
367 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 369 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
368 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 370 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
369 | bool driver_initiated); | 371 | bool driver_initiated); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ebea1a197afb..8e6b6a2d35cb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1740,9 +1740,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1740 | * We can then retry with the larger buffer. | 1740 | * We can then retry with the larger buffer. |
1741 | */ | 1741 | */ |
1742 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | 1742 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && |
1743 | !skb->len && | 1743 | !skb->len && !state->split && |
1744 | cb->min_dump_alloc < 4096) { | 1744 | cb->min_dump_alloc < 4096) { |
1745 | cb->min_dump_alloc = 4096; | 1745 | cb->min_dump_alloc = 4096; |
1746 | state->split_start = 0; | ||
1746 | rtnl_unlock(); | 1747 | rtnl_unlock(); |
1747 | return 1; | 1748 | return 1; |
1748 | } | 1749 | } |
@@ -5274,7 +5275,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5274 | if (!rdev->ops->scan) | 5275 | if (!rdev->ops->scan) |
5275 | return -EOPNOTSUPP; | 5276 | return -EOPNOTSUPP; |
5276 | 5277 | ||
5277 | if (rdev->scan_req) { | 5278 | if (rdev->scan_req || rdev->scan_msg) { |
5278 | err = -EBUSY; | 5279 | err = -EBUSY; |
5279 | goto unlock; | 5280 | goto unlock; |
5280 | } | 5281 | } |
@@ -10116,40 +10117,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | |||
10116 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10117 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
10117 | } | 10118 | } |
10118 | 10119 | ||
10119 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 10120 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
10120 | struct wireless_dev *wdev) | 10121 | struct wireless_dev *wdev, bool aborted) |
10121 | { | 10122 | { |
10122 | struct sk_buff *msg; | 10123 | struct sk_buff *msg; |
10123 | 10124 | ||
10124 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 10125 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
10125 | if (!msg) | 10126 | if (!msg) |
10126 | return; | 10127 | return NULL; |
10127 | 10128 | ||
10128 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 10129 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, |
10129 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | 10130 | aborted ? NL80211_CMD_SCAN_ABORTED : |
10131 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | ||
10130 | nlmsg_free(msg); | 10132 | nlmsg_free(msg); |
10131 | return; | 10133 | return NULL; |
10132 | } | 10134 | } |
10133 | 10135 | ||
10134 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10136 | return msg; |
10135 | NL80211_MCGRP_SCAN, GFP_KERNEL); | ||
10136 | } | 10137 | } |
10137 | 10138 | ||
10138 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 10139 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
10139 | struct wireless_dev *wdev) | 10140 | struct sk_buff *msg) |
10140 | { | 10141 | { |
10141 | struct sk_buff *msg; | ||
10142 | |||
10143 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
10144 | if (!msg) | 10142 | if (!msg) |
10145 | return; | 10143 | return; |
10146 | 10144 | ||
10147 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | ||
10148 | NL80211_CMD_SCAN_ABORTED) < 0) { | ||
10149 | nlmsg_free(msg); | ||
10150 | return; | ||
10151 | } | ||
10152 | |||
10153 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10145 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, |
10154 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10146 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
10155 | } | 10147 | } |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index cb0216e1a004..1e6df9630f42 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -8,10 +8,10 @@ void nl80211_exit(void); | |||
8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); | 8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); |
9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
10 | struct wireless_dev *wdev); | 10 | struct wireless_dev *wdev); |
11 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 11 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
12 | struct wireless_dev *wdev); | 12 | struct wireless_dev *wdev, bool aborted); |
13 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 13 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
14 | struct wireless_dev *wdev); | 14 | struct sk_buff *msg); |
15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | 15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, |
16 | struct net_device *netdev, u32 cmd); | 16 | struct net_device *netdev, u32 cmd); |
17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | 17 | void 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 | ||
164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | 164 | void ___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 | ||
216 | void __cfg80211_scan_done(struct work_struct *wk) | 226 | void __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) |