diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-02-07 13:44:14 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-07 13:44:14 -0500 |
commit | 0f96b860bc5e97d4776d0cb375c7ca1f4864f9e9 (patch) | |
tree | ef46bd077c1710a0474b5b3b31c543783197a274 /net | |
parent | ee262ad827f89e2dc7851ec2986953b5b125c6bc (diff) | |
parent | 348f7d4adee97f222e3ad9ff97956ca3793d11c6 (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.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 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, ¶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 | ||
@@ -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 | ||
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 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); |
363 | void __cfg80211_scan_done(struct work_struct *wk); | 364 | void __cfg80211_scan_done(struct work_struct *wk); |
364 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); | 365 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
366 | bool send_message); | ||
365 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 367 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
366 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 368 | int __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 | ||
10014 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 10015 | struct 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 | ||
10033 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 10034 | void 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); | |||
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) |