diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-12 15:21:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-12 15:21:05 -0400 |
commit | d07d152892aadd8dc3209ecef6788dfc83475676 (patch) | |
tree | 0f140aa244ddc2c52494155342298cef64fc8456 /net/mac80211 | |
parent | 2f8684ce7a47c91da7e0ccba2686277c103d02b6 (diff) | |
parent | 685fb72b63faf09a767cc28332545f5830b91be8 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts:
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/mwifiex/cfg80211.c
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 48 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 20 | ||||
-rw-r--r-- | net/mac80211/iface.c | 44 | ||||
-rw-r--r-- | net/mac80211/key.c | 20 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 45 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 6 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 49 | ||||
-rw-r--r-- | net/mac80211/scan.c | 116 | ||||
-rw-r--r-- | net/mac80211/status.c | 9 | ||||
-rw-r--r-- | net/mac80211/trace.h | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 25 | ||||
-rw-r--r-- | net/mac80211/util.c | 11 |
16 files changed, 209 insertions, 206 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5cc1bf7d8033..d0deb3edae21 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -135,7 +135,8 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | |||
135 | bar->control = cpu_to_le16(bar_control); | 135 | bar->control = cpu_to_le16(bar_control); |
136 | bar->start_seq_num = cpu_to_le16(ssn); | 136 | bar->start_seq_num = cpu_to_le16(ssn); |
137 | 137 | ||
138 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 138 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | |
139 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
139 | ieee80211_tx_skb_tid(sdata, skb, tid); | 140 | ieee80211_tx_skb_tid(sdata, skb, tid); |
140 | } | 141 | } |
141 | EXPORT_SYMBOL(ieee80211_send_bar); | 142 | EXPORT_SYMBOL(ieee80211_send_bar); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ccbe2413142a..cfdc03f59e27 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -20,31 +20,31 @@ | |||
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | 22 | ||
23 | static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name, | 23 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name, |
24 | enum nl80211_iftype type, | 24 | enum nl80211_iftype type, |
25 | u32 *flags, | 25 | u32 *flags, |
26 | struct vif_params *params) | 26 | struct vif_params *params) |
27 | { | 27 | { |
28 | struct ieee80211_local *local = wiphy_priv(wiphy); | 28 | struct ieee80211_local *local = wiphy_priv(wiphy); |
29 | struct net_device *dev; | 29 | struct wireless_dev *wdev; |
30 | struct ieee80211_sub_if_data *sdata; | 30 | struct ieee80211_sub_if_data *sdata; |
31 | int err; | 31 | int err; |
32 | 32 | ||
33 | err = ieee80211_if_add(local, name, &dev, type, params); | 33 | err = ieee80211_if_add(local, name, &wdev, type, params); |
34 | if (err) | 34 | if (err) |
35 | return ERR_PTR(err); | 35 | return ERR_PTR(err); |
36 | 36 | ||
37 | if (type == NL80211_IFTYPE_MONITOR && flags) { | 37 | if (type == NL80211_IFTYPE_MONITOR && flags) { |
38 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 38 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
39 | sdata->u.mntr_flags = *flags; | 39 | sdata->u.mntr_flags = *flags; |
40 | } | 40 | } |
41 | 41 | ||
42 | return dev; | 42 | return wdev; |
43 | } | 43 | } |
44 | 44 | ||
45 | static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) | 45 | static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) |
46 | { | 46 | { |
47 | ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev)); | 47 | ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev)); |
48 | 48 | ||
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
@@ -1741,6 +1741,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1741 | return -EINVAL; | 1741 | return -EINVAL; |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); | ||
1745 | |||
1744 | return 0; | 1746 | return 0; |
1745 | } | 1747 | } |
1746 | 1748 | ||
@@ -1761,10 +1763,11 @@ static int ieee80211_resume(struct wiphy *wiphy) | |||
1761 | #endif | 1763 | #endif |
1762 | 1764 | ||
1763 | static int ieee80211_scan(struct wiphy *wiphy, | 1765 | static int ieee80211_scan(struct wiphy *wiphy, |
1764 | struct net_device *dev, | ||
1765 | struct cfg80211_scan_request *req) | 1766 | struct cfg80211_scan_request *req) |
1766 | { | 1767 | { |
1767 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1768 | struct ieee80211_sub_if_data *sdata; |
1769 | |||
1770 | sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev); | ||
1768 | 1771 | ||
1769 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { | 1772 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1770 | case NL80211_IFTYPE_STATION: | 1773 | case NL80211_IFTYPE_STATION: |
@@ -2297,13 +2300,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2297 | } | 2300 | } |
2298 | 2301 | ||
2299 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2302 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
2300 | struct net_device *dev, | 2303 | struct wireless_dev *wdev, |
2301 | struct ieee80211_channel *chan, | 2304 | struct ieee80211_channel *chan, |
2302 | enum nl80211_channel_type channel_type, | 2305 | enum nl80211_channel_type channel_type, |
2303 | unsigned int duration, | 2306 | unsigned int duration, |
2304 | u64 *cookie) | 2307 | u64 *cookie) |
2305 | { | 2308 | { |
2306 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2309 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2307 | struct ieee80211_local *local = sdata->local; | 2310 | struct ieee80211_local *local = sdata->local; |
2308 | int ret; | 2311 | int ret; |
2309 | 2312 | ||
@@ -2390,23 +2393,23 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2390 | } | 2393 | } |
2391 | 2394 | ||
2392 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | 2395 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, |
2393 | struct net_device *dev, | 2396 | struct wireless_dev *wdev, |
2394 | u64 cookie) | 2397 | u64 cookie) |
2395 | { | 2398 | { |
2396 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2399 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2397 | struct ieee80211_local *local = sdata->local; | 2400 | struct ieee80211_local *local = sdata->local; |
2398 | 2401 | ||
2399 | return ieee80211_cancel_roc(local, cookie, false); | 2402 | return ieee80211_cancel_roc(local, cookie, false); |
2400 | } | 2403 | } |
2401 | 2404 | ||
2402 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 2405 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
2403 | struct ieee80211_channel *chan, bool offchan, | 2406 | struct ieee80211_channel *chan, bool offchan, |
2404 | enum nl80211_channel_type channel_type, | 2407 | enum nl80211_channel_type channel_type, |
2405 | bool channel_type_valid, unsigned int wait, | 2408 | bool channel_type_valid, unsigned int wait, |
2406 | const u8 *buf, size_t len, bool no_cck, | 2409 | const u8 *buf, size_t len, bool no_cck, |
2407 | bool dont_wait_for_ack, u64 *cookie) | 2410 | bool dont_wait_for_ack, u64 *cookie) |
2408 | { | 2411 | { |
2409 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2412 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2410 | struct ieee80211_local *local = sdata->local; | 2413 | struct ieee80211_local *local = sdata->local; |
2411 | struct sk_buff *skb; | 2414 | struct sk_buff *skb; |
2412 | struct sta_info *sta; | 2415 | struct sta_info *sta; |
@@ -2511,21 +2514,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2511 | } | 2514 | } |
2512 | 2515 | ||
2513 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | 2516 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, |
2514 | struct net_device *dev, | 2517 | struct wireless_dev *wdev, |
2515 | u64 cookie) | 2518 | u64 cookie) |
2516 | { | 2519 | { |
2517 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2520 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2518 | struct ieee80211_local *local = sdata->local; | ||
2519 | 2521 | ||
2520 | return ieee80211_cancel_roc(local, cookie, true); | 2522 | return ieee80211_cancel_roc(local, cookie, true); |
2521 | } | 2523 | } |
2522 | 2524 | ||
2523 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 2525 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
2524 | struct net_device *dev, | 2526 | struct wireless_dev *wdev, |
2525 | u16 frame_type, bool reg) | 2527 | u16 frame_type, bool reg) |
2526 | { | 2528 | { |
2527 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2529 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2528 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2530 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2529 | 2531 | ||
2530 | switch (frame_type) { | 2532 | switch (frame_type) { |
2531 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: | 2533 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 778e5916d7c3..b8dfb440c8ef 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -325,8 +325,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
325 | local->rx_handlers_drop_defrag); | 325 | local->rx_handlers_drop_defrag); |
326 | DEBUGFS_STATS_ADD(rx_handlers_drop_short, | 326 | DEBUGFS_STATS_ADD(rx_handlers_drop_short, |
327 | local->rx_handlers_drop_short); | 327 | local->rx_handlers_drop_short); |
328 | DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan, | ||
329 | local->rx_handlers_drop_passive_scan); | ||
330 | DEBUGFS_STATS_ADD(tx_expand_skb_head, | 328 | DEBUGFS_STATS_ADD(tx_expand_skb_head, |
331 | local->tx_expand_skb_head); | 329 | local->tx_expand_skb_head); |
332 | DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned, | 330 | DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e0423f8c0ce1..7998513ec831 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -85,6 +85,8 @@ struct ieee80211_bss { | |||
85 | size_t ssid_len; | 85 | size_t ssid_len; |
86 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 86 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
87 | 87 | ||
88 | u32 device_ts; | ||
89 | |||
88 | u8 dtim_period; | 90 | u8 dtim_period; |
89 | 91 | ||
90 | bool wmm_used; | 92 | bool wmm_used; |
@@ -207,7 +209,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
207 | * enum ieee80211_packet_rx_flags - packet RX flags | 209 | * enum ieee80211_packet_rx_flags - packet RX flags |
208 | * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed | 210 | * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed |
209 | * (incl. multicast frames) | 211 | * (incl. multicast frames) |
210 | * @IEEE80211_RX_IN_SCAN: received while scanning | ||
211 | * @IEEE80211_RX_FRAGMENTED: fragmented frame | 212 | * @IEEE80211_RX_FRAGMENTED: fragmented frame |
212 | * @IEEE80211_RX_AMSDU: a-MSDU packet | 213 | * @IEEE80211_RX_AMSDU: a-MSDU packet |
213 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed | 214 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed |
@@ -217,7 +218,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
217 | * @rx_flags field of &struct ieee80211_rx_status. | 218 | * @rx_flags field of &struct ieee80211_rx_status. |
218 | */ | 219 | */ |
219 | enum ieee80211_packet_rx_flags { | 220 | enum ieee80211_packet_rx_flags { |
220 | IEEE80211_RX_IN_SCAN = BIT(0), | ||
221 | IEEE80211_RX_RA_MATCH = BIT(1), | 221 | IEEE80211_RX_RA_MATCH = BIT(1), |
222 | IEEE80211_RX_FRAGMENTED = BIT(2), | 222 | IEEE80211_RX_FRAGMENTED = BIT(2), |
223 | IEEE80211_RX_AMSDU = BIT(3), | 223 | IEEE80211_RX_AMSDU = BIT(3), |
@@ -965,14 +965,14 @@ struct ieee80211_local { | |||
965 | int scan_channel_idx; | 965 | int scan_channel_idx; |
966 | int scan_ies_len; | 966 | int scan_ies_len; |
967 | 967 | ||
968 | bool sched_scanning; | ||
969 | struct ieee80211_sched_scan_ies sched_scan_ies; | 968 | struct ieee80211_sched_scan_ies sched_scan_ies; |
970 | struct work_struct sched_scan_stopped_work; | 969 | struct work_struct sched_scan_stopped_work; |
970 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | ||
971 | 971 | ||
972 | unsigned long leave_oper_channel_time; | 972 | unsigned long leave_oper_channel_time; |
973 | enum mac80211_scan_state next_scan_state; | 973 | enum mac80211_scan_state next_scan_state; |
974 | struct delayed_work scan_work; | 974 | struct delayed_work scan_work; |
975 | struct ieee80211_sub_if_data *scan_sdata; | 975 | struct ieee80211_sub_if_data __rcu *scan_sdata; |
976 | enum nl80211_channel_type _oper_channel_type; | 976 | enum nl80211_channel_type _oper_channel_type; |
977 | struct ieee80211_channel *oper_channel, *csa_channel; | 977 | struct ieee80211_channel *oper_channel, *csa_channel; |
978 | 978 | ||
@@ -1014,7 +1014,6 @@ struct ieee80211_local { | |||
1014 | unsigned int rx_handlers_drop_nullfunc; | 1014 | unsigned int rx_handlers_drop_nullfunc; |
1015 | unsigned int rx_handlers_drop_defrag; | 1015 | unsigned int rx_handlers_drop_defrag; |
1016 | unsigned int rx_handlers_drop_short; | 1016 | unsigned int rx_handlers_drop_short; |
1017 | unsigned int rx_handlers_drop_passive_scan; | ||
1018 | unsigned int tx_expand_skb_head; | 1017 | unsigned int tx_expand_skb_head; |
1019 | unsigned int tx_expand_skb_head_cloned; | 1018 | unsigned int tx_expand_skb_head_cloned; |
1020 | unsigned int rx_expand_skb_head; | 1019 | unsigned int rx_expand_skb_head; |
@@ -1091,6 +1090,12 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | |||
1091 | return netdev_priv(dev); | 1090 | return netdev_priv(dev); |
1092 | } | 1091 | } |
1093 | 1092 | ||
1093 | static inline struct ieee80211_sub_if_data * | ||
1094 | IEEE80211_WDEV_TO_SUB_IF(struct wireless_dev *wdev) | ||
1095 | { | ||
1096 | return container_of(wdev, struct ieee80211_sub_if_data, wdev); | ||
1097 | } | ||
1098 | |||
1094 | /* this struct represents 802.11n's RA/TID combination */ | 1099 | /* this struct represents 802.11n's RA/TID combination */ |
1095 | struct ieee80211_ra_tid { | 1100 | struct ieee80211_ra_tid { |
1096 | u8 ra[ETH_ALEN]; | 1101 | u8 ra[ETH_ALEN]; |
@@ -1241,8 +1246,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
1241 | struct cfg80211_scan_request *req); | 1246 | struct cfg80211_scan_request *req); |
1242 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1247 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
1243 | void ieee80211_run_deferred_scan(struct ieee80211_local *local); | 1248 | void ieee80211_run_deferred_scan(struct ieee80211_local *local); |
1244 | ieee80211_rx_result | 1249 | void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb); |
1245 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | ||
1246 | 1250 | ||
1247 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 1251 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
1248 | struct ieee80211_bss * | 1252 | struct ieee80211_bss * |
@@ -1278,7 +1282,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | |||
1278 | int ieee80211_iface_init(void); | 1282 | int ieee80211_iface_init(void); |
1279 | void ieee80211_iface_exit(void); | 1283 | void ieee80211_iface_exit(void); |
1280 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1284 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1281 | struct net_device **new_dev, enum nl80211_iftype type, | 1285 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1282 | struct vif_params *params); | 1286 | struct vif_params *params); |
1283 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 1287 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
1284 | enum nl80211_iftype type); | 1288 | enum nl80211_iftype type); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fbef7a1ada7a..334ee0fb18ca 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -112,10 +112,11 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | if (local->scan_sdata && | 115 | sdata = rcu_dereference_protected(local->scan_sdata, |
116 | !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | 116 | lockdep_is_held(&local->mtx)); |
117 | if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
117 | scanning = true; | 118 | scanning = true; |
118 | local->scan_sdata->vif.bss_conf.idle = false; | 119 | sdata->vif.bss_conf.idle = false; |
119 | } | 120 | } |
120 | 121 | ||
121 | list_for_each_entry(sdata, &local->interfaces, list) { | 122 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -333,17 +334,21 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
333 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 334 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
334 | { | 335 | { |
335 | struct ieee80211_sub_if_data *sdata; | 336 | struct ieee80211_sub_if_data *sdata; |
336 | int ret; | 337 | int ret = 0; |
337 | 338 | ||
338 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 339 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
339 | return 0; | 340 | return 0; |
340 | 341 | ||
342 | mutex_lock(&local->iflist_mtx); | ||
343 | |||
341 | if (local->monitor_sdata) | 344 | if (local->monitor_sdata) |
342 | return 0; | 345 | goto out_unlock; |
343 | 346 | ||
344 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | 347 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); |
345 | if (!sdata) | 348 | if (!sdata) { |
346 | return -ENOMEM; | 349 | ret = -ENOMEM; |
350 | goto out_unlock; | ||
351 | } | ||
347 | 352 | ||
348 | /* set up data */ | 353 | /* set up data */ |
349 | sdata->local = local; | 354 | sdata->local = local; |
@@ -357,18 +362,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
357 | if (WARN_ON(ret)) { | 362 | if (WARN_ON(ret)) { |
358 | /* ok .. stupid driver, it asked for this! */ | 363 | /* ok .. stupid driver, it asked for this! */ |
359 | kfree(sdata); | 364 | kfree(sdata); |
360 | return ret; | 365 | goto out_unlock; |
361 | } | 366 | } |
362 | 367 | ||
363 | ret = ieee80211_check_queues(sdata); | 368 | ret = ieee80211_check_queues(sdata); |
364 | if (ret) { | 369 | if (ret) { |
365 | kfree(sdata); | 370 | kfree(sdata); |
366 | return ret; | 371 | goto out_unlock; |
367 | } | 372 | } |
368 | 373 | ||
369 | rcu_assign_pointer(local->monitor_sdata, sdata); | 374 | rcu_assign_pointer(local->monitor_sdata, sdata); |
370 | 375 | out_unlock: | |
371 | return 0; | 376 | mutex_unlock(&local->iflist_mtx); |
377 | return ret; | ||
372 | } | 378 | } |
373 | 379 | ||
374 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 380 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
@@ -378,10 +384,12 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
378 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 384 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
379 | return; | 385 | return; |
380 | 386 | ||
381 | sdata = rtnl_dereference(local->monitor_sdata); | 387 | mutex_lock(&local->iflist_mtx); |
382 | 388 | ||
389 | sdata = rcu_dereference_protected(local->monitor_sdata, | ||
390 | lockdep_is_held(&local->iflist_mtx)); | ||
383 | if (!sdata) | 391 | if (!sdata) |
384 | return; | 392 | goto out_unlock; |
385 | 393 | ||
386 | rcu_assign_pointer(local->monitor_sdata, NULL); | 394 | rcu_assign_pointer(local->monitor_sdata, NULL); |
387 | synchronize_net(); | 395 | synchronize_net(); |
@@ -389,6 +397,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
389 | drv_remove_interface(local, sdata); | 397 | drv_remove_interface(local, sdata); |
390 | 398 | ||
391 | kfree(sdata); | 399 | kfree(sdata); |
400 | out_unlock: | ||
401 | mutex_unlock(&local->iflist_mtx); | ||
392 | } | 402 | } |
393 | 403 | ||
394 | /* | 404 | /* |
@@ -628,7 +638,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
628 | 638 | ||
629 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 639 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
630 | 640 | ||
631 | if (local->scan_sdata == sdata) | 641 | if (rcu_access_pointer(local->scan_sdata) == sdata) |
632 | ieee80211_scan_cancel(local); | 642 | ieee80211_scan_cancel(local); |
633 | 643 | ||
634 | /* | 644 | /* |
@@ -1373,7 +1383,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1373 | } | 1383 | } |
1374 | 1384 | ||
1375 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1385 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1376 | struct net_device **new_dev, enum nl80211_iftype type, | 1386 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1377 | struct vif_params *params) | 1387 | struct vif_params *params) |
1378 | { | 1388 | { |
1379 | struct net_device *ndev; | 1389 | struct net_device *ndev; |
@@ -1463,8 +1473,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1463 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1473 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
1464 | mutex_unlock(&local->iflist_mtx); | 1474 | mutex_unlock(&local->iflist_mtx); |
1465 | 1475 | ||
1466 | if (new_dev) | 1476 | if (new_wdev) |
1467 | *new_dev = ndev; | 1477 | *new_wdev = &sdata->wdev; |
1468 | 1478 | ||
1469 | return 0; | 1479 | return 0; |
1470 | 1480 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b3b7e526e245..7ae678ba5d67 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -194,26 +194,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
194 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 194 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
195 | } | 195 | } |
196 | 196 | ||
197 | void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | ||
198 | { | ||
199 | struct ieee80211_key *key; | ||
200 | |||
201 | key = container_of(key_conf, struct ieee80211_key, conf); | ||
202 | |||
203 | might_sleep(); | ||
204 | assert_key_lock(key->local); | ||
205 | |||
206 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | ||
207 | |||
208 | /* | ||
209 | * Flush TX path to avoid attempts to use this key | ||
210 | * after this function returns. Until then, drivers | ||
211 | * must be prepared to handle the key. | ||
212 | */ | ||
213 | synchronize_rcu(); | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | ||
216 | |||
217 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 197 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
218 | int idx, bool uni, bool multi) | 198 | int idx, bool uni, bool multi) |
219 | { | 199 | { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c794101f8987..c26e231c733a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -322,7 +322,8 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
322 | 322 | ||
323 | mutex_lock(&local->mtx); | 323 | mutex_lock(&local->mtx); |
324 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 324 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
325 | local->sched_scanning, | 325 | rcu_dereference_protected(local->sched_scan_sdata, |
326 | lockdep_is_held(&local->mtx)), | ||
326 | "%s called with hardware scan in progress\n", __func__); | 327 | "%s called with hardware scan in progress\n", __func__); |
327 | mutex_unlock(&local->mtx); | 328 | mutex_unlock(&local->mtx); |
328 | 329 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f49f14f8ba82..de4350fce11e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1108,7 +1108,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data) | |||
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | /* MLME */ | 1110 | /* MLME */ |
1111 | static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | 1111 | static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, |
1112 | struct ieee80211_sub_if_data *sdata, | 1112 | struct ieee80211_sub_if_data *sdata, |
1113 | u8 *wmm_param, size_t wmm_param_len) | 1113 | u8 *wmm_param, size_t wmm_param_len) |
1114 | { | 1114 | { |
@@ -1119,23 +1119,23 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1119 | u8 *pos, uapsd_queues = 0; | 1119 | u8 *pos, uapsd_queues = 0; |
1120 | 1120 | ||
1121 | if (!local->ops->conf_tx) | 1121 | if (!local->ops->conf_tx) |
1122 | return; | 1122 | return false; |
1123 | 1123 | ||
1124 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1124 | if (local->hw.queues < IEEE80211_NUM_ACS) |
1125 | return; | 1125 | return false; |
1126 | 1126 | ||
1127 | if (!wmm_param) | 1127 | if (!wmm_param) |
1128 | return; | 1128 | return false; |
1129 | 1129 | ||
1130 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | 1130 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
1131 | return; | 1131 | return false; |
1132 | 1132 | ||
1133 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | 1133 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) |
1134 | uapsd_queues = ifmgd->uapsd_queues; | 1134 | uapsd_queues = ifmgd->uapsd_queues; |
1135 | 1135 | ||
1136 | count = wmm_param[6] & 0x0f; | 1136 | count = wmm_param[6] & 0x0f; |
1137 | if (count == ifmgd->wmm_last_param_set) | 1137 | if (count == ifmgd->wmm_last_param_set) |
1138 | return; | 1138 | return false; |
1139 | ifmgd->wmm_last_param_set = count; | 1139 | ifmgd->wmm_last_param_set = count; |
1140 | 1140 | ||
1141 | pos = wmm_param + 8; | 1141 | pos = wmm_param + 8; |
@@ -1202,6 +1202,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1202 | 1202 | ||
1203 | /* enable WMM or activate new settings */ | 1203 | /* enable WMM or activate new settings */ |
1204 | sdata->vif.bss_conf.qos = true; | 1204 | sdata->vif.bss_conf.qos = true; |
1205 | return true; | ||
1205 | } | 1206 | } |
1206 | 1207 | ||
1207 | static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) | 1208 | static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) |
@@ -1268,11 +1269,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1268 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1269 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1269 | 1270 | ||
1270 | bss_info_changed |= BSS_CHANGED_ASSOC; | 1271 | bss_info_changed |= BSS_CHANGED_ASSOC; |
1271 | /* set timing information */ | ||
1272 | bss_conf->beacon_int = cbss->beacon_interval; | ||
1273 | bss_conf->last_tsf = cbss->tsf; | ||
1274 | |||
1275 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | ||
1276 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 1272 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
1277 | bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); | 1273 | bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); |
1278 | 1274 | ||
@@ -2435,14 +2431,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2435 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, | 2431 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, |
2436 | ifmgd->aid); | 2432 | ifmgd->aid); |
2437 | 2433 | ||
2438 | if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) { | ||
2439 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | ||
2440 | true); | ||
2441 | |||
2442 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2443 | elems.wmm_param_len); | ||
2444 | } | ||
2445 | |||
2446 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { | 2434 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { |
2447 | if (directed_tim) { | 2435 | if (directed_tim) { |
2448 | if (local->hw.conf.dynamic_ps_timeout > 0) { | 2436 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
@@ -2473,6 +2461,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2473 | ifmgd->beacon_crc = ncrc; | 2461 | ifmgd->beacon_crc = ncrc; |
2474 | ifmgd->beacon_crc_valid = true; | 2462 | ifmgd->beacon_crc_valid = true; |
2475 | 2463 | ||
2464 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | ||
2465 | true); | ||
2466 | |||
2467 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2468 | elems.wmm_param_len)) | ||
2469 | changed |= BSS_CHANGED_QOS; | ||
2470 | |||
2476 | if (elems.erp_info && elems.erp_info_len >= 1) { | 2471 | if (elems.erp_info && elems.erp_info_len >= 1) { |
2477 | erp_valid = true; | 2472 | erp_valid = true; |
2478 | erp_value = elems.erp_info[0]; | 2473 | erp_value = elems.erp_info[0]; |
@@ -2974,7 +2969,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2974 | /* scan finished notification */ | 2969 | /* scan finished notification */ |
2975 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | 2970 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) |
2976 | { | 2971 | { |
2977 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 2972 | struct ieee80211_sub_if_data *sdata; |
2978 | 2973 | ||
2979 | /* Restart STA timers */ | 2974 | /* Restart STA timers */ |
2980 | rcu_read_lock(); | 2975 | rcu_read_lock(); |
@@ -3132,9 +3127,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3132 | 3127 | ||
3133 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); | 3128 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); |
3134 | 3129 | ||
3135 | /* tell driver about BSSID and basic rates */ | 3130 | /* set timing information */ |
3131 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | ||
3132 | sdata->vif.bss_conf.sync_tsf = cbss->tsf; | ||
3133 | sdata->vif.bss_conf.sync_device_ts = bss->device_ts; | ||
3134 | |||
3135 | /* tell driver about BSSID, basic rates and timing */ | ||
3136 | ieee80211_bss_info_change_notify(sdata, | 3136 | ieee80211_bss_info_change_notify(sdata, |
3137 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES); | 3137 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | |
3138 | BSS_CHANGED_BEACON_INT); | ||
3138 | 3139 | ||
3139 | if (assoc) | 3140 | if (assoc) |
3140 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3141 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index b0fb6a2b89ad..8c047fc8b325 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -191,7 +191,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
191 | roc->frame = NULL; | 191 | roc->frame = NULL; |
192 | } | 192 | } |
193 | } else { | 193 | } else { |
194 | cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc, | 194 | cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc, |
195 | roc->chan, roc->chan_type, | 195 | roc->chan, roc->chan_type, |
196 | roc->req_duration, GFP_KERNEL); | 196 | roc->req_duration, GFP_KERNEL); |
197 | } | 197 | } |
@@ -299,7 +299,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
299 | 299 | ||
300 | /* was never transmitted */ | 300 | /* was never transmitted */ |
301 | if (roc->frame) { | 301 | if (roc->frame) { |
302 | cfg80211_mgmt_tx_status(roc->sdata->dev, | 302 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, |
303 | (unsigned long)roc->frame, | 303 | (unsigned long)roc->frame, |
304 | roc->frame->data, roc->frame->len, | 304 | roc->frame->data, roc->frame->len, |
305 | false, GFP_KERNEL); | 305 | false, GFP_KERNEL); |
@@ -307,7 +307,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
307 | } | 307 | } |
308 | 308 | ||
309 | if (!roc->mgmt_tx_cookie) | 309 | if (!roc->mgmt_tx_cookie) |
310 | cfg80211_remain_on_channel_expired(roc->sdata->dev, | 310 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, |
311 | (unsigned long)roc, | 311 | (unsigned long)roc, |
312 | roc->chan, roc->chan_type, | 312 | roc->chan, roc->chan_type, |
313 | GFP_KERNEL); | 313 | GFP_KERNEL); |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index f9e51ef8dfa2..fb1d4aa65e8c 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -626,8 +626,12 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
626 | 626 | ||
627 | #ifdef CONFIG_MAC80211_DEBUGFS | 627 | #ifdef CONFIG_MAC80211_DEBUGFS |
628 | /* use fixed index if set */ | 628 | /* use fixed index if set */ |
629 | if (mp->fixed_rate_idx != -1) | 629 | if (mp->fixed_rate_idx != -1) { |
630 | sample_idx = mp->fixed_rate_idx; | 630 | mi->max_tp_rate = mp->fixed_rate_idx; |
631 | mi->max_tp_rate2 = mp->fixed_rate_idx; | ||
632 | mi->max_prob_rate = mp->fixed_rate_idx; | ||
633 | sample_idx = -1; | ||
634 | } | ||
631 | #endif | 635 | #endif |
632 | 636 | ||
633 | if (sample_idx >= 0) { | 637 | if (sample_idx >= 0) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 839cac8fab57..090d417919af 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -413,29 +413,6 @@ static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | |||
413 | 413 | ||
414 | /* rx handlers */ | 414 | /* rx handlers */ |
415 | 415 | ||
416 | static ieee80211_rx_result debug_noinline | ||
417 | ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | ||
418 | { | ||
419 | struct ieee80211_local *local = rx->local; | ||
420 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
421 | struct sk_buff *skb = rx->skb; | ||
422 | |||
423 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | ||
424 | !local->sched_scanning)) | ||
425 | return RX_CONTINUE; | ||
426 | |||
427 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || | ||
428 | test_bit(SCAN_SW_SCANNING, &local->scanning) || | ||
429 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
430 | local->sched_scanning) | ||
431 | return ieee80211_scan_rx(rx->sdata, skb); | ||
432 | |||
433 | /* scanning finished during invoking of handlers */ | ||
434 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); | ||
435 | return RX_DROP_UNUSABLE; | ||
436 | } | ||
437 | |||
438 | |||
439 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | 416 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) |
440 | { | 417 | { |
441 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 418 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -2404,7 +2381,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | |||
2404 | if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 2381 | if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
2405 | sig = status->signal; | 2382 | sig = status->signal; |
2406 | 2383 | ||
2407 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig, | 2384 | if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, |
2408 | rx->skb->data, rx->skb->len, | 2385 | rx->skb->data, rx->skb->len, |
2409 | GFP_ATOMIC)) { | 2386 | GFP_ATOMIC)) { |
2410 | if (rx->sta) | 2387 | if (rx->sta) |
@@ -2695,7 +2672,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2695 | goto rxh_next; \ | 2672 | goto rxh_next; \ |
2696 | } while (0); | 2673 | } while (0); |
2697 | 2674 | ||
2698 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2699 | CALL_RXH(ieee80211_rx_h_check) | 2675 | CALL_RXH(ieee80211_rx_h_check) |
2700 | 2676 | ||
2701 | ieee80211_rx_reorder_ampdu(rx); | 2677 | ieee80211_rx_reorder_ampdu(rx); |
@@ -2765,11 +2741,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2765 | return 0; | 2741 | return 0; |
2766 | if (ieee80211_is_beacon(hdr->frame_control)) { | 2742 | if (ieee80211_is_beacon(hdr->frame_control)) { |
2767 | return 1; | 2743 | return 1; |
2768 | } | 2744 | } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { |
2769 | else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { | 2745 | return 0; |
2770 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN)) | ||
2771 | return 0; | ||
2772 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
2773 | } else if (!multicast && | 2746 | } else if (!multicast && |
2774 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { | 2747 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { |
2775 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2748 | if (!(sdata->dev->flags & IFF_PROMISC)) |
@@ -2807,11 +2780,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2807 | * and location updates. Note that mac80211 | 2780 | * and location updates. Note that mac80211 |
2808 | * itself never looks at these frames. | 2781 | * itself never looks at these frames. |
2809 | */ | 2782 | */ |
2810 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | 2783 | if (ieee80211_is_public_action(hdr, skb->len)) |
2811 | ieee80211_is_public_action(hdr, skb->len)) | ||
2812 | return 1; | 2784 | return 1; |
2813 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | 2785 | if (!ieee80211_is_beacon(hdr->frame_control)) |
2814 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2815 | return 0; | 2786 | return 0; |
2816 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2787 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2817 | } | 2788 | } |
@@ -2877,7 +2848,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, | |||
2877 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2848 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2878 | struct sk_buff *skb) | 2849 | struct sk_buff *skb) |
2879 | { | 2850 | { |
2880 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2881 | struct ieee80211_local *local = hw_to_local(hw); | 2851 | struct ieee80211_local *local = hw_to_local(hw); |
2882 | struct ieee80211_sub_if_data *sdata; | 2852 | struct ieee80211_sub_if_data *sdata; |
2883 | struct ieee80211_hdr *hdr; | 2853 | struct ieee80211_hdr *hdr; |
@@ -2895,11 +2865,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2895 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) | 2865 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2896 | local->dot11ReceivedFragmentCount++; | 2866 | local->dot11ReceivedFragmentCount++; |
2897 | 2867 | ||
2898 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | ||
2899 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
2900 | test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
2901 | status->rx_flags |= IEEE80211_RX_IN_SCAN; | ||
2902 | |||
2903 | if (ieee80211_is_mgmt(fc)) | 2868 | if (ieee80211_is_mgmt(fc)) |
2904 | err = skb_linearize(skb); | 2869 | err = skb_linearize(skb); |
2905 | else | 2870 | else |
@@ -2914,6 +2879,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2914 | ieee80211_parse_qos(&rx); | 2879 | ieee80211_parse_qos(&rx); |
2915 | ieee80211_verify_alignment(&rx); | 2880 | ieee80211_verify_alignment(&rx); |
2916 | 2881 | ||
2882 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) || | ||
2883 | ieee80211_is_beacon(hdr->frame_control))) | ||
2884 | ieee80211_scan_rx(local, skb); | ||
2885 | |||
2917 | if (ieee80211_is_data(fc)) { | 2886 | if (ieee80211_is_data(fc)) { |
2918 | prev_sta = NULL; | 2887 | prev_sta = NULL; |
2919 | 2888 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 379f178eab5f..e80a8b644aa0 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -83,13 +83,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
83 | 83 | ||
84 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, | 84 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, |
85 | mgmt, len, signal, GFP_ATOMIC); | 85 | mgmt, len, signal, GFP_ATOMIC); |
86 | |||
87 | if (!cbss) | 86 | if (!cbss) |
88 | return NULL; | 87 | return NULL; |
89 | 88 | ||
90 | cbss->free_priv = ieee80211_rx_bss_free; | 89 | cbss->free_priv = ieee80211_rx_bss_free; |
91 | bss = (void *)cbss->priv; | 90 | bss = (void *)cbss->priv; |
92 | 91 | ||
92 | bss->device_ts = rx_status->device_timestamp; | ||
93 | |||
93 | if (elems->parse_error) { | 94 | if (elems->parse_error) { |
94 | if (beacon) | 95 | if (beacon) |
95 | bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON; | 96 | bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON; |
@@ -165,52 +166,47 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
165 | return bss; | 166 | return bss; |
166 | } | 167 | } |
167 | 168 | ||
168 | ieee80211_rx_result | 169 | void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) |
169 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
170 | { | 170 | { |
171 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 171 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); |
172 | struct ieee80211_mgmt *mgmt; | 172 | struct ieee80211_sub_if_data *sdata1, *sdata2; |
173 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
173 | struct ieee80211_bss *bss; | 174 | struct ieee80211_bss *bss; |
174 | u8 *elements; | 175 | u8 *elements; |
175 | struct ieee80211_channel *channel; | 176 | struct ieee80211_channel *channel; |
176 | size_t baselen; | 177 | size_t baselen; |
177 | int freq; | 178 | int freq; |
178 | __le16 fc; | 179 | bool beacon; |
179 | bool presp, beacon = false; | ||
180 | struct ieee802_11_elems elems; | 180 | struct ieee802_11_elems elems; |
181 | 181 | ||
182 | if (skb->len < 2) | 182 | if (skb->len < 24 || |
183 | return RX_DROP_UNUSABLE; | 183 | (!ieee80211_is_probe_resp(mgmt->frame_control) && |
184 | 184 | !ieee80211_is_beacon(mgmt->frame_control))) | |
185 | mgmt = (struct ieee80211_mgmt *) skb->data; | 185 | return; |
186 | fc = mgmt->frame_control; | ||
187 | 186 | ||
188 | if (ieee80211_is_ctl(fc)) | 187 | sdata1 = rcu_dereference(local->scan_sdata); |
189 | return RX_CONTINUE; | 188 | sdata2 = rcu_dereference(local->sched_scan_sdata); |
190 | 189 | ||
191 | if (skb->len < 24) | 190 | if (likely(!sdata1 && !sdata2)) |
192 | return RX_CONTINUE; | 191 | return; |
193 | 192 | ||
194 | presp = ieee80211_is_probe_resp(fc); | 193 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { |
195 | if (presp) { | ||
196 | /* ignore ProbeResp to foreign address */ | 194 | /* ignore ProbeResp to foreign address */ |
197 | if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) | 195 | if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && |
198 | return RX_DROP_MONITOR; | 196 | (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr))) |
197 | return; | ||
199 | 198 | ||
200 | presp = true; | ||
201 | elements = mgmt->u.probe_resp.variable; | 199 | elements = mgmt->u.probe_resp.variable; |
202 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | 200 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); |
201 | beacon = false; | ||
203 | } else { | 202 | } else { |
204 | beacon = ieee80211_is_beacon(fc); | ||
205 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | 203 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
206 | elements = mgmt->u.beacon.variable; | 204 | elements = mgmt->u.beacon.variable; |
205 | beacon = true; | ||
207 | } | 206 | } |
208 | 207 | ||
209 | if (!presp && !beacon) | ||
210 | return RX_CONTINUE; | ||
211 | |||
212 | if (baselen > skb->len) | 208 | if (baselen > skb->len) |
213 | return RX_DROP_MONITOR; | 209 | return; |
214 | 210 | ||
215 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 211 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
216 | 212 | ||
@@ -220,22 +216,16 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
220 | else | 216 | else |
221 | freq = rx_status->freq; | 217 | freq = rx_status->freq; |
222 | 218 | ||
223 | channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); | 219 | channel = ieee80211_get_channel(local->hw.wiphy, freq); |
224 | 220 | ||
225 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 221 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
226 | return RX_DROP_MONITOR; | 222 | return; |
227 | 223 | ||
228 | bss = ieee80211_bss_info_update(sdata->local, rx_status, | 224 | bss = ieee80211_bss_info_update(local, rx_status, |
229 | mgmt, skb->len, &elems, | 225 | mgmt, skb->len, &elems, |
230 | channel, beacon); | 226 | channel, beacon); |
231 | if (bss) | 227 | if (bss) |
232 | ieee80211_rx_bss_put(sdata->local, bss); | 228 | ieee80211_rx_bss_put(local, bss); |
233 | |||
234 | if (channel == sdata->local->oper_channel) | ||
235 | return RX_CONTINUE; | ||
236 | |||
237 | dev_kfree_skb(skb); | ||
238 | return RX_QUEUED; | ||
239 | } | 229 | } |
240 | 230 | ||
241 | /* return false if no more work */ | 231 | /* return false if no more work */ |
@@ -293,7 +283,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
293 | return; | 283 | return; |
294 | 284 | ||
295 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 285 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
296 | int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); | 286 | int rc; |
287 | |||
288 | rc = drv_hw_scan(local, | ||
289 | rcu_dereference_protected(local->scan_sdata, | ||
290 | lockdep_is_held(&local->mtx)), | ||
291 | local->hw_scan_req); | ||
292 | |||
297 | if (rc == 0) | 293 | if (rc == 0) |
298 | return; | 294 | return; |
299 | } | 295 | } |
@@ -394,7 +390,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local) | |||
394 | if (!local->scan_req || local->scanning) | 390 | if (!local->scan_req || local->scanning) |
395 | return; | 391 | return; |
396 | 392 | ||
397 | if (!ieee80211_can_scan(local, local->scan_sdata)) | 393 | if (!ieee80211_can_scan(local, |
394 | rcu_dereference_protected( | ||
395 | local->scan_sdata, | ||
396 | lockdep_is_held(&local->mtx)))) | ||
398 | return; | 397 | return; |
399 | 398 | ||
400 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, | 399 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, |
@@ -405,9 +404,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
405 | unsigned long *next_delay) | 404 | unsigned long *next_delay) |
406 | { | 405 | { |
407 | int i; | 406 | int i; |
408 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 407 | struct ieee80211_sub_if_data *sdata; |
409 | enum ieee80211_band band = local->hw.conf.channel->band; | 408 | enum ieee80211_band band = local->hw.conf.channel->band; |
410 | 409 | ||
410 | sdata = rcu_dereference_protected(local->scan_sdata, | ||
411 | lockdep_is_held(&local->mtx));; | ||
412 | |||
411 | for (i = 0; i < local->scan_req->n_ssids; i++) | 413 | for (i = 0; i < local->scan_req->n_ssids; i++) |
412 | ieee80211_send_probe_req( | 414 | ieee80211_send_probe_req( |
413 | sdata, NULL, | 415 | sdata, NULL, |
@@ -439,7 +441,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
439 | if (!ieee80211_can_scan(local, sdata)) { | 441 | if (!ieee80211_can_scan(local, sdata)) { |
440 | /* wait for the work to finish/time out */ | 442 | /* wait for the work to finish/time out */ |
441 | local->scan_req = req; | 443 | local->scan_req = req; |
442 | local->scan_sdata = sdata; | 444 | rcu_assign_pointer(local->scan_sdata, sdata); |
443 | return 0; | 445 | return 0; |
444 | } | 446 | } |
445 | 447 | ||
@@ -473,7 +475,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
473 | } | 475 | } |
474 | 476 | ||
475 | local->scan_req = req; | 477 | local->scan_req = req; |
476 | local->scan_sdata = sdata; | 478 | rcu_assign_pointer(local->scan_sdata, sdata); |
477 | 479 | ||
478 | if (local->ops->hw_scan) { | 480 | if (local->ops->hw_scan) { |
479 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 481 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
@@ -533,7 +535,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
533 | ieee80211_recalc_idle(local); | 535 | ieee80211_recalc_idle(local); |
534 | 536 | ||
535 | local->scan_req = NULL; | 537 | local->scan_req = NULL; |
536 | local->scan_sdata = NULL; | 538 | rcu_assign_pointer(local->scan_sdata, NULL); |
537 | } | 539 | } |
538 | 540 | ||
539 | return rc; | 541 | return rc; |
@@ -720,7 +722,8 @@ void ieee80211_scan_work(struct work_struct *work) | |||
720 | 722 | ||
721 | mutex_lock(&local->mtx); | 723 | mutex_lock(&local->mtx); |
722 | 724 | ||
723 | sdata = local->scan_sdata; | 725 | sdata = rcu_dereference_protected(local->scan_sdata, |
726 | lockdep_is_held(&local->mtx)); | ||
724 | 727 | ||
725 | /* When scanning on-channel, the first-callback means completed. */ | 728 | /* When scanning on-channel, the first-callback means completed. */ |
726 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { | 729 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { |
@@ -741,7 +744,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
741 | int rc; | 744 | int rc; |
742 | 745 | ||
743 | local->scan_req = NULL; | 746 | local->scan_req = NULL; |
744 | local->scan_sdata = NULL; | 747 | rcu_assign_pointer(local->scan_sdata, NULL); |
745 | 748 | ||
746 | rc = __ieee80211_start_scan(sdata, req); | 749 | rc = __ieee80211_start_scan(sdata, req); |
747 | if (rc) { | 750 | if (rc) { |
@@ -893,7 +896,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
893 | 896 | ||
894 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { | 897 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { |
895 | if (local->ops->cancel_hw_scan) | 898 | if (local->ops->cancel_hw_scan) |
896 | drv_cancel_hw_scan(local, local->scan_sdata); | 899 | drv_cancel_hw_scan(local, |
900 | rcu_dereference_protected(local->scan_sdata, | ||
901 | lockdep_is_held(&local->mtx))); | ||
897 | goto out; | 902 | goto out; |
898 | } | 903 | } |
899 | 904 | ||
@@ -915,9 +920,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
915 | struct ieee80211_local *local = sdata->local; | 920 | struct ieee80211_local *local = sdata->local; |
916 | int ret, i; | 921 | int ret, i; |
917 | 922 | ||
918 | mutex_lock(&sdata->local->mtx); | 923 | mutex_lock(&local->mtx); |
919 | 924 | ||
920 | if (local->sched_scanning) { | 925 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
921 | ret = -EBUSY; | 926 | ret = -EBUSY; |
922 | goto out; | 927 | goto out; |
923 | } | 928 | } |
@@ -928,6 +933,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
928 | } | 933 | } |
929 | 934 | ||
930 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 935 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
936 | if (!local->hw.wiphy->bands[i]) | ||
937 | continue; | ||
938 | |||
931 | local->sched_scan_ies.ie[i] = kzalloc(2 + | 939 | local->sched_scan_ies.ie[i] = kzalloc(2 + |
932 | IEEE80211_MAX_SSID_LEN + | 940 | IEEE80211_MAX_SSID_LEN + |
933 | local->scan_ies_len + | 941 | local->scan_ies_len + |
@@ -948,7 +956,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
948 | ret = drv_sched_scan_start(local, sdata, req, | 956 | ret = drv_sched_scan_start(local, sdata, req, |
949 | &local->sched_scan_ies); | 957 | &local->sched_scan_ies); |
950 | if (ret == 0) { | 958 | if (ret == 0) { |
951 | local->sched_scanning = true; | 959 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
952 | goto out; | 960 | goto out; |
953 | } | 961 | } |
954 | 962 | ||
@@ -956,7 +964,7 @@ out_free: | |||
956 | while (i > 0) | 964 | while (i > 0) |
957 | kfree(local->sched_scan_ies.ie[--i]); | 965 | kfree(local->sched_scan_ies.ie[--i]); |
958 | out: | 966 | out: |
959 | mutex_unlock(&sdata->local->mtx); | 967 | mutex_unlock(&local->mtx); |
960 | return ret; | 968 | return ret; |
961 | } | 969 | } |
962 | 970 | ||
@@ -965,22 +973,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
965 | struct ieee80211_local *local = sdata->local; | 973 | struct ieee80211_local *local = sdata->local; |
966 | int ret = 0, i; | 974 | int ret = 0, i; |
967 | 975 | ||
968 | mutex_lock(&sdata->local->mtx); | 976 | mutex_lock(&local->mtx); |
969 | 977 | ||
970 | if (!local->ops->sched_scan_stop) { | 978 | if (!local->ops->sched_scan_stop) { |
971 | ret = -ENOTSUPP; | 979 | ret = -ENOTSUPP; |
972 | goto out; | 980 | goto out; |
973 | } | 981 | } |
974 | 982 | ||
975 | if (local->sched_scanning) { | 983 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
976 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 984 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
977 | kfree(local->sched_scan_ies.ie[i]); | 985 | kfree(local->sched_scan_ies.ie[i]); |
978 | 986 | ||
979 | drv_sched_scan_stop(local, sdata); | 987 | drv_sched_scan_stop(local, sdata); |
980 | local->sched_scanning = false; | 988 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
981 | } | 989 | } |
982 | out: | 990 | out: |
983 | mutex_unlock(&sdata->local->mtx); | 991 | mutex_unlock(&local->mtx); |
984 | 992 | ||
985 | return ret; | 993 | return ret; |
986 | } | 994 | } |
@@ -1004,7 +1012,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1004 | 1012 | ||
1005 | mutex_lock(&local->mtx); | 1013 | mutex_lock(&local->mtx); |
1006 | 1014 | ||
1007 | if (!local->sched_scanning) { | 1015 | if (!rcu_access_pointer(local->sched_scan_sdata)) { |
1008 | mutex_unlock(&local->mtx); | 1016 | mutex_unlock(&local->mtx); |
1009 | return; | 1017 | return; |
1010 | } | 1018 | } |
@@ -1012,7 +1020,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1012 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 1020 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1013 | kfree(local->sched_scan_ies.ie[i]); | 1021 | kfree(local->sched_scan_ies.ie[i]); |
1014 | 1022 | ||
1015 | local->sched_scanning = false; | 1023 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
1016 | 1024 | ||
1017 | mutex_unlock(&local->mtx); | 1025 | mutex_unlock(&local->mtx); |
1018 | 1026 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 2ed2f27fe8a7..8cd72914cdaf 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -519,14 +519,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
519 | u64 cookie = (unsigned long)skb; | 519 | u64 cookie = (unsigned long)skb; |
520 | acked = info->flags & IEEE80211_TX_STAT_ACK; | 520 | acked = info->flags & IEEE80211_TX_STAT_ACK; |
521 | 521 | ||
522 | /* | ||
523 | * TODO: When we have non-netdev frame TX, | ||
524 | * we cannot use skb->dev->ieee80211_ptr | ||
525 | */ | ||
526 | |||
522 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 527 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
523 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 528 | ieee80211_is_qos_nullfunc(hdr->frame_control)) |
524 | cfg80211_probe_status(skb->dev, hdr->addr1, | 529 | cfg80211_probe_status(skb->dev, hdr->addr1, |
525 | cookie, acked, GFP_ATOMIC); | 530 | cookie, acked, GFP_ATOMIC); |
526 | else | 531 | else |
527 | cfg80211_mgmt_tx_status( | 532 | cfg80211_mgmt_tx_status( |
528 | skb->dev, cookie, skb->data, skb->len, | 533 | skb->dev->ieee80211_ptr, cookie, skb->data, |
529 | acked, GFP_ATOMIC); | 534 | skb->len, acked, GFP_ATOMIC); |
530 | } | 535 | } |
531 | 536 | ||
532 | if (unlikely(info->ack_frame_id)) { | 537 | if (unlikely(info->ack_frame_id)) { |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e1e9d10ec2e7..c6d33b55b2df 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -306,7 +306,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
306 | __field(u8, dtimper) | 306 | __field(u8, dtimper) |
307 | __field(u16, bcnint) | 307 | __field(u16, bcnint) |
308 | __field(u16, assoc_cap) | 308 | __field(u16, assoc_cap) |
309 | __field(u64, timestamp) | 309 | __field(u64, sync_tsf) |
310 | __field(u32, sync_device_ts) | ||
310 | __field(u32, basic_rates) | 311 | __field(u32, basic_rates) |
311 | __field(u32, changed) | 312 | __field(u32, changed) |
312 | __field(bool, enable_beacon) | 313 | __field(bool, enable_beacon) |
@@ -325,7 +326,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
325 | __entry->dtimper = info->dtim_period; | 326 | __entry->dtimper = info->dtim_period; |
326 | __entry->bcnint = info->beacon_int; | 327 | __entry->bcnint = info->beacon_int; |
327 | __entry->assoc_cap = info->assoc_capability; | 328 | __entry->assoc_cap = info->assoc_capability; |
328 | __entry->timestamp = info->last_tsf; | 329 | __entry->sync_tsf = info->sync_tsf; |
330 | __entry->sync_device_ts = info->sync_device_ts; | ||
329 | __entry->basic_rates = info->basic_rates; | 331 | __entry->basic_rates = info->basic_rates; |
330 | __entry->enable_beacon = info->enable_beacon; | 332 | __entry->enable_beacon = info->enable_beacon; |
331 | __entry->ht_operation_mode = info->ht_operation_mode; | 333 | __entry->ht_operation_mode = info->ht_operation_mode; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c9d2175d15c1..b755e778b0c4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -523,7 +523,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) | |||
523 | static ieee80211_tx_result debug_noinline | 523 | static ieee80211_tx_result debug_noinline |
524 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | 524 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) |
525 | { | 525 | { |
526 | struct ieee80211_key *key = NULL; | 526 | struct ieee80211_key *key; |
527 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 527 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
528 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 528 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
529 | 529 | ||
@@ -542,16 +542,23 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
542 | else if (!is_multicast_ether_addr(hdr->addr1) && | 542 | else if (!is_multicast_ether_addr(hdr->addr1) && |
543 | (key = rcu_dereference(tx->sdata->default_unicast_key))) | 543 | (key = rcu_dereference(tx->sdata->default_unicast_key))) |
544 | tx->key = key; | 544 | tx->key = key; |
545 | else if (tx->sdata->drop_unencrypted && | 545 | else if (info->flags & IEEE80211_TX_CTL_INJECTED) |
546 | (tx->skb->protocol != tx->sdata->control_port_protocol) && | 546 | tx->key = NULL; |
547 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | 547 | else if (!tx->sdata->drop_unencrypted) |
548 | (!ieee80211_is_robust_mgmt_frame(hdr) || | 548 | tx->key = NULL; |
549 | (ieee80211_is_action(hdr->frame_control) && | 549 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) |
550 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) { | 550 | tx->key = NULL; |
551 | else if (ieee80211_is_robust_mgmt_frame(hdr) && | ||
552 | !(ieee80211_is_action(hdr->frame_control) && | ||
553 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) | ||
554 | tx->key = NULL; | ||
555 | else if (ieee80211_is_mgmt(hdr->frame_control) && | ||
556 | !ieee80211_is_robust_mgmt_frame(hdr)) | ||
557 | tx->key = NULL; | ||
558 | else { | ||
551 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 559 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
552 | return TX_DROP; | 560 | return TX_DROP; |
553 | } else | 561 | } |
554 | tx->key = NULL; | ||
555 | 562 | ||
556 | if (tx->key) { | 563 | if (tx->key) { |
557 | bool skip_hw = false; | 564 | bool skip_hw = false; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 64493a7bef1a..39b82fee4904 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -529,6 +529,11 @@ void ieee80211_iterate_active_interfaces( | |||
529 | &sdata->vif); | 529 | &sdata->vif); |
530 | } | 530 | } |
531 | 531 | ||
532 | sdata = rcu_dereference_protected(local->monitor_sdata, | ||
533 | lockdep_is_held(&local->iflist_mtx)); | ||
534 | if (sdata) | ||
535 | iterator(data, sdata->vif.addr, &sdata->vif); | ||
536 | |||
532 | mutex_unlock(&local->iflist_mtx); | 537 | mutex_unlock(&local->iflist_mtx); |
533 | } | 538 | } |
534 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 539 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
@@ -557,6 +562,10 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
557 | &sdata->vif); | 562 | &sdata->vif); |
558 | } | 563 | } |
559 | 564 | ||
565 | sdata = rcu_dereference(local->monitor_sdata); | ||
566 | if (sdata) | ||
567 | iterator(data, sdata->vif.addr, &sdata->vif); | ||
568 | |||
560 | rcu_read_unlock(); | 569 | rcu_read_unlock(); |
561 | } | 570 | } |
562 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 571 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
@@ -999,6 +1008,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
999 | int ext_rates_len; | 1008 | int ext_rates_len; |
1000 | 1009 | ||
1001 | sband = local->hw.wiphy->bands[band]; | 1010 | sband = local->hw.wiphy->bands[band]; |
1011 | if (WARN_ON_ONCE(!sband)) | ||
1012 | return 0; | ||
1002 | 1013 | ||
1003 | pos = buffer; | 1014 | pos = buffer; |
1004 | 1015 | ||