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); |
