diff options
-rw-r--r-- | net/mac80211/mlme.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ea7c714ba936..877b647d3e5c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -157,14 +157,18 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct cfg80211_chan_def vht_chandef; + struct ieee80211_sta_ht_cap sta_ht_cap; u32 ht_cfreq, ret; + memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); + ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); + chandef->chan = channel; chandef->width = NL80211_CHAN_WIDTH_20_NOHT; chandef->center_freq1 = channel->center_freq; chandef->center_freq2 = 0; - if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) { + if (!ht_cap || !ht_oper || !sta_ht_cap.ht_supported) { ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; goto out; } @@ -197,7 +201,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, } /* check 40 MHz support, if we have it */ - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: chandef->width = NL80211_CHAN_WIDTH_40; @@ -4196,9 +4200,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)cbss->priv; struct sta_info *new_sta = NULL; - bool have_sta = false; + struct ieee80211_supported_band *sband; + struct ieee80211_sta_ht_cap sta_ht_cap; + bool have_sta = false, is_override = false; int err; + sband = local->hw.wiphy->bands[cbss->channel->band]; + if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) return -EINVAL; @@ -4213,25 +4221,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, if (!new_sta) return -ENOMEM; } + + memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); + ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); + + is_override = (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != + (sband->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40); + + if (new_sta || is_override) { + err = ieee80211_prep_channel(sdata, cbss); + if (err) { + if (new_sta) + sta_info_free(local, new_sta); + return -EINVAL; + } + } + if (new_sta) { u32 rates = 0, basic_rates = 0; bool have_higher_than_11mbit; int min_rate = INT_MAX, min_rate_index = -1; struct ieee80211_chanctx_conf *chanctx_conf; - struct ieee80211_supported_band *sband; const struct cfg80211_bss_ies *ies; - int shift; + int shift = ieee80211_vif_get_shift(&sdata->vif); u32 rate_flags; - sband = local->hw.wiphy->bands[cbss->channel->band]; - - err = ieee80211_prep_channel(sdata, cbss); - if (err) { - sta_info_free(local, new_sta); - return -EINVAL; - } - shift = ieee80211_vif_get_shift(&sdata->vif); - rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (WARN_ON(!chanctx_conf)) { |