| From cf17e99062a81e5081c0e5e09f92cce5618318a2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 10 Feb 2020 15:07:28 +0200 |
| Subject: mac80211: fix wrong 160/80+80 MHz setting |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Shay Bar <shay.bar@celeno.com> |
| |
| [ Upstream commit 33181ea7f5a62a17fbe55f0f73428ecb5e686be8 ] |
| |
| Before this patch, STA's would set new width of 160/80+80 MHz based on AP capability only. |
| This is wrong because STA may not support > 80MHz BW. |
| Fix is to verify STA has 160/80+80 MHz capability before increasing its width to > 80MHz. |
| |
| The "support_80_80" and "support_160" setting is based on: |
| "Table 9-272 — Setting of the Supported Channel Width Set subfield and Extended NSS BW |
| Support subfield at a STA transmitting the VHT Capabilities Information field" |
| From "Draft P802.11REVmd_D3.0.pdf" |
| |
| Signed-off-by: Aviad Brikman <aviad.brikman@celeno.com> |
| Signed-off-by: Shay Bar <shay.bar@celeno.com> |
| Link: https://lore.kernel.org/r/20200210130728.23674-1-shay.bar@celeno.com |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/mac80211/util.c | 16 ++++++++++++++-- |
| 1 file changed, 14 insertions(+), 2 deletions(-) |
| |
| diff --git a/net/mac80211/util.c b/net/mac80211/util.c |
| index 739e90555d8b9..decd46b383938 100644 |
| --- a/net/mac80211/util.c |
| +++ b/net/mac80211/util.c |
| @@ -2993,10 +2993,22 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, |
| int cf0, cf1; |
| int ccfs0, ccfs1, ccfs2; |
| int ccf0, ccf1; |
| + u32 vht_cap; |
| + bool support_80_80 = false; |
| + bool support_160 = false; |
| |
| if (!oper || !htop) |
| return false; |
| |
| + vht_cap = hw->wiphy->bands[chandef->chan->band]->vht_cap.cap; |
| + support_160 = (vht_cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK | |
| + IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)); |
| + support_80_80 = ((vht_cap & |
| + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) || |
| + (vht_cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ && |
| + vht_cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) || |
| + ((vht_cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) >> |
| + IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT > 1)); |
| ccfs0 = oper->center_freq_seg0_idx; |
| ccfs1 = oper->center_freq_seg1_idx; |
| ccfs2 = (le16_to_cpu(htop->operation_mode) & |
| @@ -3024,10 +3036,10 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, |
| unsigned int diff; |
| |
| diff = abs(ccf1 - ccf0); |
| - if (diff == 8) { |
| + if ((diff == 8) && support_160) { |
| new.width = NL80211_CHAN_WIDTH_160; |
| new.center_freq1 = cf1; |
| - } else if (diff > 8) { |
| + } else if ((diff > 8) && support_80_80) { |
| new.width = NL80211_CHAN_WIDTH_80P80; |
| new.center_freq2 = cf1; |
| } |
| -- |
| 2.20.1 |
| |