diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b82a12a9f0f1..8a73de6a5f5b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -149,6 +149,7 @@ static u32 | |||
149 | ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | 149 | ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, |
150 | struct ieee80211_supported_band *sband, | 150 | struct ieee80211_supported_band *sband, |
151 | struct ieee80211_channel *channel, | 151 | struct ieee80211_channel *channel, |
152 | const struct ieee80211_ht_cap *ht_cap, | ||
152 | const struct ieee80211_ht_operation *ht_oper, | 153 | const struct ieee80211_ht_operation *ht_oper, |
153 | const struct ieee80211_vht_operation *vht_oper, | 154 | const struct ieee80211_vht_operation *vht_oper, |
154 | struct cfg80211_chan_def *chandef, bool tracking) | 155 | struct cfg80211_chan_def *chandef, bool tracking) |
@@ -162,13 +163,19 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
162 | chandef->center_freq1 = channel->center_freq; | 163 | chandef->center_freq1 = channel->center_freq; |
163 | chandef->center_freq2 = 0; | 164 | chandef->center_freq2 = 0; |
164 | 165 | ||
165 | if (!ht_oper || !sband->ht_cap.ht_supported) { | 166 | if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) { |
166 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | 167 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; |
167 | goto out; | 168 | goto out; |
168 | } | 169 | } |
169 | 170 | ||
170 | chandef->width = NL80211_CHAN_WIDTH_20; | 171 | chandef->width = NL80211_CHAN_WIDTH_20; |
171 | 172 | ||
173 | if (!(ht_cap->cap_info & | ||
174 | cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) { | ||
175 | ret = IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_VHT; | ||
176 | goto out; | ||
177 | } | ||
178 | |||
172 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, | 179 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, |
173 | channel->band); | 180 | channel->band); |
174 | /* check that channel matches the right operating channel */ | 181 | /* check that channel matches the right operating channel */ |
@@ -328,6 +335,7 @@ out: | |||
328 | 335 | ||
329 | static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | 336 | static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, |
330 | struct sta_info *sta, | 337 | struct sta_info *sta, |
338 | const struct ieee80211_ht_cap *ht_cap, | ||
331 | const struct ieee80211_ht_operation *ht_oper, | 339 | const struct ieee80211_ht_operation *ht_oper, |
332 | const struct ieee80211_vht_operation *vht_oper, | 340 | const struct ieee80211_vht_operation *vht_oper, |
333 | const u8 *bssid, u32 *changed) | 341 | const u8 *bssid, u32 *changed) |
@@ -367,8 +375,9 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
367 | sband = local->hw.wiphy->bands[chan->band]; | 375 | sband = local->hw.wiphy->bands[chan->band]; |
368 | 376 | ||
369 | /* calculate new channel (type) based on HT/VHT operation IEs */ | 377 | /* calculate new channel (type) based on HT/VHT operation IEs */ |
370 | flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, | 378 | flags = ieee80211_determine_chantype(sdata, sband, chan, |
371 | vht_oper, &chandef, true); | 379 | ht_cap, ht_oper, vht_oper, |
380 | &chandef, true); | ||
372 | 381 | ||
373 | /* | 382 | /* |
374 | * Downgrade the new channel if we associated with restricted | 383 | * Downgrade the new channel if we associated with restricted |
@@ -2677,8 +2686,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2677 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) | 2686 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) |
2678 | set_sta_flag(sta, WLAN_STA_MFP); | 2687 | set_sta_flag(sta, WLAN_STA_MFP); |
2679 | 2688 | ||
2680 | if (elems.wmm_param) | 2689 | sta->sta.wme = elems.wmm_param; |
2681 | set_sta_flag(sta, WLAN_STA_WME); | ||
2682 | 2690 | ||
2683 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 2691 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
2684 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 2692 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
@@ -3174,7 +3182,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3174 | mutex_lock(&local->sta_mtx); | 3182 | mutex_lock(&local->sta_mtx); |
3175 | sta = sta_info_get(sdata, bssid); | 3183 | sta = sta_info_get(sdata, bssid); |
3176 | 3184 | ||
3177 | if (ieee80211_config_bw(sdata, sta, elems.ht_operation, | 3185 | if (ieee80211_config_bw(sdata, sta, |
3186 | elems.ht_cap_elem, elems.ht_operation, | ||
3178 | elems.vht_operation, bssid, &changed)) { | 3187 | elems.vht_operation, bssid, &changed)) { |
3179 | mutex_unlock(&local->sta_mtx); | 3188 | mutex_unlock(&local->sta_mtx); |
3180 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3189 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
@@ -3808,6 +3817,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3808 | { | 3817 | { |
3809 | struct ieee80211_local *local = sdata->local; | 3818 | struct ieee80211_local *local = sdata->local; |
3810 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3819 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3820 | const struct ieee80211_ht_cap *ht_cap = NULL; | ||
3811 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3821 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3812 | const struct ieee80211_vht_operation *vht_oper = NULL; | 3822 | const struct ieee80211_vht_operation *vht_oper = NULL; |
3813 | struct ieee80211_supported_band *sband; | 3823 | struct ieee80211_supported_band *sband; |
@@ -3824,14 +3834,17 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3824 | 3834 | ||
3825 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | 3835 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && |
3826 | sband->ht_cap.ht_supported) { | 3836 | sband->ht_cap.ht_supported) { |
3827 | const u8 *ht_oper_ie, *ht_cap; | 3837 | const u8 *ht_oper_ie, *ht_cap_ie; |
3828 | 3838 | ||
3829 | ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION); | 3839 | ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION); |
3830 | if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) | 3840 | if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) |
3831 | ht_oper = (void *)(ht_oper_ie + 2); | 3841 | ht_oper = (void *)(ht_oper_ie + 2); |
3832 | 3842 | ||
3833 | ht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY); | 3843 | ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY); |
3834 | if (!ht_cap || ht_cap[1] < sizeof(struct ieee80211_ht_cap)) { | 3844 | if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) |
3845 | ht_cap = (void *)(ht_cap_ie + 2); | ||
3846 | |||
3847 | if (!ht_cap) { | ||
3835 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 3848 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3836 | ht_oper = NULL; | 3849 | ht_oper = NULL; |
3837 | } | 3850 | } |
@@ -3862,7 +3875,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3862 | 3875 | ||
3863 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, | 3876 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, |
3864 | cbss->channel, | 3877 | cbss->channel, |
3865 | ht_oper, vht_oper, | 3878 | ht_cap, ht_oper, vht_oper, |
3866 | &chandef, false); | 3879 | &chandef, false); |
3867 | 3880 | ||
3868 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), | 3881 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), |