Commit 75e296e9 authored by Johannes Berg's avatar Johannes Berg

mac80211: simplify and improve HT/VHT/HE disable code

Check early on that a device has support for QoS (at least 4
queues) when it supports HT/VHT/HE, so we don't have to check
this while connecting.

This lets us clean up the code there: move some of it into
channel preparation to clean up a bit more, and then change
the logic to only check the "wmm_used" flag.

Additionally, disable HE consistently when VHT is disabled.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131111300.891737-3-luca@coelho.fiSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d6039a34
...@@ -981,6 +981,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -981,6 +981,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (!supp_he) if (!supp_he)
supp_he = !!ieee80211_get_he_sta_cap(sband); supp_he = !!ieee80211_get_he_sta_cap(sband);
/* HT, VHT, HE require QoS, thus >= 4 queues */
if (WARN_ON(local->hw.queues < IEEE80211_NUM_ACS &&
(supp_ht || supp_vht || supp_he)))
return -EINVAL;
if (!sband->ht_cap.ht_supported) if (!sband->ht_cap.ht_supported)
continue; continue;
......
...@@ -164,7 +164,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -164,7 +164,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
chandef->center_freq1 = channel->center_freq; chandef->center_freq1 = channel->center_freq;
if (!ht_oper || !sta_ht_cap.ht_supported) { if (!ht_oper || !sta_ht_cap.ht_supported) {
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT |
IEEE80211_STA_DISABLE_HE;
goto out; goto out;
} }
...@@ -185,7 +187,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -185,7 +187,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
"Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
channel->center_freq, ht_cfreq, channel->center_freq, ht_cfreq,
ht_oper->primary_chan, channel->band); ht_oper->primary_chan, channel->band);
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT |
IEEE80211_STA_DISABLE_HE;
goto out; goto out;
} }
...@@ -301,7 +305,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -301,7 +305,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
IEEE80211_CHAN_DISABLED)) { IEEE80211_CHAN_DISABLED)) {
if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
ret = IEEE80211_STA_DISABLE_HT | ret = IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT; IEEE80211_STA_DISABLE_VHT |
IEEE80211_STA_DISABLE_HE;
break; break;
} }
...@@ -393,6 +398,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, ...@@ -393,6 +398,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT | IEEE80211_STA_DISABLE_VHT |
IEEE80211_STA_DISABLE_HE |
IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_40MHZ |
IEEE80211_STA_DISABLE_80P80MHZ | IEEE80211_STA_DISABLE_80P80MHZ |
IEEE80211_STA_DISABLE_160MHZ)) || IEEE80211_STA_DISABLE_160MHZ)) ||
...@@ -4760,10 +4766,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ...@@ -4760,10 +4766,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
IEEE80211_STA_DISABLE_80P80MHZ | IEEE80211_STA_DISABLE_80P80MHZ |
IEEE80211_STA_DISABLE_160MHZ); IEEE80211_STA_DISABLE_160MHZ);
/* disable HT/VHT/HE if we don't support them */
if (!sband->ht_cap.ht_supported) {
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
}
if (!sband->vht_cap.vht_supported)
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
if (!ieee80211_get_he_sta_cap(sband))
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
rcu_read_lock(); rcu_read_lock();
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
sband->ht_cap.ht_supported) {
const u8 *ht_oper_ie, *ht_cap_ie; const u8 *ht_oper_ie, *ht_cap_ie;
ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION); ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
...@@ -4780,8 +4798,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ...@@ -4780,8 +4798,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
} }
} }
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
sband->vht_cap.vht_supported) {
const u8 *vht_oper_ie, *vht_cap; const u8 *vht_oper_ie, *vht_cap;
vht_oper_ie = ieee80211_bss_get_ie(cbss, vht_oper_ie = ieee80211_bss_get_ie(cbss,
...@@ -4791,9 +4808,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ...@@ -4791,9 +4808,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
if (vht_oper && !ht_oper) { if (vht_oper && !ht_oper) {
vht_oper = NULL; vht_oper = NULL;
sdata_info(sdata, sdata_info(sdata,
"AP advertised VHT without HT, disabling both\n"); "AP advertised VHT without HT, disabling HT/VHT/HE\n");
ifmgd->flags |= IEEE80211_STA_DISABLE_HT; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
} }
vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY); vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
...@@ -4803,9 +4821,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ...@@ -4803,9 +4821,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
} }
} }
if (!ieee80211_get_he_sta_cap(sband))
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) { if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) {
const struct cfg80211_bss_ies *ies; const struct cfg80211_bss_ies *ies;
const u8 *he_oper_ie; const u8 *he_oper_ie;
...@@ -5304,27 +5319,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -5304,27 +5319,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
} }
} }
/* Also disable HT if we don't support it or the AP doesn't use WMM */
sband = local->hw.wiphy->bands[req->bss->channel->band]; sband = local->hw.wiphy->bands[req->bss->channel->band];
if (!sband->ht_cap.ht_supported ||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
if (!bss->wmm_used &&
!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
netdev_info(sdata->dev,
"disabling HT as WMM/QoS is not supported by the AP\n");
}
/* disable VHT if we don't support it or the AP doesn't use WMM */ /* also disable HT/VHT/HE if the AP doesn't use WMM */
if (!sband->vht_cap.vht_supported || if (!bss->wmm_used) {
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
if (!bss->wmm_used && ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) netdev_info(sdata->dev,
netdev_info(sdata->dev, "disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n");
"disabling VHT as WMM/QoS is not supported by the AP\n");
} }
memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
...@@ -5456,6 +5459,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -5456,6 +5459,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & ASSOC_REQ_DISABLE_HT) { if (req->flags & ASSOC_REQ_DISABLE_HT) {
ifmgd->flags |= IEEE80211_STA_DISABLE_HT; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
} }
if (req->flags & ASSOC_REQ_DISABLE_VHT) if (req->flags & ASSOC_REQ_DISABLE_VHT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment