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.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 7e595ce24eeb..0ccf3a07dc02 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -14,29 +14,41 @@
14#include <net/iw_handler.h> 14#include <net/iw_handler.h>
15#include "core.h" 15#include "core.h"
16#include "nl80211.h" 16#include "nl80211.h"
17#include "wext-compat.h"
17 18
18#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) 19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
19 20
20void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 21void __cfg80211_scan_done(struct work_struct *wk)
21{ 22{
23 struct cfg80211_registered_device *rdev;
24 struct cfg80211_scan_request *request;
22 struct net_device *dev; 25 struct net_device *dev;
23#ifdef CONFIG_WIRELESS_EXT 26#ifdef CONFIG_WIRELESS_EXT
24 union iwreq_data wrqu; 27 union iwreq_data wrqu;
25#endif 28#endif
26 29
27 dev = dev_get_by_index(&init_net, request->ifidx); 30 rdev = container_of(wk, struct cfg80211_registered_device,
28 if (!dev) 31 scan_done_wk);
29 goto out;
30 32
31 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 33 mutex_lock(&rdev->mtx);
34 request = rdev->scan_req;
35
36 dev = request->dev;
32 37
33 if (aborted) 38 /*
39 * This must be before sending the other events!
40 * Otherwise, wpa_supplicant gets completely confused with
41 * wext events.
42 */
43 cfg80211_sme_scan_done(dev);
44
45 if (request->aborted)
34 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); 46 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
35 else 47 else
36 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); 48 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
37 49
38#ifdef CONFIG_WIRELESS_EXT 50#ifdef CONFIG_WIRELESS_EXT
39 if (!aborted) { 51 if (!request->aborted) {
40 memset(&wrqu, 0, sizeof(wrqu)); 52 memset(&wrqu, 0, sizeof(wrqu));
41 53
42 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 54 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
@@ -45,10 +57,18 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
45 57
46 dev_put(dev); 58 dev_put(dev);
47 59
48 out: 60 cfg80211_unlock_rdev(rdev);
49 wiphy_to_dev(request->wiphy)->scan_req = NULL; 61 wiphy_to_dev(request->wiphy)->scan_req = NULL;
50 kfree(request); 62 kfree(request);
51} 63}
64
65void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
66{
67 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
68
69 request->aborted = aborted;
70 schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk);
71}
52EXPORT_SYMBOL(cfg80211_scan_done); 72EXPORT_SYMBOL(cfg80211_scan_done);
53 73
54static void bss_release(struct kref *ref) 74static void bss_release(struct kref *ref)
@@ -62,6 +82,8 @@ static void bss_release(struct kref *ref)
62 if (bss->ies_allocated) 82 if (bss->ies_allocated)
63 kfree(bss->pub.information_elements); 83 kfree(bss->pub.information_elements);
64 84
85 BUG_ON(atomic_read(&bss->hold));
86
65 kfree(bss); 87 kfree(bss);
66} 88}
67 89
@@ -84,8 +106,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
84 bool expired = false; 106 bool expired = false;
85 107
86 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { 108 list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
87 if (bss->hold || 109 if (atomic_read(&bss->hold))
88 !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) 110 continue;
111 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
89 continue; 112 continue;
90 list_del(&bss->list); 113 list_del(&bss->list);
91 rb_erase(&bss->rbn, &dev->bss_tree); 114 rb_erase(&bss->rbn, &dev->bss_tree);
@@ -547,30 +570,6 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
547} 570}
548EXPORT_SYMBOL(cfg80211_unlink_bss); 571EXPORT_SYMBOL(cfg80211_unlink_bss);
549 572
550void cfg80211_hold_bss(struct cfg80211_bss *pub)
551{
552 struct cfg80211_internal_bss *bss;
553
554 if (!pub)
555 return;
556
557 bss = container_of(pub, struct cfg80211_internal_bss, pub);
558 bss->hold = true;
559}
560EXPORT_SYMBOL(cfg80211_hold_bss);
561
562void cfg80211_unhold_bss(struct cfg80211_bss *pub)
563{
564 struct cfg80211_internal_bss *bss;
565
566 if (!pub)
567 return;
568
569 bss = container_of(pub, struct cfg80211_internal_bss, pub);
570 bss->hold = false;
571}
572EXPORT_SYMBOL(cfg80211_unhold_bss);
573
574#ifdef CONFIG_WIRELESS_EXT 573#ifdef CONFIG_WIRELESS_EXT
575int cfg80211_wext_siwscan(struct net_device *dev, 574int cfg80211_wext_siwscan(struct net_device *dev,
576 struct iw_request_info *info, 575 struct iw_request_info *info,
@@ -586,7 +585,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
586 if (!netif_running(dev)) 585 if (!netif_running(dev))
587 return -ENETDOWN; 586 return -ENETDOWN;
588 587
589 rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); 588 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
590 589
591 if (IS_ERR(rdev)) 590 if (IS_ERR(rdev))
592 return PTR_ERR(rdev); 591 return PTR_ERR(rdev);
@@ -611,7 +610,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
611 } 610 }
612 611
613 creq->wiphy = wiphy; 612 creq->wiphy = wiphy;
614 creq->ifidx = dev->ifindex; 613 creq->dev = dev;
615 creq->ssids = (void *)(creq + 1); 614 creq->ssids = (void *)(creq + 1);
616 creq->channels = (void *)(creq->ssids + 1); 615 creq->channels = (void *)(creq->ssids + 1);
617 creq->n_channels = n_channels; 616 creq->n_channels = n_channels;
@@ -648,9 +647,12 @@ int cfg80211_wext_siwscan(struct net_device *dev,
648 if (err) { 647 if (err) {
649 rdev->scan_req = NULL; 648 rdev->scan_req = NULL;
650 kfree(creq); 649 kfree(creq);
650 } else {
651 nl80211_send_scan_start(rdev, dev);
652 dev_hold(dev);
651 } 653 }
652 out: 654 out:
653 cfg80211_put_dev(rdev); 655 cfg80211_unlock_rdev(rdev);
654 return err; 656 return err;
655} 657}
656EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); 658EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -941,7 +943,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
941 if (!netif_running(dev)) 943 if (!netif_running(dev))
942 return -ENETDOWN; 944 return -ENETDOWN;
943 945
944 rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); 946 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
945 947
946 if (IS_ERR(rdev)) 948 if (IS_ERR(rdev))
947 return PTR_ERR(rdev); 949 return PTR_ERR(rdev);
@@ -959,7 +961,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
959 } 961 }
960 962
961 out: 963 out:
962 cfg80211_put_dev(rdev); 964 cfg80211_unlock_rdev(rdev);
963 return res; 965 return res;
964} 966}
965EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); 967EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);