aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/chan.c27
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mlme.c32
-rw-r--r--net/mac80211/rx.c8
4 files changed, 51 insertions, 19 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index d1f7abddb18..e00ce8c3e28 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
8static enum ieee80211_chan_mode 9static 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 */
144enum 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 173c1396070..63fb0eb79d8 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);
1503enum nl80211_channel_type 1503enum nl80211_channel_type
1504ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); 1504ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info);
1505enum 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 90d1db36cde..0df22372af8 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 53c88d14547..bcfe8c77c83 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: