diff options
-rw-r--r-- | net/mac80211/chan.c | 27 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 32 | ||||
-rw-r--r-- | net/mac80211/rx.c | 8 |
4 files changed, 51 insertions, 19 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index d1f7abddb182..e00ce8c3e28e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/nl80211.h> | 5 | #include <linux/nl80211.h> |
6 | #include <net/cfg80211.h> | ||
6 | #include "ieee80211_i.h" | 7 | #include "ieee80211_i.h" |
7 | 8 | ||
8 | static enum ieee80211_chan_mode | 9 | static enum ieee80211_chan_mode |
@@ -134,3 +135,29 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
134 | 135 | ||
135 | return result; | 136 | return result; |
136 | } | 137 | } |
138 | |||
139 | /* | ||
140 | * ieee80211_get_tx_channel_type returns the channel type we should | ||
141 | * use for packet transmission, given the channel capability and | ||
142 | * whatever regulatory flags we have been given. | ||
143 | */ | ||
144 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
145 | struct ieee80211_local *local, | ||
146 | enum nl80211_channel_type channel_type) | ||
147 | { | ||
148 | switch (channel_type) { | ||
149 | case NL80211_CHAN_HT40PLUS: | ||
150 | if (local->hw.conf.channel->flags & | ||
151 | IEEE80211_CHAN_NO_HT40PLUS) | ||
152 | return NL80211_CHAN_HT20; | ||
153 | break; | ||
154 | case NL80211_CHAN_HT40MINUS: | ||
155 | if (local->hw.conf.channel->flags & | ||
156 | IEEE80211_CHAN_NO_HT40MINUS) | ||
157 | return NL80211_CHAN_HT20; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | return channel_type; | ||
163 | } | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 173c1396070d..63fb0eb79d8e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1502,6 +1502,9 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
1502 | enum nl80211_channel_type chantype); | 1502 | enum nl80211_channel_type chantype); |
1503 | enum nl80211_channel_type | 1503 | enum nl80211_channel_type |
1504 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); | 1504 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); |
1505 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
1506 | struct ieee80211_local *local, | ||
1507 | enum nl80211_channel_type channel_type); | ||
1505 | 1508 | ||
1506 | #ifdef CONFIG_MAC80211_NOINLINE | 1509 | #ifdef CONFIG_MAC80211_NOINLINE |
1507 | #define debug_noinline noinline | 1510 | #define debug_noinline noinline |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 90d1db36cdef..0df22372af8d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -189,7 +189,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
189 | u16 ht_opmode; | 189 | u16 ht_opmode; |
190 | bool enable_ht = true; | 190 | bool enable_ht = true; |
191 | enum nl80211_channel_type prev_chantype; | 191 | enum nl80211_channel_type prev_chantype; |
192 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 192 | enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; |
193 | enum nl80211_channel_type tx_channel_type; | ||
193 | 194 | ||
194 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 195 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
195 | prev_chantype = sdata->vif.bss_conf.channel_type; | 196 | prev_chantype = sdata->vif.bss_conf.channel_type; |
@@ -216,7 +217,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
216 | } | 217 | } |
217 | 218 | ||
218 | if (enable_ht) { | 219 | if (enable_ht) { |
219 | channel_type = NL80211_CHAN_HT20; | 220 | rx_channel_type = NL80211_CHAN_HT20; |
220 | 221 | ||
221 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | 222 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
222 | !ieee80111_cfg_override_disables_ht40(sdata) && | 223 | !ieee80111_cfg_override_disables_ht40(sdata) && |
@@ -224,29 +225,28 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
224 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | 225 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
225 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 226 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
226 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 227 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
227 | if (!(local->hw.conf.channel->flags & | 228 | rx_channel_type = NL80211_CHAN_HT40PLUS; |
228 | IEEE80211_CHAN_NO_HT40PLUS)) | ||
229 | channel_type = NL80211_CHAN_HT40PLUS; | ||
230 | break; | 229 | break; |
231 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 230 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
232 | if (!(local->hw.conf.channel->flags & | 231 | rx_channel_type = NL80211_CHAN_HT40MINUS; |
233 | IEEE80211_CHAN_NO_HT40MINUS)) | ||
234 | channel_type = NL80211_CHAN_HT40MINUS; | ||
235 | break; | 232 | break; |
236 | } | 233 | } |
237 | } | 234 | } |
238 | } | 235 | } |
239 | 236 | ||
237 | tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type); | ||
238 | |||
240 | if (local->tmp_channel) | 239 | if (local->tmp_channel) |
241 | local->tmp_channel_type = channel_type; | 240 | local->tmp_channel_type = rx_channel_type; |
242 | 241 | ||
243 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 242 | if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) { |
244 | /* can only fail due to HT40+/- mismatch */ | 243 | /* can only fail due to HT40+/- mismatch */ |
245 | channel_type = NL80211_CHAN_HT20; | 244 | rx_channel_type = NL80211_CHAN_HT20; |
246 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | 245 | WARN_ON(!ieee80211_set_channel_type(local, sdata, |
246 | rx_channel_type)); | ||
247 | } | 247 | } |
248 | 248 | ||
249 | if (beacon_htcap_ie && (prev_chantype != channel_type)) { | 249 | if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) { |
250 | /* | 250 | /* |
251 | * Whenever the AP announces the HT mode change that can be | 251 | * Whenever the AP announces the HT mode change that can be |
252 | * 40MHz intolerant or etc., it would be safer to stop tx | 252 | * 40MHz intolerant or etc., it would be safer to stop tx |
@@ -264,13 +264,13 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
264 | /* channel_type change automatically detected */ | 264 | /* channel_type change automatically detected */ |
265 | ieee80211_hw_config(local, 0); | 265 | ieee80211_hw_config(local, 0); |
266 | 266 | ||
267 | if (prev_chantype != channel_type) { | 267 | if (prev_chantype != tx_channel_type) { |
268 | rcu_read_lock(); | 268 | rcu_read_lock(); |
269 | sta = sta_info_get(sdata, bssid); | 269 | sta = sta_info_get(sdata, bssid); |
270 | if (sta) | 270 | if (sta) |
271 | rate_control_rate_update(local, sband, sta, | 271 | rate_control_rate_update(local, sband, sta, |
272 | IEEE80211_RC_HT_CHANGED, | 272 | IEEE80211_RC_HT_CHANGED, |
273 | channel_type); | 273 | tx_channel_type); |
274 | rcu_read_unlock(); | 274 | rcu_read_unlock(); |
275 | 275 | ||
276 | if (beacon_htcap_ie) | 276 | if (beacon_htcap_ie) |
@@ -283,7 +283,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
283 | /* if bss configuration changed store the new one */ | 283 | /* if bss configuration changed store the new one */ |
284 | if (sdata->ht_opmode_valid != enable_ht || | 284 | if (sdata->ht_opmode_valid != enable_ht || |
285 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || | 285 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || |
286 | prev_chantype != channel_type) { | 286 | prev_chantype != rx_channel_type) { |
287 | changed |= BSS_CHANGED_HT; | 287 | changed |= BSS_CHANGED_HT; |
288 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 288 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
289 | sdata->ht_opmode_valid = enable_ht; | 289 | sdata->ht_opmode_valid = enable_ht; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 53c88d145472..bcfe8c77c839 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2269,9 +2269,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2269 | 2269 | ||
2270 | sband = rx->local->hw.wiphy->bands[status->band]; | 2270 | sband = rx->local->hw.wiphy->bands[status->band]; |
2271 | 2271 | ||
2272 | rate_control_rate_update(local, sband, rx->sta, | 2272 | rate_control_rate_update( |
2273 | IEEE80211_RC_SMPS_CHANGED, | 2273 | local, sband, rx->sta, |
2274 | local->_oper_channel_type); | 2274 | IEEE80211_RC_SMPS_CHANGED, |
2275 | ieee80211_get_tx_channel_type( | ||
2276 | local, local->_oper_channel_type)); | ||
2275 | goto handled; | 2277 | goto handled; |
2276 | } | 2278 | } |
2277 | default: | 2279 | default: |