diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 358226f63b81..11783192a625 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -137,11 +137,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
137 | struct sta_info *sta; | 137 | struct sta_info *sta; |
138 | u32 changed = 0; | 138 | u32 changed = 0; |
139 | u16 ht_opmode; | 139 | u16 ht_opmode; |
140 | bool enable_ht = true, ht_changed; | 140 | bool enable_ht = true; |
141 | enum nl80211_channel_type prev_chantype; | ||
141 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 142 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
142 | 143 | ||
143 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 144 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
144 | 145 | ||
146 | prev_chantype = sdata->vif.bss_conf.channel_type; | ||
147 | |||
145 | /* HT is not supported */ | 148 | /* HT is not supported */ |
146 | if (!sband->ht_cap.ht_supported) | 149 | if (!sband->ht_cap.ht_supported) |
147 | enable_ht = false; | 150 | enable_ht = false; |
@@ -172,38 +175,37 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
172 | } | 175 | } |
173 | } | 176 | } |
174 | 177 | ||
175 | ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || | ||
176 | channel_type != local->hw.conf.channel_type; | ||
177 | |||
178 | if (local->tmp_channel) | 178 | if (local->tmp_channel) |
179 | local->tmp_channel_type = channel_type; | 179 | local->tmp_channel_type = channel_type; |
180 | local->oper_channel_type = channel_type; | ||
181 | 180 | ||
182 | if (ht_changed) { | 181 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
183 | /* channel_type change automatically detected */ | 182 | /* can only fail due to HT40+/- mismatch */ |
184 | ieee80211_hw_config(local, 0); | 183 | channel_type = NL80211_CHAN_HT20; |
184 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | ||
185 | } | ||
185 | 186 | ||
187 | /* channel_type change automatically detected */ | ||
188 | ieee80211_hw_config(local, 0); | ||
189 | |||
190 | if (prev_chantype != channel_type) { | ||
186 | rcu_read_lock(); | 191 | rcu_read_lock(); |
187 | sta = sta_info_get(sdata, bssid); | 192 | sta = sta_info_get(sdata, bssid); |
188 | if (sta) | 193 | if (sta) |
189 | rate_control_rate_update(local, sband, sta, | 194 | rate_control_rate_update(local, sband, sta, |
190 | IEEE80211_RC_HT_CHANGED, | 195 | IEEE80211_RC_HT_CHANGED, |
191 | local->oper_channel_type); | 196 | channel_type); |
192 | rcu_read_unlock(); | 197 | rcu_read_unlock(); |
193 | } | 198 | } |
194 | |||
195 | /* disable HT */ | ||
196 | if (!enable_ht) | ||
197 | return 0; | ||
198 | 199 | ||
199 | ht_opmode = le16_to_cpu(hti->operation_mode); | 200 | ht_opmode = le16_to_cpu(hti->operation_mode); |
200 | 201 | ||
201 | /* if bss configuration changed store the new one */ | 202 | /* if bss configuration changed store the new one */ |
202 | if (!sdata->ht_opmode_valid || | 203 | if (sdata->ht_opmode_valid != enable_ht || |
203 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | 204 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || |
205 | prev_chantype != channel_type) { | ||
204 | changed |= BSS_CHANGED_HT; | 206 | changed |= BSS_CHANGED_HT; |
205 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 207 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
206 | sdata->ht_opmode_valid = true; | 208 | sdata->ht_opmode_valid = enable_ht; |
207 | } | 209 | } |
208 | 210 | ||
209 | return changed; | 211 | return changed; |
@@ -866,7 +868,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
866 | ieee80211_set_wmm_default(sdata); | 868 | ieee80211_set_wmm_default(sdata); |
867 | 869 | ||
868 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 870 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
869 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 871 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); |
870 | 872 | ||
871 | /* on the next assoc, re-program HT parameters */ | 873 | /* on the next assoc, re-program HT parameters */ |
872 | sdata->ht_opmode_valid = false; | 874 | sdata->ht_opmode_valid = false; |
@@ -883,8 +885,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
883 | 885 | ||
884 | ieee80211_hw_config(local, config_changed); | 886 | ieee80211_hw_config(local, config_changed); |
885 | 887 | ||
886 | /* And the BSSID changed -- not very interesting here */ | 888 | /* The BSSID (not really interesting) and HT changed */ |
887 | changed |= BSS_CHANGED_BSSID; | 889 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
888 | ieee80211_bss_info_change_notify(sdata, changed); | 890 | ieee80211_bss_info_change_notify(sdata, changed); |
889 | 891 | ||
890 | if (remove_sta) | 892 | if (remove_sta) |
@@ -2266,7 +2268,7 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | |||
2266 | if ((chan != local->tmp_channel || | 2268 | if ((chan != local->tmp_channel || |
2267 | channel_type != local->tmp_channel_type) && | 2269 | channel_type != local->tmp_channel_type) && |
2268 | (chan != local->oper_channel || | 2270 | (chan != local->oper_channel || |
2269 | channel_type != local->oper_channel_type)) | 2271 | channel_type != local->_oper_channel_type)) |
2270 | return -EBUSY; | 2272 | return -EBUSY; |
2271 | 2273 | ||
2272 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 2274 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); |