diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-20 12:30:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-20 12:30:48 -0400 |
commit | 90b90f60c4f8e3a8525dfeb4aec46a9c7a29c857 (patch) | |
tree | 9b1d8ca6084012a02b302520bc26e5be65ba7b2a /net/mac80211 | |
parent | 769162e38b91e1d300752e666260fa6c7b203fbc (diff) | |
parent | 36eb22e97a2b621fb707eead58ef915ab0f46e9e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 62 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 24 | ||||
-rw-r--r-- | net/mac80211/iface.c | 60 | ||||
-rw-r--r-- | net/mac80211/key.c | 20 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 62 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 12 | ||||
-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 | 30 | ||||
-rw-r--r-- | net/mac80211/util.c | 11 |
16 files changed, 250 insertions, 227 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..d41974aacf51 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 | } |
@@ -917,6 +917,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
917 | 917 | ||
918 | kfree_rcu(old, rcu_head); | 918 | kfree_rcu(old, rcu_head); |
919 | 919 | ||
920 | sta_info_flush(sdata->local, sdata); | ||
920 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 921 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
921 | 922 | ||
922 | return 0; | 923 | return 0; |
@@ -1741,6 +1742,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1741 | return -EINVAL; | 1742 | return -EINVAL; |
1742 | } | 1743 | } |
1743 | 1744 | ||
1745 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); | ||
1746 | |||
1744 | return 0; | 1747 | return 0; |
1745 | } | 1748 | } |
1746 | 1749 | ||
@@ -1761,10 +1764,11 @@ static int ieee80211_resume(struct wiphy *wiphy) | |||
1761 | #endif | 1764 | #endif |
1762 | 1765 | ||
1763 | static int ieee80211_scan(struct wiphy *wiphy, | 1766 | static int ieee80211_scan(struct wiphy *wiphy, |
1764 | struct net_device *dev, | ||
1765 | struct cfg80211_scan_request *req) | 1767 | struct cfg80211_scan_request *req) |
1766 | { | 1768 | { |
1767 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1769 | struct ieee80211_sub_if_data *sdata; |
1770 | |||
1771 | sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev); | ||
1768 | 1772 | ||
1769 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { | 1773 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1770 | case NL80211_IFTYPE_STATION: | 1774 | case NL80211_IFTYPE_STATION: |
@@ -2297,13 +2301,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2297 | } | 2301 | } |
2298 | 2302 | ||
2299 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2303 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
2300 | struct net_device *dev, | 2304 | struct wireless_dev *wdev, |
2301 | struct ieee80211_channel *chan, | 2305 | struct ieee80211_channel *chan, |
2302 | enum nl80211_channel_type channel_type, | 2306 | enum nl80211_channel_type channel_type, |
2303 | unsigned int duration, | 2307 | unsigned int duration, |
2304 | u64 *cookie) | 2308 | u64 *cookie) |
2305 | { | 2309 | { |
2306 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2310 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2307 | struct ieee80211_local *local = sdata->local; | 2311 | struct ieee80211_local *local = sdata->local; |
2308 | int ret; | 2312 | int ret; |
2309 | 2313 | ||
@@ -2390,23 +2394,23 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2390 | } | 2394 | } |
2391 | 2395 | ||
2392 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | 2396 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, |
2393 | struct net_device *dev, | 2397 | struct wireless_dev *wdev, |
2394 | u64 cookie) | 2398 | u64 cookie) |
2395 | { | 2399 | { |
2396 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2400 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2397 | struct ieee80211_local *local = sdata->local; | 2401 | struct ieee80211_local *local = sdata->local; |
2398 | 2402 | ||
2399 | return ieee80211_cancel_roc(local, cookie, false); | 2403 | return ieee80211_cancel_roc(local, cookie, false); |
2400 | } | 2404 | } |
2401 | 2405 | ||
2402 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 2406 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
2403 | struct ieee80211_channel *chan, bool offchan, | 2407 | struct ieee80211_channel *chan, bool offchan, |
2404 | enum nl80211_channel_type channel_type, | 2408 | enum nl80211_channel_type channel_type, |
2405 | bool channel_type_valid, unsigned int wait, | 2409 | bool channel_type_valid, unsigned int wait, |
2406 | const u8 *buf, size_t len, bool no_cck, | 2410 | const u8 *buf, size_t len, bool no_cck, |
2407 | bool dont_wait_for_ack, u64 *cookie) | 2411 | bool dont_wait_for_ack, u64 *cookie) |
2408 | { | 2412 | { |
2409 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2413 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2410 | struct ieee80211_local *local = sdata->local; | 2414 | struct ieee80211_local *local = sdata->local; |
2411 | struct sk_buff *skb; | 2415 | struct sk_buff *skb; |
2412 | struct sta_info *sta; | 2416 | struct sta_info *sta; |
@@ -2490,6 +2494,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2490 | skb->dev = sdata->dev; | 2494 | skb->dev = sdata->dev; |
2491 | 2495 | ||
2492 | if (!need_offchan) { | 2496 | if (!need_offchan) { |
2497 | *cookie = (unsigned long) skb; | ||
2493 | ieee80211_tx_skb(sdata, skb); | 2498 | ieee80211_tx_skb(sdata, skb); |
2494 | ret = 0; | 2499 | ret = 0; |
2495 | goto out_unlock; | 2500 | goto out_unlock; |
@@ -2511,21 +2516,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2511 | } | 2516 | } |
2512 | 2517 | ||
2513 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | 2518 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, |
2514 | struct net_device *dev, | 2519 | struct wireless_dev *wdev, |
2515 | u64 cookie) | 2520 | u64 cookie) |
2516 | { | 2521 | { |
2517 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2522 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2518 | struct ieee80211_local *local = sdata->local; | ||
2519 | 2523 | ||
2520 | return ieee80211_cancel_roc(local, cookie, true); | 2524 | return ieee80211_cancel_roc(local, cookie, true); |
2521 | } | 2525 | } |
2522 | 2526 | ||
2523 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 2527 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
2524 | struct net_device *dev, | 2528 | struct wireless_dev *wdev, |
2525 | u16 frame_type, bool reg) | 2529 | u16 frame_type, bool reg) |
2526 | { | 2530 | { |
2527 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2531 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2528 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2532 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2529 | 2533 | ||
2530 | switch (frame_type) { | 2534 | switch (frame_type) { |
2531 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: | 2535 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: |
@@ -2980,14 +2984,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
2980 | return 0; | 2984 | return 0; |
2981 | } | 2985 | } |
2982 | 2986 | ||
2983 | static void ieee80211_set_monitor_enabled(struct wiphy *wiphy, bool enabled) | 2987 | static struct ieee80211_channel * |
2988 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
2989 | enum nl80211_channel_type *type) | ||
2984 | { | 2990 | { |
2985 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2991 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2986 | 2992 | ||
2987 | if (enabled) | 2993 | *type = local->_oper_channel_type; |
2988 | WARN_ON(ieee80211_add_virtual_monitor(local)); | 2994 | return local->oper_channel; |
2989 | else | ||
2990 | ieee80211_del_virtual_monitor(local); | ||
2991 | } | 2995 | } |
2992 | 2996 | ||
2993 | #ifdef CONFIG_PM | 2997 | #ifdef CONFIG_PM |
@@ -3064,11 +3068,11 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3064 | .tdls_mgmt = ieee80211_tdls_mgmt, | 3068 | .tdls_mgmt = ieee80211_tdls_mgmt, |
3065 | .probe_client = ieee80211_probe_client, | 3069 | .probe_client = ieee80211_probe_client, |
3066 | .set_noack_map = ieee80211_set_noack_map, | 3070 | .set_noack_map = ieee80211_set_noack_map, |
3067 | .set_monitor_enabled = ieee80211_set_monitor_enabled, | ||
3068 | #ifdef CONFIG_PM | 3071 | #ifdef CONFIG_PM |
3069 | .set_wakeup = ieee80211_set_wakeup, | 3072 | .set_wakeup = ieee80211_set_wakeup, |
3070 | #endif | 3073 | #endif |
3071 | .get_et_sset_count = ieee80211_get_et_sset_count, | 3074 | .get_et_sset_count = ieee80211_get_et_sset_count, |
3072 | .get_et_stats = ieee80211_get_et_stats, | 3075 | .get_et_stats = ieee80211_get_et_stats, |
3073 | .get_et_strings = ieee80211_get_et_strings, | 3076 | .get_et_strings = ieee80211_get_et_strings, |
3077 | .get_channel = ieee80211_cfg_get_channel, | ||
3074 | }; | 3078 | }; |
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..bb61f7718c4c 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); |
@@ -1487,10 +1491,6 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1487 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1491 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1488 | struct sk_buff *skb, bool need_basic); | 1492 | struct sk_buff *skb, bool need_basic); |
1489 | 1493 | ||
1490 | /* virtual monitor */ | ||
1491 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local); | ||
1492 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local); | ||
1493 | |||
1494 | /* channel management */ | 1494 | /* channel management */ |
1495 | enum ieee80211_chan_mode { | 1495 | enum ieee80211_chan_mode { |
1496 | CHAN_MODE_UNDEFINED, | 1496 | CHAN_MODE_UNDEFINED, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fbef7a1ada7a..bfb57dcc1538 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) { |
@@ -330,20 +331,24 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
330 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 331 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
331 | } | 332 | } |
332 | 333 | ||
333 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 334 | static 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,31 +362,34 @@ 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 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
375 | { | 381 | { |
376 | struct ieee80211_sub_if_data *sdata; | 382 | struct ieee80211_sub_if_data *sdata; |
377 | 383 | ||
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 | /* |
@@ -487,6 +497,12 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
487 | break; | 497 | break; |
488 | } | 498 | } |
489 | 499 | ||
500 | if (local->monitors == 0 && local->open_count == 0) { | ||
501 | res = ieee80211_add_virtual_monitor(local); | ||
502 | if (res) | ||
503 | goto err_stop; | ||
504 | } | ||
505 | |||
490 | /* must be before the call to ieee80211_configure_filter */ | 506 | /* must be before the call to ieee80211_configure_filter */ |
491 | local->monitors++; | 507 | local->monitors++; |
492 | if (local->monitors == 1) { | 508 | if (local->monitors == 1) { |
@@ -501,6 +517,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
501 | break; | 517 | break; |
502 | default: | 518 | default: |
503 | if (coming_up) { | 519 | if (coming_up) { |
520 | ieee80211_del_virtual_monitor(local); | ||
521 | |||
504 | res = drv_add_interface(local, sdata); | 522 | res = drv_add_interface(local, sdata); |
505 | if (res) | 523 | if (res) |
506 | goto err_stop; | 524 | goto err_stop; |
@@ -628,7 +646,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
628 | 646 | ||
629 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 647 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
630 | 648 | ||
631 | if (local->scan_sdata == sdata) | 649 | if (rcu_access_pointer(local->scan_sdata) == sdata) |
632 | ieee80211_scan_cancel(local); | 650 | ieee80211_scan_cancel(local); |
633 | 651 | ||
634 | /* | 652 | /* |
@@ -735,6 +753,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
735 | if (local->monitors == 0) { | 753 | if (local->monitors == 0) { |
736 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 754 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
737 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 755 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
756 | ieee80211_del_virtual_monitor(local); | ||
738 | } | 757 | } |
739 | 758 | ||
740 | ieee80211_adjust_monitor_flags(sdata, -1); | 759 | ieee80211_adjust_monitor_flags(sdata, -1); |
@@ -808,6 +827,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
808 | } | 827 | } |
809 | } | 828 | } |
810 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 829 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
830 | |||
831 | if (local->monitors == local->open_count && local->monitors > 0) | ||
832 | ieee80211_add_virtual_monitor(local); | ||
811 | } | 833 | } |
812 | 834 | ||
813 | static int ieee80211_stop(struct net_device *dev) | 835 | static int ieee80211_stop(struct net_device *dev) |
@@ -1373,7 +1395,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1373 | } | 1395 | } |
1374 | 1396 | ||
1375 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1397 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1376 | struct net_device **new_dev, enum nl80211_iftype type, | 1398 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1377 | struct vif_params *params) | 1399 | struct vif_params *params) |
1378 | { | 1400 | { |
1379 | struct net_device *ndev; | 1401 | struct net_device *ndev; |
@@ -1463,8 +1485,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1463 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1485 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
1464 | mutex_unlock(&local->iflist_mtx); | 1486 | mutex_unlock(&local->iflist_mtx); |
1465 | 1487 | ||
1466 | if (new_dev) | 1488 | if (new_wdev) |
1467 | *new_dev = ndev; | 1489 | *new_wdev = &sdata->wdev; |
1468 | 1490 | ||
1469 | return 0; | 1491 | return 0; |
1470 | 1492 | ||
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..cef0c9e79aba 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 | ||
@@ -1364,6 +1360,17 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1364 | } | 1360 | } |
1365 | mutex_unlock(&local->sta_mtx); | 1361 | mutex_unlock(&local->sta_mtx); |
1366 | 1362 | ||
1363 | /* | ||
1364 | * if we want to get out of ps before disassoc (why?) we have | ||
1365 | * to do it before sending disassoc, as otherwise the null-packet | ||
1366 | * won't be valid. | ||
1367 | */ | ||
1368 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1369 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
1370 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
1371 | } | ||
1372 | local->ps_sdata = NULL; | ||
1373 | |||
1367 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 1374 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ |
1368 | if (tx) | 1375 | if (tx) |
1369 | drv_flush(local, false); | 1376 | drv_flush(local, false); |
@@ -1399,12 +1406,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1399 | del_timer_sync(&local->dynamic_ps_timer); | 1406 | del_timer_sync(&local->dynamic_ps_timer); |
1400 | cancel_work_sync(&local->dynamic_ps_enable_work); | 1407 | cancel_work_sync(&local->dynamic_ps_enable_work); |
1401 | 1408 | ||
1402 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1403 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
1404 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
1405 | } | ||
1406 | local->ps_sdata = NULL; | ||
1407 | |||
1408 | /* Disable ARP filtering */ | 1409 | /* Disable ARP filtering */ |
1409 | if (sdata->vif.bss_conf.arp_filter_enabled) { | 1410 | if (sdata->vif.bss_conf.arp_filter_enabled) { |
1410 | sdata->vif.bss_conf.arp_filter_enabled = false; | 1411 | sdata->vif.bss_conf.arp_filter_enabled = false; |
@@ -2435,14 +2436,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2435 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, | 2436 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, |
2436 | ifmgd->aid); | 2437 | ifmgd->aid); |
2437 | 2438 | ||
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) { | 2439 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { |
2447 | if (directed_tim) { | 2440 | if (directed_tim) { |
2448 | if (local->hw.conf.dynamic_ps_timeout > 0) { | 2441 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
@@ -2473,6 +2466,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2473 | ifmgd->beacon_crc = ncrc; | 2466 | ifmgd->beacon_crc = ncrc; |
2474 | ifmgd->beacon_crc_valid = true; | 2467 | ifmgd->beacon_crc_valid = true; |
2475 | 2468 | ||
2469 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | ||
2470 | true); | ||
2471 | |||
2472 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2473 | elems.wmm_param_len)) | ||
2474 | changed |= BSS_CHANGED_QOS; | ||
2475 | |||
2476 | if (elems.erp_info && elems.erp_info_len >= 1) { | 2476 | if (elems.erp_info && elems.erp_info_len >= 1) { |
2477 | erp_valid = true; | 2477 | erp_valid = true; |
2478 | erp_value = elems.erp_info[0]; | 2478 | erp_value = elems.erp_info[0]; |
@@ -2974,7 +2974,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2974 | /* scan finished notification */ | 2974 | /* scan finished notification */ |
2975 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | 2975 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) |
2976 | { | 2976 | { |
2977 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 2977 | struct ieee80211_sub_if_data *sdata; |
2978 | 2978 | ||
2979 | /* Restart STA timers */ | 2979 | /* Restart STA timers */ |
2980 | rcu_read_lock(); | 2980 | rcu_read_lock(); |
@@ -3132,9 +3132,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3132 | 3132 | ||
3133 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); | 3133 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); |
3134 | 3134 | ||
3135 | /* tell driver about BSSID and basic rates */ | 3135 | /* set timing information */ |
3136 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | ||
3137 | sdata->vif.bss_conf.sync_tsf = cbss->tsf; | ||
3138 | sdata->vif.bss_conf.sync_device_ts = bss->device_ts; | ||
3139 | |||
3140 | /* tell driver about BSSID, basic rates and timing */ | ||
3136 | ieee80211_bss_info_change_notify(sdata, | 3141 | ieee80211_bss_info_change_notify(sdata, |
3137 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES); | 3142 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | |
3143 | BSS_CHANGED_BEACON_INT); | ||
3138 | 3144 | ||
3139 | if (assoc) | 3145 | if (assoc) |
3140 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3146 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index b0fb6a2b89ad..635c3250c668 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); |
@@ -324,6 +324,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
324 | container_of(work, struct ieee80211_roc_work, work.work); | 324 | container_of(work, struct ieee80211_roc_work, work.work); |
325 | struct ieee80211_sub_if_data *sdata = roc->sdata; | 325 | struct ieee80211_sub_if_data *sdata = roc->sdata; |
326 | struct ieee80211_local *local = sdata->local; | 326 | struct ieee80211_local *local = sdata->local; |
327 | bool started; | ||
327 | 328 | ||
328 | mutex_lock(&local->mtx); | 329 | mutex_lock(&local->mtx); |
329 | 330 | ||
@@ -366,9 +367,10 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
366 | /* finish this ROC */ | 367 | /* finish this ROC */ |
367 | finish: | 368 | finish: |
368 | list_del(&roc->list); | 369 | list_del(&roc->list); |
370 | started = roc->started; | ||
369 | ieee80211_roc_notify_destroy(roc); | 371 | ieee80211_roc_notify_destroy(roc); |
370 | 372 | ||
371 | if (roc->started) { | 373 | if (started) { |
372 | drv_flush(local, false); | 374 | drv_flush(local, false); |
373 | 375 | ||
374 | local->tmp_channel = NULL; | 376 | local->tmp_channel = NULL; |
@@ -379,7 +381,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
379 | 381 | ||
380 | ieee80211_recalc_idle(local); | 382 | ieee80211_recalc_idle(local); |
381 | 383 | ||
382 | if (roc->started) | 384 | if (started) |
383 | ieee80211_start_next_roc(local); | 385 | ieee80211_start_next_roc(local); |
384 | } | 386 | } |
385 | 387 | ||
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 67edd69e8421..0cb4edee6af5 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 267b2940fadd..bcaee5d12839 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; |
@@ -164,52 +165,47 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
164 | return bss; | 165 | return bss; |
165 | } | 166 | } |
166 | 167 | ||
167 | ieee80211_rx_result | 168 | void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) |
168 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
169 | { | 169 | { |
170 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 170 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); |
171 | struct ieee80211_mgmt *mgmt; | 171 | struct ieee80211_sub_if_data *sdata1, *sdata2; |
172 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
172 | struct ieee80211_bss *bss; | 173 | struct ieee80211_bss *bss; |
173 | u8 *elements; | 174 | u8 *elements; |
174 | struct ieee80211_channel *channel; | 175 | struct ieee80211_channel *channel; |
175 | size_t baselen; | 176 | size_t baselen; |
176 | int freq; | 177 | int freq; |
177 | __le16 fc; | 178 | bool beacon; |
178 | bool presp, beacon = false; | ||
179 | struct ieee802_11_elems elems; | 179 | struct ieee802_11_elems elems; |
180 | 180 | ||
181 | if (skb->len < 2) | 181 | if (skb->len < 24 || |
182 | return RX_DROP_UNUSABLE; | 182 | (!ieee80211_is_probe_resp(mgmt->frame_control) && |
183 | 183 | !ieee80211_is_beacon(mgmt->frame_control))) | |
184 | mgmt = (struct ieee80211_mgmt *) skb->data; | 184 | return; |
185 | fc = mgmt->frame_control; | ||
186 | 185 | ||
187 | if (ieee80211_is_ctl(fc)) | 186 | sdata1 = rcu_dereference(local->scan_sdata); |
188 | return RX_CONTINUE; | 187 | sdata2 = rcu_dereference(local->sched_scan_sdata); |
189 | 188 | ||
190 | if (skb->len < 24) | 189 | if (likely(!sdata1 && !sdata2)) |
191 | return RX_CONTINUE; | 190 | return; |
192 | 191 | ||
193 | presp = ieee80211_is_probe_resp(fc); | 192 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { |
194 | if (presp) { | ||
195 | /* ignore ProbeResp to foreign address */ | 193 | /* ignore ProbeResp to foreign address */ |
196 | if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) | 194 | if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && |
197 | return RX_DROP_MONITOR; | 195 | (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr))) |
196 | return; | ||
198 | 197 | ||
199 | presp = true; | ||
200 | elements = mgmt->u.probe_resp.variable; | 198 | elements = mgmt->u.probe_resp.variable; |
201 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | 199 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); |
200 | beacon = false; | ||
202 | } else { | 201 | } else { |
203 | beacon = ieee80211_is_beacon(fc); | ||
204 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | 202 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
205 | elements = mgmt->u.beacon.variable; | 203 | elements = mgmt->u.beacon.variable; |
204 | beacon = true; | ||
206 | } | 205 | } |
207 | 206 | ||
208 | if (!presp && !beacon) | ||
209 | return RX_CONTINUE; | ||
210 | |||
211 | if (baselen > skb->len) | 207 | if (baselen > skb->len) |
212 | return RX_DROP_MONITOR; | 208 | return; |
213 | 209 | ||
214 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 210 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
215 | 211 | ||
@@ -219,22 +215,16 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
219 | else | 215 | else |
220 | freq = rx_status->freq; | 216 | freq = rx_status->freq; |
221 | 217 | ||
222 | channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); | 218 | channel = ieee80211_get_channel(local->hw.wiphy, freq); |
223 | 219 | ||
224 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 220 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
225 | return RX_DROP_MONITOR; | 221 | return; |
226 | 222 | ||
227 | bss = ieee80211_bss_info_update(sdata->local, rx_status, | 223 | bss = ieee80211_bss_info_update(local, rx_status, |
228 | mgmt, skb->len, &elems, | 224 | mgmt, skb->len, &elems, |
229 | channel, beacon); | 225 | channel, beacon); |
230 | if (bss) | 226 | if (bss) |
231 | ieee80211_rx_bss_put(sdata->local, bss); | 227 | ieee80211_rx_bss_put(local, bss); |
232 | |||
233 | if (channel == sdata->local->oper_channel) | ||
234 | return RX_CONTINUE; | ||
235 | |||
236 | dev_kfree_skb(skb); | ||
237 | return RX_QUEUED; | ||
238 | } | 228 | } |
239 | 229 | ||
240 | /* return false if no more work */ | 230 | /* return false if no more work */ |
@@ -292,7 +282,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
292 | return; | 282 | return; |
293 | 283 | ||
294 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 284 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
295 | int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); | 285 | int rc; |
286 | |||
287 | rc = drv_hw_scan(local, | ||
288 | rcu_dereference_protected(local->scan_sdata, | ||
289 | lockdep_is_held(&local->mtx)), | ||
290 | local->hw_scan_req); | ||
291 | |||
296 | if (rc == 0) | 292 | if (rc == 0) |
297 | return; | 293 | return; |
298 | } | 294 | } |
@@ -393,7 +389,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local) | |||
393 | if (!local->scan_req || local->scanning) | 389 | if (!local->scan_req || local->scanning) |
394 | return; | 390 | return; |
395 | 391 | ||
396 | if (!ieee80211_can_scan(local, local->scan_sdata)) | 392 | if (!ieee80211_can_scan(local, |
393 | rcu_dereference_protected( | ||
394 | local->scan_sdata, | ||
395 | lockdep_is_held(&local->mtx)))) | ||
397 | return; | 396 | return; |
398 | 397 | ||
399 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, | 398 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, |
@@ -404,9 +403,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
404 | unsigned long *next_delay) | 403 | unsigned long *next_delay) |
405 | { | 404 | { |
406 | int i; | 405 | int i; |
407 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 406 | struct ieee80211_sub_if_data *sdata; |
408 | enum ieee80211_band band = local->hw.conf.channel->band; | 407 | enum ieee80211_band band = local->hw.conf.channel->band; |
409 | 408 | ||
409 | sdata = rcu_dereference_protected(local->scan_sdata, | ||
410 | lockdep_is_held(&local->mtx));; | ||
411 | |||
410 | for (i = 0; i < local->scan_req->n_ssids; i++) | 412 | for (i = 0; i < local->scan_req->n_ssids; i++) |
411 | ieee80211_send_probe_req( | 413 | ieee80211_send_probe_req( |
412 | sdata, NULL, | 414 | sdata, NULL, |
@@ -438,7 +440,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
438 | if (!ieee80211_can_scan(local, sdata)) { | 440 | if (!ieee80211_can_scan(local, sdata)) { |
439 | /* wait for the work to finish/time out */ | 441 | /* wait for the work to finish/time out */ |
440 | local->scan_req = req; | 442 | local->scan_req = req; |
441 | local->scan_sdata = sdata; | 443 | rcu_assign_pointer(local->scan_sdata, sdata); |
442 | return 0; | 444 | return 0; |
443 | } | 445 | } |
444 | 446 | ||
@@ -472,7 +474,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
472 | } | 474 | } |
473 | 475 | ||
474 | local->scan_req = req; | 476 | local->scan_req = req; |
475 | local->scan_sdata = sdata; | 477 | rcu_assign_pointer(local->scan_sdata, sdata); |
476 | 478 | ||
477 | if (local->ops->hw_scan) { | 479 | if (local->ops->hw_scan) { |
478 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 480 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
@@ -532,7 +534,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
532 | ieee80211_recalc_idle(local); | 534 | ieee80211_recalc_idle(local); |
533 | 535 | ||
534 | local->scan_req = NULL; | 536 | local->scan_req = NULL; |
535 | local->scan_sdata = NULL; | 537 | rcu_assign_pointer(local->scan_sdata, NULL); |
536 | } | 538 | } |
537 | 539 | ||
538 | return rc; | 540 | return rc; |
@@ -719,7 +721,8 @@ void ieee80211_scan_work(struct work_struct *work) | |||
719 | 721 | ||
720 | mutex_lock(&local->mtx); | 722 | mutex_lock(&local->mtx); |
721 | 723 | ||
722 | sdata = local->scan_sdata; | 724 | sdata = rcu_dereference_protected(local->scan_sdata, |
725 | lockdep_is_held(&local->mtx)); | ||
723 | 726 | ||
724 | /* When scanning on-channel, the first-callback means completed. */ | 727 | /* When scanning on-channel, the first-callback means completed. */ |
725 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { | 728 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { |
@@ -740,7 +743,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
740 | int rc; | 743 | int rc; |
741 | 744 | ||
742 | local->scan_req = NULL; | 745 | local->scan_req = NULL; |
743 | local->scan_sdata = NULL; | 746 | rcu_assign_pointer(local->scan_sdata, NULL); |
744 | 747 | ||
745 | rc = __ieee80211_start_scan(sdata, req); | 748 | rc = __ieee80211_start_scan(sdata, req); |
746 | if (rc) { | 749 | if (rc) { |
@@ -892,7 +895,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
892 | 895 | ||
893 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { | 896 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { |
894 | if (local->ops->cancel_hw_scan) | 897 | if (local->ops->cancel_hw_scan) |
895 | drv_cancel_hw_scan(local, local->scan_sdata); | 898 | drv_cancel_hw_scan(local, |
899 | rcu_dereference_protected(local->scan_sdata, | ||
900 | lockdep_is_held(&local->mtx))); | ||
896 | goto out; | 901 | goto out; |
897 | } | 902 | } |
898 | 903 | ||
@@ -914,9 +919,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
914 | struct ieee80211_local *local = sdata->local; | 919 | struct ieee80211_local *local = sdata->local; |
915 | int ret, i; | 920 | int ret, i; |
916 | 921 | ||
917 | mutex_lock(&sdata->local->mtx); | 922 | mutex_lock(&local->mtx); |
918 | 923 | ||
919 | if (local->sched_scanning) { | 924 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
920 | ret = -EBUSY; | 925 | ret = -EBUSY; |
921 | goto out; | 926 | goto out; |
922 | } | 927 | } |
@@ -927,6 +932,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
927 | } | 932 | } |
928 | 933 | ||
929 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 934 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
935 | if (!local->hw.wiphy->bands[i]) | ||
936 | continue; | ||
937 | |||
930 | local->sched_scan_ies.ie[i] = kzalloc(2 + | 938 | local->sched_scan_ies.ie[i] = kzalloc(2 + |
931 | IEEE80211_MAX_SSID_LEN + | 939 | IEEE80211_MAX_SSID_LEN + |
932 | local->scan_ies_len + | 940 | local->scan_ies_len + |
@@ -947,7 +955,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
947 | ret = drv_sched_scan_start(local, sdata, req, | 955 | ret = drv_sched_scan_start(local, sdata, req, |
948 | &local->sched_scan_ies); | 956 | &local->sched_scan_ies); |
949 | if (ret == 0) { | 957 | if (ret == 0) { |
950 | local->sched_scanning = true; | 958 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
951 | goto out; | 959 | goto out; |
952 | } | 960 | } |
953 | 961 | ||
@@ -955,7 +963,7 @@ out_free: | |||
955 | while (i > 0) | 963 | while (i > 0) |
956 | kfree(local->sched_scan_ies.ie[--i]); | 964 | kfree(local->sched_scan_ies.ie[--i]); |
957 | out: | 965 | out: |
958 | mutex_unlock(&sdata->local->mtx); | 966 | mutex_unlock(&local->mtx); |
959 | return ret; | 967 | return ret; |
960 | } | 968 | } |
961 | 969 | ||
@@ -964,22 +972,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
964 | struct ieee80211_local *local = sdata->local; | 972 | struct ieee80211_local *local = sdata->local; |
965 | int ret = 0, i; | 973 | int ret = 0, i; |
966 | 974 | ||
967 | mutex_lock(&sdata->local->mtx); | 975 | mutex_lock(&local->mtx); |
968 | 976 | ||
969 | if (!local->ops->sched_scan_stop) { | 977 | if (!local->ops->sched_scan_stop) { |
970 | ret = -ENOTSUPP; | 978 | ret = -ENOTSUPP; |
971 | goto out; | 979 | goto out; |
972 | } | 980 | } |
973 | 981 | ||
974 | if (local->sched_scanning) { | 982 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
975 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 983 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
976 | kfree(local->sched_scan_ies.ie[i]); | 984 | kfree(local->sched_scan_ies.ie[i]); |
977 | 985 | ||
978 | drv_sched_scan_stop(local, sdata); | 986 | drv_sched_scan_stop(local, sdata); |
979 | local->sched_scanning = false; | 987 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
980 | } | 988 | } |
981 | out: | 989 | out: |
982 | mutex_unlock(&sdata->local->mtx); | 990 | mutex_unlock(&local->mtx); |
983 | 991 | ||
984 | return ret; | 992 | return ret; |
985 | } | 993 | } |
@@ -1003,7 +1011,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1003 | 1011 | ||
1004 | mutex_lock(&local->mtx); | 1012 | mutex_lock(&local->mtx); |
1005 | 1013 | ||
1006 | if (!local->sched_scanning) { | 1014 | if (!rcu_access_pointer(local->sched_scan_sdata)) { |
1007 | mutex_unlock(&local->mtx); | 1015 | mutex_unlock(&local->mtx); |
1008 | return; | 1016 | return; |
1009 | } | 1017 | } |
@@ -1011,7 +1019,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1011 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 1019 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1012 | kfree(local->sched_scan_ies.ie[i]); | 1020 | kfree(local->sched_scan_ies.ie[i]); |
1013 | 1021 | ||
1014 | local->sched_scanning = false; | 1022 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
1015 | 1023 | ||
1016 | mutex_unlock(&local->mtx); | 1024 | mutex_unlock(&local->mtx); |
1017 | 1025 | ||
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..acf712ffb5e6 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; |
@@ -1817,6 +1824,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1817 | /* RA TA mDA mSA AE:DA SA */ | 1824 | /* RA TA mDA mSA AE:DA SA */ |
1818 | mesh_da = mppath->mpp; | 1825 | mesh_da = mppath->mpp; |
1819 | is_mesh_mcast = 0; | 1826 | is_mesh_mcast = 0; |
1827 | } else if (mpath) { | ||
1828 | mesh_da = mpath->dst; | ||
1829 | is_mesh_mcast = 0; | ||
1820 | } else { | 1830 | } else { |
1821 | /* DA TA mSA AE:SA */ | 1831 | /* DA TA mSA AE:SA */ |
1822 | mesh_da = bcast; | 1832 | mesh_da = bcast; |
@@ -2714,7 +2724,7 @@ EXPORT_SYMBOL(ieee80211_get_buffered_bc); | |||
2714 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | 2724 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
2715 | struct sk_buff *skb, int tid) | 2725 | struct sk_buff *skb, int tid) |
2716 | { | 2726 | { |
2717 | int ac = ieee802_1d_to_ac[tid]; | 2727 | int ac = ieee802_1d_to_ac[tid & 7]; |
2718 | 2728 | ||
2719 | skb_set_mac_header(skb, 0); | 2729 | skb_set_mac_header(skb, 0); |
2720 | skb_set_network_header(skb, 0); | 2730 | skb_set_network_header(skb, 0); |
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 | ||