diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
commit | 38a00840638b4932152bca48098dbfa069d942a2 (patch) | |
tree | dd12897854f6df8aac237d5fd46551c74be8153a /net/mac80211 | |
parent | 391e5c22f5f4e55817f8ba18a08ea717ed2d4a1f (diff) | |
parent | 2f8684ce7a47c91da7e0ccba2686277c103d02b6 (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/cfg.c | 24 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 16 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 22 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 11 | ||||
-rw-r--r-- | net/mac80211/iface.c | 258 | ||||
-rw-r--r-- | net/mac80211/main.c | 17 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 4 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 28 | ||||
-rw-r--r-- | net/mac80211/trace.h | 7 | ||||
-rw-r--r-- | net/mac80211/tx.c | 16 | ||||
-rw-r--r-- | net/mac80211/util.c | 49 |
11 files changed, 258 insertions, 194 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c2a2dcbfdf01..ccbe2413142a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2668,8 +2668,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2668 | tf->u.setup_req.capability = | 2668 | tf->u.setup_req.capability = |
2669 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2669 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2670 | 2670 | ||
2671 | ieee80211_add_srates_ie(&sdata->vif, skb, false); | 2671 | ieee80211_add_srates_ie(sdata, skb, false); |
2672 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); | 2672 | ieee80211_add_ext_srates_ie(sdata, skb, false); |
2673 | ieee80211_tdls_add_ext_capab(skb); | 2673 | ieee80211_tdls_add_ext_capab(skb); |
2674 | break; | 2674 | break; |
2675 | case WLAN_TDLS_SETUP_RESPONSE: | 2675 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2682,8 +2682,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2682 | tf->u.setup_resp.capability = | 2682 | tf->u.setup_resp.capability = |
2683 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2683 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2684 | 2684 | ||
2685 | ieee80211_add_srates_ie(&sdata->vif, skb, false); | 2685 | ieee80211_add_srates_ie(sdata, skb, false); |
2686 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); | 2686 | ieee80211_add_ext_srates_ie(sdata, skb, false); |
2687 | ieee80211_tdls_add_ext_capab(skb); | 2687 | ieee80211_tdls_add_ext_capab(skb); |
2688 | break; | 2688 | break; |
2689 | case WLAN_TDLS_SETUP_CONFIRM: | 2689 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2743,8 +2743,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2743 | mgmt->u.action.u.tdls_discover_resp.capability = | 2743 | mgmt->u.action.u.tdls_discover_resp.capability = |
2744 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2744 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2745 | 2745 | ||
2746 | ieee80211_add_srates_ie(&sdata->vif, skb, false); | 2746 | ieee80211_add_srates_ie(sdata, skb, false); |
2747 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); | 2747 | ieee80211_add_ext_srates_ie(sdata, skb, false); |
2748 | ieee80211_tdls_add_ext_capab(skb); | 2748 | ieee80211_tdls_add_ext_capab(skb); |
2749 | break; | 2749 | break; |
2750 | default: | 2750 | default: |
@@ -2980,14 +2980,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
2980 | return 0; | 2980 | return 0; |
2981 | } | 2981 | } |
2982 | 2982 | ||
2983 | static struct ieee80211_channel * | 2983 | static void ieee80211_set_monitor_enabled(struct wiphy *wiphy, bool enabled) |
2984 | ieee80211_wiphy_get_channel(struct wiphy *wiphy, | ||
2985 | enum nl80211_channel_type *type) | ||
2986 | { | 2984 | { |
2987 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2985 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2988 | 2986 | ||
2989 | *type = local->_oper_channel_type; | 2987 | if (enabled) |
2990 | return local->oper_channel; | 2988 | WARN_ON(ieee80211_add_virtual_monitor(local)); |
2989 | else | ||
2990 | ieee80211_del_virtual_monitor(local); | ||
2991 | } | 2991 | } |
2992 | 2992 | ||
2993 | #ifdef CONFIG_PM | 2993 | #ifdef CONFIG_PM |
@@ -3063,8 +3063,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3063 | .tdls_oper = ieee80211_tdls_oper, | 3063 | .tdls_oper = ieee80211_tdls_oper, |
3064 | .tdls_mgmt = ieee80211_tdls_mgmt, | 3064 | .tdls_mgmt = ieee80211_tdls_mgmt, |
3065 | .probe_client = ieee80211_probe_client, | 3065 | .probe_client = ieee80211_probe_client, |
3066 | .get_channel = ieee80211_wiphy_get_channel, | ||
3067 | .set_noack_map = ieee80211_set_noack_map, | 3066 | .set_noack_map = ieee80211_set_noack_map, |
3067 | .set_monitor_enabled = ieee80211_set_monitor_enabled, | ||
3068 | #ifdef CONFIG_PM | 3068 | #ifdef CONFIG_PM |
3069 | .set_wakeup = ieee80211_set_wakeup, | 3069 | .set_wakeup = ieee80211_set_wakeup, |
3070 | #endif | 3070 | #endif |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 7932767bb482..090d08ff22c4 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -283,6 +283,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
283 | 283 | ||
284 | lockdep_assert_held(&sdata->local->key_mtx); | 284 | lockdep_assert_held(&sdata->local->key_mtx); |
285 | 285 | ||
286 | if (sdata->debugfs.default_unicast_key) { | ||
287 | debugfs_remove(sdata->debugfs.default_unicast_key); | ||
288 | sdata->debugfs.default_unicast_key = NULL; | ||
289 | } | ||
290 | |||
286 | if (sdata->default_unicast_key) { | 291 | if (sdata->default_unicast_key) { |
287 | key = key_mtx_dereference(sdata->local, | 292 | key = key_mtx_dereference(sdata->local, |
288 | sdata->default_unicast_key); | 293 | sdata->default_unicast_key); |
@@ -290,9 +295,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
290 | sdata->debugfs.default_unicast_key = | 295 | sdata->debugfs.default_unicast_key = |
291 | debugfs_create_symlink("default_unicast_key", | 296 | debugfs_create_symlink("default_unicast_key", |
292 | sdata->debugfs.dir, buf); | 297 | sdata->debugfs.dir, buf); |
293 | } else { | 298 | } |
294 | debugfs_remove(sdata->debugfs.default_unicast_key); | 299 | |
295 | sdata->debugfs.default_unicast_key = NULL; | 300 | if (sdata->debugfs.default_multicast_key) { |
301 | debugfs_remove(sdata->debugfs.default_multicast_key); | ||
302 | sdata->debugfs.default_multicast_key = NULL; | ||
296 | } | 303 | } |
297 | 304 | ||
298 | if (sdata->default_multicast_key) { | 305 | if (sdata->default_multicast_key) { |
@@ -302,9 +309,6 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
302 | sdata->debugfs.default_multicast_key = | 309 | sdata->debugfs.default_multicast_key = |
303 | debugfs_create_symlink("default_multicast_key", | 310 | debugfs_create_symlink("default_multicast_key", |
304 | sdata->debugfs.dir, buf); | 311 | sdata->debugfs.dir, buf); |
305 | } else { | ||
306 | debugfs_remove(sdata->debugfs.default_multicast_key); | ||
307 | sdata->debugfs.default_multicast_key = NULL; | ||
308 | } | 312 | } |
309 | } | 313 | } |
310 | 314 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 44e8c1242781..df9203199102 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -27,14 +27,6 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | |||
27 | local->ops->tx(&local->hw, skb); | 27 | local->ops->tx(&local->hw, skb); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline void drv_tx_frags(struct ieee80211_local *local, | ||
31 | struct ieee80211_vif *vif, | ||
32 | struct ieee80211_sta *sta, | ||
33 | struct sk_buff_head *skbs) | ||
34 | { | ||
35 | local->ops->tx_frags(&local->hw, vif, sta, skbs); | ||
36 | } | ||
37 | |||
38 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, | 30 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, |
39 | u32 sset, u8 *data) | 31 | u32 sset, u8 *data) |
40 | { | 32 | { |
@@ -860,4 +852,18 @@ static inline int drv_get_rssi(struct ieee80211_local *local, | |||
860 | 852 | ||
861 | return ret; | 853 | return ret; |
862 | } | 854 | } |
855 | |||
856 | static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, | ||
857 | struct ieee80211_sub_if_data *sdata) | ||
858 | { | ||
859 | might_sleep(); | ||
860 | |||
861 | check_sdata_in_driver(sdata); | ||
862 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | ||
863 | |||
864 | trace_drv_mgd_prepare_tx(local, sdata); | ||
865 | if (local->ops->mgd_prepare_tx) | ||
866 | local->ops->mgd_prepare_tx(&local->hw, &sdata->vif); | ||
867 | trace_drv_return_void(local); | ||
868 | } | ||
863 | #endif /* __MAC80211_DRIVER_OPS */ | 869 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f834a005e1c5..e0423f8c0ce1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1284,7 +1284,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1284 | enum nl80211_iftype type); | 1284 | enum nl80211_iftype type); |
1285 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 1285 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
1286 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 1286 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
1287 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | ||
1288 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1287 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1289 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1288 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1290 | const int offset); | 1289 | const int offset); |
@@ -1481,6 +1480,16 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1481 | struct ieee80211_channel *channel, | 1480 | struct ieee80211_channel *channel, |
1482 | enum nl80211_channel_type channel_type, | 1481 | enum nl80211_channel_type channel_type, |
1483 | u16 prot_mode); | 1482 | u16 prot_mode); |
1483 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | ||
1484 | u32 cap); | ||
1485 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | ||
1486 | struct sk_buff *skb, bool need_basic); | ||
1487 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | ||
1488 | struct sk_buff *skb, bool need_basic); | ||
1489 | |||
1490 | /* virtual monitor */ | ||
1491 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local); | ||
1492 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local); | ||
1484 | 1493 | ||
1485 | /* channel management */ | 1494 | /* channel management */ |
1486 | enum ieee80211_chan_mode { | 1495 | enum ieee80211_chan_mode { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 58c2ab3d483a..fbef7a1ada7a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -43,6 +43,127 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | 45 | ||
46 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
47 | const char *reason) | ||
48 | { | ||
49 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
50 | return 0; | ||
51 | |||
52 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
53 | return IEEE80211_CONF_CHANGE_IDLE; | ||
54 | } | ||
55 | |||
56 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
57 | { | ||
58 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
59 | return 0; | ||
60 | |||
61 | drv_flush(local, false); | ||
62 | |||
63 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
64 | return IEEE80211_CONF_CHANGE_IDLE; | ||
65 | } | ||
66 | |||
67 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
68 | { | ||
69 | struct ieee80211_sub_if_data *sdata; | ||
70 | int count = 0; | ||
71 | bool working = false, scanning = false; | ||
72 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
73 | struct ieee80211_roc_work *roc; | ||
74 | |||
75 | #ifdef CONFIG_PROVE_LOCKING | ||
76 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
77 | !lockdep_is_held(&local->iflist_mtx)); | ||
78 | #endif | ||
79 | lockdep_assert_held(&local->mtx); | ||
80 | |||
81 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
82 | if (!ieee80211_sdata_running(sdata)) { | ||
83 | sdata->vif.bss_conf.idle = true; | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
88 | |||
89 | /* do not count disabled managed interfaces */ | ||
90 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
91 | !sdata->u.mgd.associated && | ||
92 | !sdata->u.mgd.auth_data && | ||
93 | !sdata->u.mgd.assoc_data) { | ||
94 | sdata->vif.bss_conf.idle = true; | ||
95 | continue; | ||
96 | } | ||
97 | /* do not count unused IBSS interfaces */ | ||
98 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
99 | !sdata->u.ibss.ssid_len) { | ||
100 | sdata->vif.bss_conf.idle = true; | ||
101 | continue; | ||
102 | } | ||
103 | /* count everything else */ | ||
104 | sdata->vif.bss_conf.idle = false; | ||
105 | count++; | ||
106 | } | ||
107 | |||
108 | if (!local->ops->remain_on_channel) { | ||
109 | list_for_each_entry(roc, &local->roc_list, list) { | ||
110 | working = true; | ||
111 | roc->sdata->vif.bss_conf.idle = false; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (local->scan_sdata && | ||
116 | !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
117 | scanning = true; | ||
118 | local->scan_sdata->vif.bss_conf.idle = false; | ||
119 | } | ||
120 | |||
121 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
122 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
123 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
124 | continue; | ||
125 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
126 | continue; | ||
127 | if (!ieee80211_sdata_running(sdata)) | ||
128 | continue; | ||
129 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
130 | } | ||
131 | |||
132 | if (working || scanning) | ||
133 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
134 | else | ||
135 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
136 | |||
137 | if (count) | ||
138 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
139 | else | ||
140 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
141 | |||
142 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
143 | |||
144 | if (working) | ||
145 | return ieee80211_idle_off(local, "working"); | ||
146 | if (scanning) | ||
147 | return ieee80211_idle_off(local, "scanning"); | ||
148 | if (!count) | ||
149 | return ieee80211_idle_on(local); | ||
150 | else | ||
151 | return ieee80211_idle_off(local, "in use"); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
157 | { | ||
158 | u32 chg; | ||
159 | |||
160 | mutex_lock(&local->iflist_mtx); | ||
161 | chg = __ieee80211_recalc_idle(local); | ||
162 | mutex_unlock(&local->iflist_mtx); | ||
163 | if (chg) | ||
164 | ieee80211_hw_config(local, chg); | ||
165 | } | ||
166 | |||
46 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 167 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
47 | { | 168 | { |
48 | int meshhdrlen; | 169 | int meshhdrlen; |
@@ -209,7 +330,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
209 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 330 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
210 | } | 331 | } |
211 | 332 | ||
212 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 333 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
213 | { | 334 | { |
214 | struct ieee80211_sub_if_data *sdata; | 335 | struct ieee80211_sub_if_data *sdata; |
215 | int ret; | 336 | int ret; |
@@ -250,7 +371,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
250 | return 0; | 371 | return 0; |
251 | } | 372 | } |
252 | 373 | ||
253 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 374 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
254 | { | 375 | { |
255 | struct ieee80211_sub_if_data *sdata; | 376 | struct ieee80211_sub_if_data *sdata; |
256 | 377 | ||
@@ -366,12 +487,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
366 | break; | 487 | break; |
367 | } | 488 | } |
368 | 489 | ||
369 | if (local->monitors == 0 && local->open_count == 0) { | ||
370 | res = ieee80211_add_virtual_monitor(local); | ||
371 | if (res) | ||
372 | goto err_stop; | ||
373 | } | ||
374 | |||
375 | /* must be before the call to ieee80211_configure_filter */ | 490 | /* must be before the call to ieee80211_configure_filter */ |
376 | local->monitors++; | 491 | local->monitors++; |
377 | if (local->monitors == 1) { | 492 | if (local->monitors == 1) { |
@@ -386,8 +501,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
386 | break; | 501 | break; |
387 | default: | 502 | default: |
388 | if (coming_up) { | 503 | if (coming_up) { |
389 | ieee80211_del_virtual_monitor(local); | ||
390 | |||
391 | res = drv_add_interface(local, sdata); | 504 | res = drv_add_interface(local, sdata); |
392 | if (res) | 505 | if (res) |
393 | goto err_stop; | 506 | goto err_stop; |
@@ -622,7 +735,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
622 | if (local->monitors == 0) { | 735 | if (local->monitors == 0) { |
623 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 736 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
624 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 737 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
625 | ieee80211_del_virtual_monitor(local); | ||
626 | } | 738 | } |
627 | 739 | ||
628 | ieee80211_adjust_monitor_flags(sdata, -1); | 740 | ieee80211_adjust_monitor_flags(sdata, -1); |
@@ -696,9 +808,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
696 | } | 808 | } |
697 | } | 809 | } |
698 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 810 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
699 | |||
700 | if (local->monitors == local->open_count && local->monitors > 0) | ||
701 | ieee80211_add_virtual_monitor(local); | ||
702 | } | 811 | } |
703 | 812 | ||
704 | static int ieee80211_stop(struct net_device *dev) | 813 | static int ieee80211_stop(struct net_device *dev) |
@@ -1403,127 +1512,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1403 | list_del(&unreg_list); | 1512 | list_del(&unreg_list); |
1404 | } | 1513 | } |
1405 | 1514 | ||
1406 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
1407 | const char *reason) | ||
1408 | { | ||
1409 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
1410 | return 0; | ||
1411 | |||
1412 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
1413 | return IEEE80211_CONF_CHANGE_IDLE; | ||
1414 | } | ||
1415 | |||
1416 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
1417 | { | ||
1418 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
1419 | return 0; | ||
1420 | |||
1421 | drv_flush(local, false); | ||
1422 | |||
1423 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
1424 | return IEEE80211_CONF_CHANGE_IDLE; | ||
1425 | } | ||
1426 | |||
1427 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
1428 | { | ||
1429 | struct ieee80211_sub_if_data *sdata; | ||
1430 | int count = 0; | ||
1431 | bool working = false, scanning = false; | ||
1432 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
1433 | struct ieee80211_roc_work *roc; | ||
1434 | |||
1435 | #ifdef CONFIG_PROVE_LOCKING | ||
1436 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
1437 | !lockdep_is_held(&local->iflist_mtx)); | ||
1438 | #endif | ||
1439 | lockdep_assert_held(&local->mtx); | ||
1440 | |||
1441 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1442 | if (!ieee80211_sdata_running(sdata)) { | ||
1443 | sdata->vif.bss_conf.idle = true; | ||
1444 | continue; | ||
1445 | } | ||
1446 | |||
1447 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
1448 | |||
1449 | /* do not count disabled managed interfaces */ | ||
1450 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1451 | !sdata->u.mgd.associated && | ||
1452 | !sdata->u.mgd.auth_data && | ||
1453 | !sdata->u.mgd.assoc_data) { | ||
1454 | sdata->vif.bss_conf.idle = true; | ||
1455 | continue; | ||
1456 | } | ||
1457 | /* do not count unused IBSS interfaces */ | ||
1458 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
1459 | !sdata->u.ibss.ssid_len) { | ||
1460 | sdata->vif.bss_conf.idle = true; | ||
1461 | continue; | ||
1462 | } | ||
1463 | /* count everything else */ | ||
1464 | sdata->vif.bss_conf.idle = false; | ||
1465 | count++; | ||
1466 | } | ||
1467 | |||
1468 | if (!local->ops->remain_on_channel) { | ||
1469 | list_for_each_entry(roc, &local->roc_list, list) { | ||
1470 | working = true; | ||
1471 | roc->sdata->vif.bss_conf.idle = false; | ||
1472 | } | ||
1473 | } | ||
1474 | |||
1475 | if (local->scan_sdata && | ||
1476 | !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
1477 | scanning = true; | ||
1478 | local->scan_sdata->vif.bss_conf.idle = false; | ||
1479 | } | ||
1480 | |||
1481 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1482 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1483 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1484 | continue; | ||
1485 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
1486 | continue; | ||
1487 | if (!ieee80211_sdata_running(sdata)) | ||
1488 | continue; | ||
1489 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
1490 | } | ||
1491 | |||
1492 | if (working || scanning) | ||
1493 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1494 | else | ||
1495 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1496 | |||
1497 | if (count) | ||
1498 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1499 | else | ||
1500 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1501 | |||
1502 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
1503 | |||
1504 | if (working) | ||
1505 | return ieee80211_idle_off(local, "working"); | ||
1506 | if (scanning) | ||
1507 | return ieee80211_idle_off(local, "scanning"); | ||
1508 | if (!count) | ||
1509 | return ieee80211_idle_on(local); | ||
1510 | else | ||
1511 | return ieee80211_idle_off(local, "in use"); | ||
1512 | |||
1513 | return 0; | ||
1514 | } | ||
1515 | |||
1516 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
1517 | { | ||
1518 | u32 chg; | ||
1519 | |||
1520 | mutex_lock(&local->iflist_mtx); | ||
1521 | chg = __ieee80211_recalc_idle(local); | ||
1522 | mutex_unlock(&local->iflist_mtx); | ||
1523 | if (chg) | ||
1524 | ieee80211_hw_config(local, chg); | ||
1525 | } | ||
1526 | |||
1527 | static int netdev_notify(struct notifier_block *nb, | 1515 | static int netdev_notify(struct notifier_block *nb, |
1528 | unsigned long state, | 1516 | unsigned long state, |
1529 | void *ndev) | 1517 | void *ndev) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0b040fb73673..c794101f8987 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -587,7 +587,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
587 | 587 | ||
588 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); | 588 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); |
589 | 589 | ||
590 | BUG_ON(!ops->tx && !ops->tx_frags); | 590 | BUG_ON(!ops->tx); |
591 | BUG_ON(!ops->start); | 591 | BUG_ON(!ops->start); |
592 | BUG_ON(!ops->stop); | 592 | BUG_ON(!ops->stop); |
593 | BUG_ON(!ops->config); | 593 | BUG_ON(!ops->config); |
@@ -688,7 +688,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
688 | int result, i; | 688 | int result, i; |
689 | enum ieee80211_band band; | 689 | enum ieee80211_band band; |
690 | int channels, max_bitrates; | 690 | int channels, max_bitrates; |
691 | bool supp_ht; | 691 | bool supp_ht, supp_vht; |
692 | netdev_features_t feature_whitelist; | 692 | netdev_features_t feature_whitelist; |
693 | static const u32 cipher_suites[] = { | 693 | static const u32 cipher_suites[] = { |
694 | /* keep WEP first, it may be removed below */ | 694 | /* keep WEP first, it may be removed below */ |
@@ -706,12 +706,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
706 | local->hw.offchannel_tx_hw_queue >= local->hw.queues)) | 706 | local->hw.offchannel_tx_hw_queue >= local->hw.queues)) |
707 | return -EINVAL; | 707 | return -EINVAL; |
708 | 708 | ||
709 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) | ||
710 | #ifdef CONFIG_PM | 709 | #ifdef CONFIG_PM |
711 | && (!local->ops->suspend || !local->ops->resume) | 710 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && |
712 | #endif | 711 | (!local->ops->suspend || !local->ops->resume)) |
713 | ) | ||
714 | return -EINVAL; | 712 | return -EINVAL; |
713 | #endif | ||
715 | 714 | ||
716 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) | 715 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) |
717 | return -EINVAL; | 716 | return -EINVAL; |
@@ -733,6 +732,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
733 | channels = 0; | 732 | channels = 0; |
734 | max_bitrates = 0; | 733 | max_bitrates = 0; |
735 | supp_ht = false; | 734 | supp_ht = false; |
735 | supp_vht = false; | ||
736 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 736 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
737 | struct ieee80211_supported_band *sband; | 737 | struct ieee80211_supported_band *sband; |
738 | 738 | ||
@@ -750,6 +750,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
750 | if (max_bitrates < sband->n_bitrates) | 750 | if (max_bitrates < sband->n_bitrates) |
751 | max_bitrates = sband->n_bitrates; | 751 | max_bitrates = sband->n_bitrates; |
752 | supp_ht = supp_ht || sband->ht_cap.ht_supported; | 752 | supp_ht = supp_ht || sband->ht_cap.ht_supported; |
753 | supp_vht = supp_vht || sband->vht_cap.vht_supported; | ||
753 | } | 754 | } |
754 | 755 | ||
755 | local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + | 756 | local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + |
@@ -825,6 +826,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
825 | if (supp_ht) | 826 | if (supp_ht) |
826 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); | 827 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); |
827 | 828 | ||
829 | if (supp_vht) | ||
830 | local->scan_ies_len += | ||
831 | 2 + sizeof(struct ieee80211_vht_capabilities); | ||
832 | |||
828 | if (!local->ops->hw_scan) { | 833 | if (!local->ops->hw_scan) { |
829 | /* For hw_scan, driver needs to set these up. */ | 834 | /* For hw_scan, driver needs to set these up. */ |
830 | local->hw.wiphy->max_scan_ssids = 4; | 835 | local->hw.wiphy->max_scan_ssids = 4; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9ad74dd87a7b..af671b984df3 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -258,8 +258,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
258 | pos = skb_put(skb, 2); | 258 | pos = skb_put(skb, 2); |
259 | memcpy(pos + 2, &plid, 2); | 259 | memcpy(pos + 2, &plid, 2); |
260 | } | 260 | } |
261 | if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || | 261 | if (ieee80211_add_srates_ie(sdata, skb, true) || |
262 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || | 262 | ieee80211_add_ext_srates_ie(sdata, skb, true) || |
263 | mesh_add_rsn_ie(skb, sdata) || | 263 | mesh_add_rsn_ie(skb, sdata) || |
264 | mesh_add_meshid_ie(skb, sdata) || | 264 | mesh_add_meshid_ie(skb, sdata) || |
265 | mesh_add_meshconf_ie(skb, sdata)) | 265 | mesh_add_meshconf_ie(skb, sdata)) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index aa69a331f374..f49f14f8ba82 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -541,6 +541,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
541 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | 541 | memcpy(pos, assoc_data->ie + offset, noffset - offset); |
542 | } | 542 | } |
543 | 543 | ||
544 | drv_mgd_prepare_tx(local, sdata); | ||
545 | |||
544 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 546 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
545 | ieee80211_tx_skb(sdata, skb); | 547 | ieee80211_tx_skb(sdata, skb); |
546 | } | 548 | } |
@@ -580,6 +582,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
580 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | 582 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
581 | IEEE80211_SKB_CB(skb)->flags |= | 583 | IEEE80211_SKB_CB(skb)->flags |= |
582 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | 584 | IEEE80211_TX_INTFL_DONT_ENCRYPT; |
585 | |||
586 | drv_mgd_prepare_tx(local, sdata); | ||
587 | |||
583 | ieee80211_tx_skb(sdata, skb); | 588 | ieee80211_tx_skb(sdata, skb); |
584 | } | 589 | } |
585 | } | 590 | } |
@@ -902,9 +907,6 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
902 | if (!mgd->associated) | 907 | if (!mgd->associated) |
903 | return false; | 908 | return false; |
904 | 909 | ||
905 | if (!mgd->associated->beacon_ies) | ||
906 | return false; | ||
907 | |||
908 | if (mgd->flags & (IEEE80211_STA_BEACON_POLL | | 910 | if (mgd->flags & (IEEE80211_STA_BEACON_POLL | |
909 | IEEE80211_STA_CONNECTION_POLL)) | 911 | IEEE80211_STA_CONNECTION_POLL)) |
910 | return false; | 912 | return false; |
@@ -1362,6 +1364,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1362 | } | 1364 | } |
1363 | mutex_unlock(&local->sta_mtx); | 1365 | mutex_unlock(&local->sta_mtx); |
1364 | 1366 | ||
1367 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | ||
1368 | if (tx) | ||
1369 | drv_flush(local, false); | ||
1370 | |||
1365 | /* deauthenticate/disassociate now */ | 1371 | /* deauthenticate/disassociate now */ |
1366 | if (tx || frame_buf) | 1372 | if (tx || frame_buf) |
1367 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, | 1373 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, |
@@ -1610,6 +1616,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1610 | { | 1616 | { |
1611 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1617 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1612 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1618 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1619 | struct cfg80211_bss *cbss; | ||
1613 | struct sk_buff *skb; | 1620 | struct sk_buff *skb; |
1614 | const u8 *ssid; | 1621 | const u8 *ssid; |
1615 | int ssid_len; | 1622 | int ssid_len; |
@@ -1619,16 +1626,22 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1619 | 1626 | ||
1620 | ASSERT_MGD_MTX(ifmgd); | 1627 | ASSERT_MGD_MTX(ifmgd); |
1621 | 1628 | ||
1622 | if (!ifmgd->associated) | 1629 | if (ifmgd->associated) |
1630 | cbss = ifmgd->associated; | ||
1631 | else if (ifmgd->auth_data) | ||
1632 | cbss = ifmgd->auth_data->bss; | ||
1633 | else if (ifmgd->assoc_data) | ||
1634 | cbss = ifmgd->assoc_data->bss; | ||
1635 | else | ||
1623 | return NULL; | 1636 | return NULL; |
1624 | 1637 | ||
1625 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1638 | ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); |
1626 | if (WARN_ON_ONCE(ssid == NULL)) | 1639 | if (WARN_ON_ONCE(ssid == NULL)) |
1627 | ssid_len = 0; | 1640 | ssid_len = 0; |
1628 | else | 1641 | else |
1629 | ssid_len = ssid[1]; | 1642 | ssid_len = ssid[1]; |
1630 | 1643 | ||
1631 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, | 1644 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, |
1632 | (u32) -1, ssid + 2, ssid_len, | 1645 | (u32) -1, ssid + 2, ssid_len, |
1633 | NULL, 0, true); | 1646 | NULL, 0, true); |
1634 | 1647 | ||
@@ -1747,6 +1760,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1747 | if (!elems.challenge) | 1760 | if (!elems.challenge) |
1748 | return; | 1761 | return; |
1749 | auth_data->expected_transaction = 4; | 1762 | auth_data->expected_transaction = 4; |
1763 | drv_mgd_prepare_tx(sdata->local, sdata); | ||
1750 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, | 1764 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, |
1751 | elems.challenge - 2, elems.challenge_len + 2, | 1765 | elems.challenge - 2, elems.challenge_len + 2, |
1752 | auth_data->bss->bssid, auth_data->bss->bssid, | 1766 | auth_data->bss->bssid, auth_data->bss->bssid, |
@@ -2630,6 +2644,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2630 | return -ETIMEDOUT; | 2644 | return -ETIMEDOUT; |
2631 | } | 2645 | } |
2632 | 2646 | ||
2647 | drv_mgd_prepare_tx(local, sdata); | ||
2648 | |||
2633 | if (auth_data->bss->proberesp_ies) { | 2649 | if (auth_data->bss->proberesp_ies) { |
2634 | sdata_info(sdata, "send auth to %pM (try %d/%d)\n", | 2650 | sdata_info(sdata, "send auth to %pM (try %d/%d)\n", |
2635 | auth_data->bss->bssid, auth_data->tries, | 2651 | auth_data->bss->bssid, auth_data->tries, |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 2e60f4acd027..e1e9d10ec2e7 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1244,6 +1244,13 @@ TRACE_EVENT(drv_get_rssi, | |||
1244 | ) | 1244 | ) |
1245 | ); | 1245 | ); |
1246 | 1246 | ||
1247 | DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, | ||
1248 | TP_PROTO(struct ieee80211_local *local, | ||
1249 | struct ieee80211_sub_if_data *sdata), | ||
1250 | |||
1251 | TP_ARGS(local, sdata) | ||
1252 | ); | ||
1253 | |||
1247 | /* | 1254 | /* |
1248 | * Tracing for API calls that drivers call. | 1255 | * Tracing for API calls that drivers call. |
1249 | */ | 1256 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ec8f53467374..c9d2175d15c1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -140,6 +140,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
140 | if (r->flags & IEEE80211_RATE_MANDATORY_A) | 140 | if (r->flags & IEEE80211_RATE_MANDATORY_A) |
141 | mrate = r->bitrate; | 141 | mrate = r->bitrate; |
142 | break; | 142 | break; |
143 | case IEEE80211_BAND_60GHZ: | ||
144 | /* TODO, for now fall through */ | ||
143 | case IEEE80211_NUM_BANDS: | 145 | case IEEE80211_NUM_BANDS: |
144 | WARN_ON(1); | 146 | WARN_ON(1); |
145 | break; | 147 | break; |
@@ -957,8 +959,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
957 | info->control.rates[1].idx = -1; | 959 | info->control.rates[1].idx = -1; |
958 | info->control.rates[2].idx = -1; | 960 | info->control.rates[2].idx = -1; |
959 | info->control.rates[3].idx = -1; | 961 | info->control.rates[3].idx = -1; |
960 | info->control.rates[4].idx = -1; | 962 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4); |
961 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); | ||
962 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 963 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
963 | } else { | 964 | } else { |
964 | hdr->frame_control &= ~morefrags; | 965 | hdr->frame_control &= ~morefrags; |
@@ -1293,11 +1294,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local, | |||
1293 | break; | 1294 | break; |
1294 | } | 1295 | } |
1295 | 1296 | ||
1296 | if (local->ops->tx_frags) | 1297 | result = ieee80211_tx_frags(local, vif, pubsta, skbs, |
1297 | drv_tx_frags(local, vif, pubsta, skbs); | 1298 | txpending); |
1298 | else | ||
1299 | result = ieee80211_tx_frags(local, vif, pubsta, skbs, | ||
1300 | txpending); | ||
1301 | 1299 | ||
1302 | ieee80211_tpt_led_trig_tx(local, fc, led_len); | 1300 | ieee80211_tpt_led_trig_tx(local, fc, led_len); |
1303 | ieee80211_led_tx(local, 1); | 1301 | ieee80211_led_tx(local, 1); |
@@ -2420,9 +2418,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2420 | *pos++ = WLAN_EID_SSID; | 2418 | *pos++ = WLAN_EID_SSID; |
2421 | *pos++ = 0x0; | 2419 | *pos++ = 0x0; |
2422 | 2420 | ||
2423 | if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || | 2421 | if (ieee80211_add_srates_ie(sdata, skb, true) || |
2424 | mesh_add_ds_params_ie(skb, sdata) || | 2422 | mesh_add_ds_params_ie(skb, sdata) || |
2425 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || | 2423 | ieee80211_add_ext_srates_ie(sdata, skb, true) || |
2426 | mesh_add_rsn_ie(skb, sdata) || | 2424 | mesh_add_rsn_ie(skb, sdata) || |
2427 | mesh_add_ht_cap_ie(skb, sdata) || | 2425 | mesh_add_ht_cap_ie(skb, sdata) || |
2428 | mesh_add_ht_oper_ie(skb, sdata) || | 2426 | mesh_add_ht_oper_ie(skb, sdata) || |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 242ecde381f6..64493a7bef1a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -268,6 +268,10 @@ EXPORT_SYMBOL(ieee80211_ctstoself_duration); | |||
268 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | 268 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) |
269 | { | 269 | { |
270 | struct ieee80211_sub_if_data *sdata; | 270 | struct ieee80211_sub_if_data *sdata; |
271 | int n_acs = IEEE80211_NUM_ACS; | ||
272 | |||
273 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
274 | n_acs = 1; | ||
271 | 275 | ||
272 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
273 | int ac; | 277 | int ac; |
@@ -279,7 +283,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
279 | local->queue_stop_reasons[sdata->vif.cab_queue] != 0) | 283 | local->queue_stop_reasons[sdata->vif.cab_queue] != 0) |
280 | continue; | 284 | continue; |
281 | 285 | ||
282 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 286 | for (ac = 0; ac < n_acs; ac++) { |
283 | int ac_queue = sdata->vif.hw_queue[ac]; | 287 | int ac_queue = sdata->vif.hw_queue[ac]; |
284 | 288 | ||
285 | if (ac_queue == queue || | 289 | if (ac_queue == queue || |
@@ -341,6 +345,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
341 | { | 345 | { |
342 | struct ieee80211_local *local = hw_to_local(hw); | 346 | struct ieee80211_local *local = hw_to_local(hw); |
343 | struct ieee80211_sub_if_data *sdata; | 347 | struct ieee80211_sub_if_data *sdata; |
348 | int n_acs = IEEE80211_NUM_ACS; | ||
344 | 349 | ||
345 | trace_stop_queue(local, queue, reason); | 350 | trace_stop_queue(local, queue, reason); |
346 | 351 | ||
@@ -352,11 +357,14 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
352 | 357 | ||
353 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 358 | __set_bit(reason, &local->queue_stop_reasons[queue]); |
354 | 359 | ||
360 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
361 | n_acs = 1; | ||
362 | |||
355 | rcu_read_lock(); | 363 | rcu_read_lock(); |
356 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 364 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
357 | int ac; | 365 | int ac; |
358 | 366 | ||
359 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 367 | for (ac = 0; ac < n_acs; ac++) { |
360 | if (sdata->vif.hw_queue[ac] == queue || | 368 | if (sdata->vif.hw_queue[ac] == queue || |
361 | sdata->vif.cab_queue == queue) | 369 | sdata->vif.cab_queue == queue) |
362 | netif_stop_subqueue(sdata->dev, ac); | 370 | netif_stop_subqueue(sdata->dev, ac); |
@@ -1072,6 +1080,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1072 | pos += noffset - offset; | 1080 | pos += noffset - offset; |
1073 | } | 1081 | } |
1074 | 1082 | ||
1083 | if (sband->vht_cap.vht_supported) | ||
1084 | pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, | ||
1085 | sband->vht_cap.cap); | ||
1086 | |||
1075 | return pos - buffer; | 1087 | return pos - buffer; |
1076 | } | 1088 | } |
1077 | 1089 | ||
@@ -1411,10 +1423,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1411 | if (ieee80211_sdata_running(sdata)) | 1423 | if (ieee80211_sdata_running(sdata)) |
1412 | ieee80211_enable_keys(sdata); | 1424 | ieee80211_enable_keys(sdata); |
1413 | 1425 | ||
1426 | wake_up: | ||
1414 | local->in_reconfig = false; | 1427 | local->in_reconfig = false; |
1415 | barrier(); | 1428 | barrier(); |
1416 | 1429 | ||
1417 | wake_up: | ||
1418 | /* | 1430 | /* |
1419 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation | 1431 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation |
1420 | * sessions can be established after a resume. | 1432 | * sessions can be established after a resume. |
@@ -1699,6 +1711,27 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1699 | return pos; | 1711 | return pos; |
1700 | } | 1712 | } |
1701 | 1713 | ||
1714 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | ||
1715 | u32 cap) | ||
1716 | { | ||
1717 | __le32 tmp; | ||
1718 | |||
1719 | *pos++ = WLAN_EID_VHT_CAPABILITY; | ||
1720 | *pos++ = sizeof(struct ieee80211_vht_capabilities); | ||
1721 | memset(pos, 0, sizeof(struct ieee80211_vht_capabilities)); | ||
1722 | |||
1723 | /* capability flags */ | ||
1724 | tmp = cpu_to_le32(cap); | ||
1725 | memcpy(pos, &tmp, sizeof(u32)); | ||
1726 | pos += sizeof(u32); | ||
1727 | |||
1728 | /* VHT MCS set */ | ||
1729 | memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); | ||
1730 | pos += sizeof(vht_cap->vht_mcs); | ||
1731 | |||
1732 | return pos; | ||
1733 | } | ||
1734 | |||
1702 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1735 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1703 | struct ieee80211_channel *channel, | 1736 | struct ieee80211_channel *channel, |
1704 | enum nl80211_channel_type channel_type, | 1737 | enum nl80211_channel_type channel_type, |
@@ -1764,15 +1797,14 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | |||
1764 | return channel_type; | 1797 | return channel_type; |
1765 | } | 1798 | } |
1766 | 1799 | ||
1767 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, | 1800 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1768 | struct sk_buff *skb, bool need_basic) | 1801 | struct sk_buff *skb, bool need_basic) |
1769 | { | 1802 | { |
1770 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1771 | struct ieee80211_local *local = sdata->local; | 1803 | struct ieee80211_local *local = sdata->local; |
1772 | struct ieee80211_supported_band *sband; | 1804 | struct ieee80211_supported_band *sband; |
1773 | int rate; | 1805 | int rate; |
1774 | u8 i, rates, *pos; | 1806 | u8 i, rates, *pos; |
1775 | u32 basic_rates = vif->bss_conf.basic_rates; | 1807 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1776 | 1808 | ||
1777 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1809 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1778 | rates = sband->n_bitrates; | 1810 | rates = sband->n_bitrates; |
@@ -1796,15 +1828,14 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif, | |||
1796 | return 0; | 1828 | return 0; |
1797 | } | 1829 | } |
1798 | 1830 | ||
1799 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, | 1831 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1800 | struct sk_buff *skb, bool need_basic) | 1832 | struct sk_buff *skb, bool need_basic) |
1801 | { | 1833 | { |
1802 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1803 | struct ieee80211_local *local = sdata->local; | 1834 | struct ieee80211_local *local = sdata->local; |
1804 | struct ieee80211_supported_band *sband; | 1835 | struct ieee80211_supported_band *sband; |
1805 | int rate; | 1836 | int rate; |
1806 | u8 i, exrates, *pos; | 1837 | u8 i, exrates, *pos; |
1807 | u32 basic_rates = vif->bss_conf.basic_rates; | 1838 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1808 | 1839 | ||
1809 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1840 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1810 | exrates = sband->n_bitrates; | 1841 | exrates = sband->n_bitrates; |