aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c27
-rw-r--r--net/mac80211/driver-ops.h29
-rw-r--r--net/mac80211/driver-trace.h88
-rw-r--r--net/mac80211/ieee80211_i.h9
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/rx.c6
-rw-r--r--net/mac80211/scan.c99
7 files changed, 242 insertions, 22 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c416cce5e1ed..a2ff47493e0a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1362,6 +1362,31 @@ static int ieee80211_scan(struct wiphy *wiphy,
1362 return ieee80211_request_scan(sdata, req); 1362 return ieee80211_request_scan(sdata, req);
1363} 1363}
1364 1364
1365static int
1366ieee80211_sched_scan_start(struct wiphy *wiphy,
1367 struct net_device *dev,
1368 struct cfg80211_sched_scan_request *req)
1369{
1370 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1371
1372 if (!sdata->local->ops->sched_scan_start)
1373 return -EOPNOTSUPP;
1374
1375 return ieee80211_request_sched_scan_start(sdata, req);
1376}
1377
1378static int
1379ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev,
1380 bool driver_initiated)
1381{
1382 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1383
1384 if (!sdata->local->ops->sched_scan_stop)
1385 return -EOPNOTSUPP;
1386
1387 return ieee80211_request_sched_scan_stop(sdata, driver_initiated);
1388}
1389
1365static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, 1390static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
1366 struct cfg80211_auth_request *req) 1391 struct cfg80211_auth_request *req)
1367{ 1392{
@@ -2103,6 +2128,8 @@ struct cfg80211_ops mac80211_config_ops = {
2103 .suspend = ieee80211_suspend, 2128 .suspend = ieee80211_suspend,
2104 .resume = ieee80211_resume, 2129 .resume = ieee80211_resume,
2105 .scan = ieee80211_scan, 2130 .scan = ieee80211_scan,
2131 .sched_scan_start = ieee80211_sched_scan_start,
2132 .sched_scan_stop = ieee80211_sched_scan_stop,
2106 .auth = ieee80211_auth, 2133 .auth = ieee80211_auth,
2107 .assoc = ieee80211_assoc, 2134 .assoc = ieee80211_assoc,
2108 .deauth = ieee80211_deauth, 2135 .deauth = ieee80211_deauth,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index aa16bd8ef789..eebf7a67daf7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -212,12 +212,39 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
212 212
213 might_sleep(); 213 might_sleep();
214 214
215 trace_drv_hw_scan(local, sdata, req); 215 trace_drv_hw_scan(local, sdata);
216 ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); 216 ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
217 trace_drv_return_int(local, ret); 217 trace_drv_return_int(local, ret);
218 return ret; 218 return ret;
219} 219}
220 220
221static inline int
222drv_sched_scan_start(struct ieee80211_local *local,
223 struct ieee80211_sub_if_data *sdata,
224 struct cfg80211_sched_scan_request *req,
225 struct ieee80211_sched_scan_ies *ies)
226{
227 int ret;
228
229 might_sleep();
230
231 trace_drv_sched_scan_start(local, sdata);
232 ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
233 req, ies);
234 trace_drv_return_int(local, ret);
235 return ret;
236}
237
238static inline void drv_sched_scan_stop(struct ieee80211_local *local,
239 struct ieee80211_sub_if_data *sdata)
240{
241 might_sleep();
242
243 trace_drv_sched_scan_stop(local, sdata);
244 local->ops->sched_scan_stop(&local->hw, &sdata->vif);
245 trace_drv_return_void(local);
246}
247
221static inline void drv_sw_scan_start(struct ieee80211_local *local) 248static inline void drv_sw_scan_start(struct ieee80211_local *local)
222{ 249{
223 might_sleep(); 250 might_sleep();
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index dd9779d41d2b..ed9edcbd9aa5 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -98,6 +98,27 @@ DECLARE_EVENT_CLASS(local_u32_evt,
98 ) 98 )
99); 99);
100 100
101DECLARE_EVENT_CLASS(local_sdata_evt,
102 TP_PROTO(struct ieee80211_local *local,
103 struct ieee80211_sub_if_data *sdata),
104 TP_ARGS(local, sdata),
105
106 TP_STRUCT__entry(
107 LOCAL_ENTRY
108 VIF_ENTRY
109 ),
110
111 TP_fast_assign(
112 LOCAL_ASSIGN;
113 VIF_ASSIGN;
114 ),
115
116 TP_printk(
117 LOCAL_PR_FMT VIF_PR_FMT,
118 LOCAL_PR_ARG, VIF_PR_ARG
119 )
120);
121
101DEFINE_EVENT(local_only_evt, drv_return_void, 122DEFINE_EVENT(local_only_evt, drv_return_void,
102 TP_PROTO(struct ieee80211_local *local), 123 TP_PROTO(struct ieee80211_local *local),
103 TP_ARGS(local) 124 TP_ARGS(local)
@@ -433,27 +454,22 @@ TRACE_EVENT(drv_update_tkip_key,
433 ) 454 )
434); 455);
435 456
436TRACE_EVENT(drv_hw_scan, 457DEFINE_EVENT(local_sdata_evt, drv_hw_scan,
437 TP_PROTO(struct ieee80211_local *local, 458 TP_PROTO(struct ieee80211_local *local,
438 struct ieee80211_sub_if_data *sdata, 459 struct ieee80211_sub_if_data *sdata),
439 struct cfg80211_scan_request *req), 460 TP_ARGS(local, sdata)
440 461);
441 TP_ARGS(local, sdata, req),
442
443 TP_STRUCT__entry(
444 LOCAL_ENTRY
445 VIF_ENTRY
446 ),
447 462
448 TP_fast_assign( 463DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
449 LOCAL_ASSIGN; 464 TP_PROTO(struct ieee80211_local *local,
450 VIF_ASSIGN; 465 struct ieee80211_sub_if_data *sdata),
451 ), 466 TP_ARGS(local, sdata)
467);
452 468
453 TP_printk( 469DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop,
454 LOCAL_PR_FMT VIF_PR_FMT, 470 TP_PROTO(struct ieee80211_local *local,
455 LOCAL_PR_ARG,VIF_PR_ARG 471 struct ieee80211_sub_if_data *sdata),
456 ) 472 TP_ARGS(local, sdata)
457); 473);
458 474
459DEFINE_EVENT(local_only_evt, drv_sw_scan_start, 475DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
@@ -1180,6 +1196,42 @@ TRACE_EVENT(api_scan_completed,
1180 ) 1196 )
1181); 1197);
1182 1198
1199TRACE_EVENT(api_sched_scan_results,
1200 TP_PROTO(struct ieee80211_local *local),
1201
1202 TP_ARGS(local),
1203
1204 TP_STRUCT__entry(
1205 LOCAL_ENTRY
1206 ),
1207
1208 TP_fast_assign(
1209 LOCAL_ASSIGN;
1210 ),
1211
1212 TP_printk(
1213 LOCAL_PR_FMT, LOCAL_PR_ARG
1214 )
1215);
1216
1217TRACE_EVENT(api_sched_scan_stopped,
1218 TP_PROTO(struct ieee80211_local *local),
1219
1220 TP_ARGS(local),
1221
1222 TP_STRUCT__entry(
1223 LOCAL_ENTRY
1224 ),
1225
1226 TP_fast_assign(
1227 LOCAL_ASSIGN;
1228 ),
1229
1230 TP_printk(
1231 LOCAL_PR_FMT, LOCAL_PR_ARG
1232 )
1233);
1234
1183TRACE_EVENT(api_sta_block_awake, 1235TRACE_EVENT(api_sta_block_awake,
1184 TP_PROTO(struct ieee80211_local *local, 1236 TP_PROTO(struct ieee80211_local *local,
1185 struct ieee80211_sta *sta, bool block), 1237 struct ieee80211_sta *sta, bool block),
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7f4d0dc1d534..6f55a789c099 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -847,6 +847,9 @@ struct ieee80211_local {
847 int scan_channel_idx; 847 int scan_channel_idx;
848 int scan_ies_len; 848 int scan_ies_len;
849 849
850 bool sched_scanning;
851 struct ieee80211_sched_scan_ies sched_scan_ies;
852
850 unsigned long leave_oper_channel_time; 853 unsigned long leave_oper_channel_time;
851 enum mac80211_scan_state next_scan_state; 854 enum mac80211_scan_state next_scan_state;
852 struct delayed_work scan_work; 855 struct delayed_work scan_work;
@@ -1154,6 +1157,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
1154void ieee80211_rx_bss_put(struct ieee80211_local *local, 1157void ieee80211_rx_bss_put(struct ieee80211_local *local,
1155 struct ieee80211_bss *bss); 1158 struct ieee80211_bss *bss);
1156 1159
1160/* scheduled scan handling */
1161int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1162 struct cfg80211_sched_scan_request *req);
1163int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
1164 bool driver_initiated);
1165
1157/* off-channel helpers */ 1166/* off-channel helpers */
1158bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); 1167bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
1159void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, 1168void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ab1f464817af..30e6a682a047 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work)
358 flush_workqueue(local->workqueue); 358 flush_workqueue(local->workqueue);
359 359
360 mutex_lock(&local->mtx); 360 mutex_lock(&local->mtx);
361 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), 361 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
362 local->sched_scanning,
362 "%s called with hardware scan in progress\n", __func__); 363 "%s called with hardware scan in progress\n", __func__);
363 mutex_unlock(&local->mtx); 364 mutex_unlock(&local->mtx);
364 365
@@ -833,6 +834,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
833 if (!local->ops->remain_on_channel) 834 if (!local->ops->remain_on_channel)
834 local->hw.wiphy->max_remain_on_channel_duration = 5000; 835 local->hw.wiphy->max_remain_on_channel_duration = 5000;
835 836
837 if (local->ops->sched_scan_start)
838 local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
839
836 result = wiphy_register(local->hw.wiphy); 840 result = wiphy_register(local->hw.wiphy);
837 if (result < 0) 841 if (result < 0)
838 goto fail_wiphy_register; 842 goto fail_wiphy_register;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 634f3d97a279..1b9413fb3839 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -404,11 +404,13 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
404 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); 404 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
405 struct sk_buff *skb = rx->skb; 405 struct sk_buff *skb = rx->skb;
406 406
407 if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) 407 if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
408 !local->sched_scanning))
408 return RX_CONTINUE; 409 return RX_CONTINUE;
409 410
410 if (test_bit(SCAN_HW_SCANNING, &local->scanning) || 411 if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
411 test_bit(SCAN_SW_SCANNING, &local->scanning)) 412 test_bit(SCAN_SW_SCANNING, &local->scanning) ||
413 local->sched_scanning)
412 return ieee80211_scan_rx(rx->sdata, skb); 414 return ieee80211_scan_rx(rx->sdata, skb);
413 415
414 /* scanning finished during invoking of handlers */ 416 /* scanning finished during invoking of handlers */
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
855int 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
897out_free:
898 while (i > 0)
899 kfree(local->sched_scan_ies.ie[--i]);
900out:
901 mutex_unlock(&sdata->local->mtx);
902 return ret;
903}
904
905int 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
927out:
928 mutex_unlock(&sdata->local->mtx);
929
930 return ret;
931}
932
933void 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}
941EXPORT_SYMBOL(ieee80211_sched_scan_results);
942
943void 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}
951EXPORT_SYMBOL(ieee80211_sched_scan_stopped);