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.c33
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
149ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, 149ieee80211_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
329static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, 336static 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),