diff options
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r-- | net/mac80211/scan.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8acce724f0dc..ea44a8e941ec 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | 17 | #include <linux/pm_qos_params.h> |
18 | #include <linux/slab.h> | ||
18 | #include <net/sch_generic.h> | 19 | #include <net/sch_generic.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <net/mac80211.h> | 21 | #include <net/mac80211.h> |
@@ -850,3 +851,101 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
850 | } | 851 | } |
851 | mutex_unlock(&local->mtx); | 852 | mutex_unlock(&local->mtx); |
852 | } | 853 | } |
854 | |||
855 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | ||
856 | struct cfg80211_sched_scan_request *req) | ||
857 | { | ||
858 | struct ieee80211_local *local = sdata->local; | ||
859 | int ret, i; | ||
860 | |||
861 | mutex_lock(&sdata->local->mtx); | ||
862 | |||
863 | if (local->sched_scanning) { | ||
864 | ret = -EBUSY; | ||
865 | goto out; | ||
866 | } | ||
867 | |||
868 | if (!local->ops->sched_scan_start) { | ||
869 | ret = -ENOTSUPP; | ||
870 | goto out; | ||
871 | } | ||
872 | |||
873 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
874 | local->sched_scan_ies.ie[i] = kzalloc(2 + | ||
875 | IEEE80211_MAX_SSID_LEN + | ||
876 | local->scan_ies_len, | ||
877 | GFP_KERNEL); | ||
878 | if (!local->sched_scan_ies.ie[i]) { | ||
879 | ret = -ENOMEM; | ||
880 | goto out_free; | ||
881 | } | ||
882 | |||
883 | local->sched_scan_ies.len[i] = | ||
884 | ieee80211_build_preq_ies(local, | ||
885 | local->sched_scan_ies.ie[i], | ||
886 | req->ie, req->ie_len, i, | ||
887 | (u32) -1, 0); | ||
888 | } | ||
889 | |||
890 | ret = drv_sched_scan_start(local, sdata, req, | ||
891 | &local->sched_scan_ies); | ||
892 | if (ret == 0) { | ||
893 | local->sched_scanning = true; | ||
894 | goto out; | ||
895 | } | ||
896 | |||
897 | out_free: | ||
898 | while (i > 0) | ||
899 | kfree(local->sched_scan_ies.ie[--i]); | ||
900 | out: | ||
901 | mutex_unlock(&sdata->local->mtx); | ||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, | ||
906 | bool driver_initiated) | ||
907 | { | ||
908 | struct ieee80211_local *local = sdata->local; | ||
909 | int ret = 0, i; | ||
910 | |||
911 | mutex_lock(&sdata->local->mtx); | ||
912 | |||
913 | if (!local->ops->sched_scan_stop) { | ||
914 | ret = -ENOTSUPP; | ||
915 | goto out; | ||
916 | } | ||
917 | |||
918 | if (local->sched_scanning) { | ||
919 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
920 | kfree(local->sched_scan_ies.ie[i]); | ||
921 | |||
922 | if (!driver_initiated) | ||
923 | drv_sched_scan_stop(local, sdata); | ||
924 | local->sched_scanning = false; | ||
925 | } | ||
926 | |||
927 | out: | ||
928 | mutex_unlock(&sdata->local->mtx); | ||
929 | |||
930 | return ret; | ||
931 | } | ||
932 | |||
933 | void ieee80211_sched_scan_results(struct ieee80211_hw *hw) | ||
934 | { | ||
935 | struct ieee80211_local *local = hw_to_local(hw); | ||
936 | |||
937 | trace_api_sched_scan_results(local); | ||
938 | |||
939 | cfg80211_sched_scan_results(hw->wiphy); | ||
940 | } | ||
941 | EXPORT_SYMBOL(ieee80211_sched_scan_results); | ||
942 | |||
943 | void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) | ||
944 | { | ||
945 | struct ieee80211_local *local = hw_to_local(hw); | ||
946 | |||
947 | trace_api_sched_scan_stopped(local); | ||
948 | |||
949 | cfg80211_sched_scan_stopped(hw->wiphy); | ||
950 | } | ||
951 | EXPORT_SYMBOL(ieee80211_sched_scan_stopped); | ||