aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c44
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);