[PATCH AUTOSEL 5.8 18/53] wireless: fix wrong 160/80+80 MHz setting

From: Sasha Levin
Date: Mon Sep 07 2020 - 13:11:00 EST


From: Shay Bar <shay.bar@xxxxxxxxxx>

[ Upstream commit 3579994476b65cb5e272ff0f720a1fd31322e53f ]

Fix cfg80211_chandef_usable():
consider IEEE80211_VHT_CAP_EXT_NSS_BW when verifying 160/80+80 MHz.

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@xxxxxxxxxx>
Signed-off-by: Shay Bar <shay.bar@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20200826143139.25976-1-shay.bar@xxxxxxxxxx
[reformat the code a bit and use u32_get_bits()]
Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
net/wireless/chan.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index cddf92c5d09ef..7a7cc4ade2b36 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -10,6 +10,7 @@
*/

#include <linux/export.h>
+#include <linux/bitfield.h>
#include <net/cfg80211.h>
#include "core.h"
#include "rdev-ops.h"
@@ -892,6 +893,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
struct ieee80211_sta_vht_cap *vht_cap;
struct ieee80211_edmg *edmg_cap;
u32 width, control_freq, cap;
+ bool support_80_80 = false;

if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return false;
@@ -944,9 +946,13 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
break;
case NL80211_CHAN_WIDTH_80P80:
- cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (chandef->chan->band != NL80211_BAND_6GHZ &&
- cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ cap = vht_cap->cap;
+ support_80_80 =
+ (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
+ (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
+ cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
+ u32_get_bits(cap, IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) > 1;
+ if (chandef->chan->band != NL80211_BAND_6GHZ && !support_80_80)
return false;
/* fall through */
case NL80211_CHAN_WIDTH_80:
@@ -966,7 +972,8 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
- cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ &&
+ !(vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
return false;
break;
default:
--
2.25.1