2020-05-13 19:46:19

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 01/11] cfg80211: use only HE capability to set prohibited flags in 6 GHz

The prohibited flags to determine whether configured bandwidth
is supported by driver are validated only against HT and VHT capability.
In 6 GHz band, Only HE capability should be validated to find out
given chandef is usable.

Co-developed-by: Vamsi Krishna <[email protected]>
Signed-off-by: Vamsi Krishna <[email protected]>
Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/wireless/chan.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index fcac5c6366e1..582b487576e1 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -19,6 +19,11 @@ static bool cfg80211_valid_60g_freq(u32 freq)
return freq >= 58320 && freq <= 70200;
}

+static bool cfg80211_is_6ghz_freq(u32 freq)
+{
+ return (freq > 5940 && freq < 7105);
+}
+
void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *chan,
enum nl80211_channel_type chan_type)
@@ -882,6 +887,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
struct ieee80211_edmg *edmg_cap;
+ const struct ieee80211_sta_he_cap *he_cap;
u32 width, control_freq, cap;

if (WARN_ON(!cfg80211_chandef_valid(chandef)))
@@ -890,6 +896,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap;
+ he_cap = ieee80211_get_he_sta_cap(wiphy->bands[chandef->chan->band]);

if (edmg_cap->channels &&
!cfg80211_edmg_usable(wiphy,
@@ -919,6 +926,16 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
break;
case NL80211_CHAN_WIDTH_40:
width = 40;
+ if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {
+ if (!he_cap)
+ return false;
+ if (!he_cap->has_he_6ghz)
+ return false;
+ if (!(he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
+ return false;
+ break;
+ }
if (!ht_cap->ht_supported)
return false;
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
@@ -933,24 +950,53 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
break;
case NL80211_CHAN_WIDTH_80P80:
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ if (!cfg80211_is_6ghz_freq(chandef->center_freq1) &&
+ cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
return false;
+ if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {
+ if (!he_cap)
+ return false;
+ if (!he_cap->has_he_6ghz)
+ return false;
+ if (!(he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G))
+ return false;
+ }
/* fall through */
case NL80211_CHAN_WIDTH_80:
- if (!vht_cap->vht_supported)
+ if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {
+ if (!he_cap)
+ return false;
+ if (!he_cap->has_he_6ghz)
+ return false;
+ if (!(he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
+ return false;
+ } else if (!vht_cap->vht_supported) {
return false;
+ }
prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
+ prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
+ width = 160;
+ if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {
+ if (!he_cap)
+ return false;
+ if (!he_cap->has_he_6ghz)
+ return false;
+ if (!(he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G))
+ return false;
+ break;
+ }
if (!vht_cap->vht_supported)
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)
return false;
- prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
- width = 160;
break;
default:
WARN_ON_ONCE(1);
--
2.7.4


2020-05-13 19:46:19

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 05/11] mac80211: fix memory overlap due to variable length param

As of now HE operation element in bss_conf includes variable length
optional field followed by other HE variable. Though the optional
field never be used, actually it is referring to next member of the
bss_conf structure which is not correct. Fix it by declaring needed
HE operation fields within bss_conf itself.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath11k/mac.c | 3 +--
include/net/mac80211.h | 7 +++++--
net/mac80211/he.c | 13 +++++--------
3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 9f8bc19cc5ae..06d063274eea 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1168,8 +1168,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
sizeof(arg->peer_he_cap_macinfo));
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
sizeof(arg->peer_he_cap_phyinfo));
- memcpy(&arg->peer_he_ops, &vif->bss_conf.he_operation,
- sizeof(arg->peer_he_ops));
+ arg->peer_he_ops = vif->bss_conf.he_oper.params;

/* the top most byte is used to indicate BSS color info */
arg->peer_he_ops &= 0xffffff;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 97fec4d310ac..2af956bdf80c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -603,7 +603,7 @@ struct ieee80211_ftm_responder_params {
* nontransmitted BSSIDs
* @profile_periodicity: the least number of beacon frames need to be received
* in order to discover all the nontransmitted BSSIDs in the set.
- * @he_operation: HE operation information of the AP we are connected to
+ * @he_oper: HE operation information of the AP we are connected to
* @he_obss_pd: OBSS Packet Detection parameters.
* @he_bss_color: BSS coloring settings, if BSS supports HE
*/
@@ -666,7 +666,10 @@ struct ieee80211_bss_conf {
u8 bssid_indicator;
bool ema_ap;
u8 profile_periodicity;
- struct ieee80211_he_operation he_operation;
+ struct {
+ u32 params;
+ u16 nss_set;
+ } he_oper;
struct ieee80211_he_obss_pd he_obss_pd;
struct cfg80211_he_bss_color he_bss_color;
};
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index 1087f715338b..f520552b22be 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -57,17 +57,14 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,

void
ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
- const struct ieee80211_he_operation *he_op_ie_elem)
+ const struct ieee80211_he_operation *he_op_ie)
{
- struct ieee80211_he_operation *he_operation =
- &vif->bss_conf.he_operation;
-
- if (!he_op_ie_elem) {
- memset(he_operation, 0, sizeof(*he_operation));
+ memset(&vif->bss_conf.he_oper, 0, sizeof(vif->bss_conf.he_oper));
+ if (!he_op_ie)
return;
- }

- vif->bss_conf.he_operation = *he_op_ie_elem;
+ vif->bss_conf.he_oper.params = __le32_to_cpu(he_op_ie->he_oper_params);
+ vif->bss_conf.he_oper.nss_set = __le16_to_cpu(he_op_ie->he_mcs_nss_set);
}

void
--
2.7.4

2020-05-13 19:46:19

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 02/11] cfg80211: handle 6 GHz capability of new station

Handle 6 GHz HE capability while adding new station. It will be used
later in mac80211 station processing.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 6 ++++++
net/wireless/nl80211.c | 12 ++++++++++++
3 files changed, 20 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 70e48f66dac8..0797a296c083 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1225,6 +1225,7 @@ struct sta_txpwr {
* @he_capa_len: the length of the HE capabilities
* @airtime_weight: airtime scheduler weight for this station
* @txpwr: transmit power for an associated station
+ * @he_6ghz_capa: HE 6 GHz Band capabilities of station
*/
struct station_parameters {
const u8 *supported_rates;
@@ -1257,6 +1258,7 @@ struct station_parameters {
u8 he_capa_len;
u16 airtime_weight;
struct sta_txpwr txpwr;
+ const struct ieee80211_he_6ghz_band_cap *he_6ghz_capa;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2b691161830f..9c0a912f1684 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2470,6 +2470,9 @@ enum nl80211_commands {
* no roaming occurs between the reauth threshold and PMK expiration,
* disassociation is still forced.
*
+ * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from
+ * association request when used with NL80211_CMD_NEW_STATION).
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2945,6 +2948,8 @@ enum nl80211_attrs {
NL80211_ATTR_PMK_LIFETIME,
NL80211_ATTR_PMK_REAUTH_THRESHOLD,

+ NL80211_ATTR_HE_6GHZ_CAPABILITY,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -2998,6 +3003,7 @@ enum nl80211_attrs {
#define NL80211_HE_MAX_CAPABILITY_LEN 54
#define NL80211_MAX_NR_CIPHER_SUITES 5
#define NL80211_MAX_NR_AKM_SUITES 2
+#define NL80211_HE_6GHZ_CAPABILITY_LEN 2

#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 692bcd35f809..bcd7a452e8b1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -661,6 +661,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
[NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
[NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
+ [NL80211_ATTR_HE_6GHZ_CAPABILITY] = {
+ .type = NLA_EXACT_LEN,
+ .len = NL80211_HE_6GHZ_CAPABILITY_LEN,
+ },
};

/* policy for the key attributes */
@@ -6129,6 +6133,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}

+ if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
+ params.he_6ghz_capa =
+ nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
+
if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
params.opmode_notif_used = true;
params.opmode_notif =
@@ -6177,6 +6185,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}

+ /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
+ if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
+ return -EINVAL;
+
/* When you run into this, adjust the code below for the new flag */
BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);

--
2.7.4

2020-05-13 19:46:20

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

In 6 GHz band, determine chandef from 6 GHz operation information
of HE operation element.

Reported-by: kernel test robot <[email protected]>
Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/ieee80211_i.h | 3 ++
net/mac80211/mesh.c | 1 +
net/mac80211/mlme.c | 12 ++++++
net/mac80211/util.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0bb442feb1db..42a7782c973a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2194,6 +2194,9 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw,
const struct ieee80211_vht_operation *oper,
const struct ieee80211_ht_operation *htop,
struct cfg80211_chan_def *chandef);
+bool ieee80211_chandef_he_oper(struct ieee80211_sub_if_data *sdata,
+ const struct ieee80211_he_operation *heop,
+ struct cfg80211_chan_def *chandef);
u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);

int __must_check
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 04d3da733bc8..0521b57939e1 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -99,6 +99,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
ieee80211_chandef_vht_oper(&sdata->local->hw,
ie->vht_operation, ie->ht_operation,
&sta_chan_def);
+ ieee80211_chandef_he_oper(sdata, ie->he_operation, &sta_chan_def);

if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
&sta_chan_def))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b4dfefd482a6..9115dc9c7d78 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -163,6 +163,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = channel->center_freq;

+ if (channel->band == NL80211_BAND_6GHZ)
+ goto skip_ht_vht_oper;
+
if (!ht_oper || !sta_ht_cap.ht_supported) {
ret = IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_VHT |
@@ -263,6 +266,15 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,

*chandef = vht_chandef;

+skip_ht_vht_oper:
+ if (!ieee80211_chandef_he_oper(sdata, he_oper, chandef)) {
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE))
+ sdata_info(sdata,
+ "AP HE information is invalid, disable HE\n");
+ ret = IEEE80211_STA_DISABLE_HE;
+ goto out;
+ }
+
ret = 0;

out:
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 90b8c42b1aa8..f6ab8835d69a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3170,6 +3170,102 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw,
return true;
}

+bool ieee80211_chandef_he_oper(struct ieee80211_sub_if_data *sdata,
+ const struct ieee80211_he_operation *heop,
+ struct cfg80211_chan_def *chandef)
+{
+ struct ieee80211_he_oper_6ghz_op_info info;
+ const struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_supported_band *sband;
+ struct cfg80211_chan_def new = *chandef;
+ int cf0, cf1;
+ int ccf0, ccf1;
+ bool support_80_80;
+ bool support_160;
+ u8 he_phy_cap;
+ u8 pos = 0;
+
+ /* Below HE Operation check is required only for 6 GHz band */
+ if (chandef->chan->band != NL80211_BAND_6GHZ)
+ return true;
+
+ if (!heop)
+ return false;
+
+ sband = sdata->local->hw.wiphy->bands[chandef->chan->band];
+ if (!sband)
+ return false;
+
+ he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type);
+ if (!he_cap)
+ return false;
+
+ if (!(le32_to_cpu(heop->he_oper_params) &
+ IEEE80211_HE_OPERATION_6GHZ_OP_INFO))
+ return false;
+
+ he_phy_cap = he_cap->he_cap_elem.phy_cap_info[0];
+ support_160 =
+ !!(he_phy_cap &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
+ support_80_80 =
+ !!(he_phy_cap &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G);
+
+ if (le32_to_cpu(heop->he_oper_params) &
+ IEEE80211_HE_OPERATION_VHT_OPER_INFO)
+ pos += 3;
+ if (le32_to_cpu(heop->he_oper_params) &
+ IEEE80211_HE_OPERATION_CO_HOSTED_BSS)
+ pos += 1;
+
+ memcpy(&info, &heop->optional[pos], sizeof(info));
+ ccf0 = info.center_freq_seg0_idx;
+ ccf1 = info.center_freq_seg1_idx;
+
+ cf0 = ieee80211_channel_to_frequency(ccf0, chandef->chan->band);
+ cf1 = ieee80211_channel_to_frequency(ccf1, chandef->chan->band);
+
+ switch (info.control & 0x3) {
+ case IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ:
+ new.center_freq1 = cf0;
+ new.width = NL80211_CHAN_WIDTH_20;
+ break;
+ case IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ:
+ new.center_freq1 = cf0;
+ new.width = NL80211_CHAN_WIDTH_40;
+ break;
+ case IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ:
+ new.center_freq1 = cf0;
+ new.width = NL80211_CHAN_WIDTH_80;
+ break;
+ case IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ:
+ new.center_freq1 = cf0;
+ new.width = NL80211_CHAN_WIDTH_80;
+ if (ccf1) {
+ unsigned int diff;
+
+ diff = abs(ccf1 - ccf0);
+ if (diff == 8 && support_160) {
+ new.width = NL80211_CHAN_WIDTH_160;
+ new.center_freq1 = cf1;
+ } else if ((diff > 8) && support_80_80) {
+ new.width = NL80211_CHAN_WIDTH_80P80;
+ new.center_freq2 = cf1;
+ }
+ }
+ break;
+ default:
+ return false;
+ }
+
+ if (!cfg80211_chandef_valid(&new))
+ return false;
+
+ *chandef = new;
+ return true;
+}
+
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
const struct ieee80211_supported_band *sband,
const u8 *srates, int srates_len, u32 *rates)
--
2.7.4

2020-05-13 19:47:13

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 09/11] mac80211: do not allow HT/VHT IEs in 6 GHz mesh mode

As HT/VHT elements are not allowed in 6 GHz band, do not include
them in mesh beacon template formation.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/mesh.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 0cbe3260c5c1..04d3da733bc8 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -415,6 +415,10 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
if (!sband)
return -EINVAL;

+ /* HT not allowed in 6 GHz */
+ if (sband->band == NL80211_BAND_6GHZ)
+ return 0;
+
if (!sband->ht_cap.ht_supported ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -452,6 +456,10 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[channel->band];
ht_cap = &sband->ht_cap;

+ /* HT not allowed in 6 GHz */
+ if (sband->band == NL80211_BAND_6GHZ)
+ return 0;
+
if (!ht_cap->ht_supported ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -479,6 +487,10 @@ int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata,
if (!sband)
return -EINVAL;

+ /* VHT not allowed in 6 GHz */
+ if (sband->band == NL80211_BAND_6GHZ)
+ return 0;
+
if (!sband->vht_cap.vht_supported ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -516,6 +528,10 @@ int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[channel->band];
vht_cap = &sband->vht_cap;

+ /* VHT not allowed in 6 GHz */
+ if (sband->band == NL80211_BAND_6GHZ)
+ return 0;
+
if (!vht_cap->vht_supported ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
--
2.7.4

2020-05-13 19:47:18

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 08/11] mac80211: build HE operation with 6 GHz oper information

Add 6 GHz operation information (IEEE 802.11ax/D6.0, Figure 9-787k)
while building HE operation element for non-HE AP. This field is used to
determine channel information in the absence of HT/VHT IEs.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/mesh.c | 11 +++++---
net/mac80211/util.c | 63 +++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6517a56970b7..0bb442feb1db 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2175,7 +2175,7 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
const struct ieee80211_sta_he_cap *he_cap,
u8 *end);
u8 *ieee80211_ie_build_he_6ghz_band_cap(u8 *pos, u16 he_6ghz_cap);
-u8 *ieee80211_ie_build_he_oper(u8 *pos);
+u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef);
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
const struct ieee80211_supported_band *sband,
const u8 *srates, int srates_len, u32 *rates);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2ca34869538d..0cbe3260c5c1 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -565,6 +565,7 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
{
const struct ieee80211_sta_he_cap *he_cap;
struct ieee80211_supported_band *sband;
+ u32 len;
u8 *pos;

sband = ieee80211_get_sband(sdata);
@@ -578,11 +579,15 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
return 0;

- if (skb_tailroom(skb) < 2 + 1 + sizeof(struct ieee80211_he_operation))
+ len = 2 + 1 + sizeof(struct ieee80211_he_operation);
+ if (sdata->vif.bss_conf.chandef.chan->band == NL80211_BAND_6GHZ)
+ len += sizeof(struct ieee80211_he_oper_6ghz_op_info);
+
+ if (skb_tailroom(skb) < len)
return -ENOMEM;

- pos = skb_put(skb, 2 + 1 + sizeof(struct ieee80211_he_operation));
- ieee80211_ie_build_he_oper(pos);
+ pos = skb_put(skb, len);
+ ieee80211_ie_build_he_oper(pos, &sdata->vif.bss_conf.chandef);

return 0;
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2bcebe672c0d..90b8c42b1aa8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2977,13 +2977,18 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
return pos + sizeof(struct ieee80211_vht_operation);
}

-u8 *ieee80211_ie_build_he_oper(u8 *pos)
+u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef)
{
struct ieee80211_he_operation *he_oper;
+ struct ieee80211_he_oper_6ghz_op_info *he_6ghz_op;
u32 he_oper_params;
+ u8 ie_len = 1 + sizeof(struct ieee80211_he_operation);
+
+ if (chandef->chan->band == NL80211_BAND_6GHZ)
+ ie_len += sizeof(struct ieee80211_he_oper_6ghz_op_info);

*pos++ = WLAN_EID_EXTENSION;
- *pos++ = 1 + sizeof(struct ieee80211_he_operation);
+ *pos++ = ie_len;
*pos++ = WLAN_EID_EXT_HE_OPERATION;

he_oper_params = 0;
@@ -2993,16 +2998,66 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos)
IEEE80211_HE_OPERATION_ER_SU_DISABLE);
he_oper_params |= u32_encode_bits(1,
IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED);
+ if (chandef->chan->band == NL80211_BAND_6GHZ)
+ he_oper_params |= u32_encode_bits(1,
+ IEEE80211_HE_OPERATION_6GHZ_OP_INFO);

he_oper = (struct ieee80211_he_operation *)pos;
he_oper->he_oper_params = cpu_to_le32(he_oper_params);

/* don't require special HE peer rates */
he_oper->he_mcs_nss_set = cpu_to_le16(0xffff);
+ pos += sizeof(struct ieee80211_he_operation);

- /* TODO add VHT operational and 6GHz operational subelement? */
+ if (chandef->chan->band != NL80211_BAND_6GHZ)
+ goto out;

- return pos + sizeof(struct ieee80211_vht_operation);
+ /* TODO add VHT operational */
+ he_6ghz_op = (struct ieee80211_he_oper_6ghz_op_info *)pos;
+ he_6ghz_op->min_rate = 6; /* 6 Mbps */
+ he_6ghz_op->primary_chan =
+ ieee80211_frequency_to_channel(chandef->chan->center_freq);
+ he_6ghz_op->center_freq_seg0_idx =
+ ieee80211_frequency_to_channel(chandef->center_freq1);
+ if (chandef->center_freq2)
+ he_6ghz_op->center_freq_seg1_idx =
+ ieee80211_frequency_to_channel(chandef->center_freq2);
+ else
+ he_6ghz_op->center_freq_seg1_idx = 0;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_160:
+ /* Convert 160 MHz channel width to new style as interop
+ * workaround.
+ */
+ he_6ghz_op->control =
+ IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ;
+ he_6ghz_op->center_freq_seg1_idx =
+ he_6ghz_op->center_freq_seg0_idx;
+ if (chandef->chan->center_freq < chandef->center_freq1)
+ he_6ghz_op->center_freq_seg0_idx -= 8;
+ else
+ he_6ghz_op->center_freq_seg0_idx += 8;
+ fallthrough;
+ case NL80211_CHAN_WIDTH_80P80:
+ he_6ghz_op->control =
+ IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ he_6ghz_op->control = IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ he_6ghz_op->control = IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ;
+ break;
+ default:
+ he_6ghz_op->control = IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ;
+ break;
+ }
+
+ pos += sizeof(struct ieee80211_he_oper_6ghz_op_info);
+
+out:
+ return pos;
}

bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
--
2.7.4

2020-05-13 19:49:20

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 04/11] mac80211: add HE 6 GHz Band Capabilities into parse extension

Handle 6 GHz band capability element parsing for association.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/linux/ieee80211.h | 1 +
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/util.c | 4 ++++
3 files changed, 6 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 77462dff6db3..86b094738ce9 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2614,6 +2614,7 @@ enum ieee80211_eid_ext {
WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
WLAN_EID_EXT_NON_INHERITANCE = 56,
+ WLAN_EID_EXT_HE_6GHZ_BAND_CAP = 59,
};

/* Action category code */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f8ed4f621f7f..5e33746d7210 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1491,6 +1491,7 @@ struct ieee802_11_elems {
const struct ieee80211_he_operation *he_operation;
const struct ieee80211_he_spr *he_spr;
const struct ieee80211_mu_edca_param_set *mu_edca_param_set;
+ const struct ieee80211_he_6ghz_band_cap *he_6ghz_cap_elem;
const u8 *uora_element;
const u8 *mesh_id;
const u8 *peering;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 20436c86b9bf..5a33755c22f4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -936,6 +936,10 @@ static void ieee80211_parse_extension_element(u32 *crc,
len >= ieee80211_he_spr_size(data))
elems->he_spr = data;
break;
+ case WLAN_EID_EXT_HE_6GHZ_BAND_CAP:
+ if (len == sizeof(struct ieee80211_he_6ghz_band_cap))
+ elems->he_6ghz_cap_elem = data;
+ break;
}
}

--
2.7.4

2020-05-13 19:49:20

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 03/11] nl80211: add HE 6 GHz Band Capability support

Define new structures for HE 6 GHz band capabilities as per
IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element
and 6 GHz Operation Information field of HE operation element
(IEEE P802.11ax/D6.0, Figure 9-787k).

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/linux/ieee80211.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 16268ef1cbcc..77462dff6db3 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1632,6 +1632,44 @@ struct ieee80211_he_mcs_nss_supp {
} __packed;

/**
+ * enum ieee80211_he_6ghz_chanwidth - HE 6 GHz channel width
+ * @IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ: 20 MHz bandwidth
+ * @IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ: 40 MHz bandwidth
+ * @IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ: 80 MHz bandwidth
+ * @IEEE80211_HE_6GHZ_CHANWIDTH_80P80MHZ: 160 or 80+80 MHz bandwidth
+ */
+enum ieee80211_he_6ghz_chanwidth {
+ IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ = 0,
+ IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ = 1,
+ IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ = 2,
+ IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ = 3,
+};
+
+/**
+ * struct ieee80211_he_oper_6ghz_op_info - 6 GHz Operation Information
+ *
+ * This structure is defined as described in IEEE P802.11ax/D6.0,
+ * Figure 9-787k—6 GHz Operation Information field.
+ *
+ * @primary_chan: The channel number of the primary channel in the 6 GHz band.
+ * @control: First two bits defines channel width field indicates the BSS
+ * channel width and is set to 0 for 20 MHz, 1 for 40 MHz, 2 for 80 MHz,
+ * and 3 for 80+80 or 160 MHz.
+ * @center_freq_seg0_idx: Channel center frequency index for the 20 MHz,
+ * 40 MHz, or 80 MHz, or 80+80 MHz.
+ * @center_freq_seg1_idx: Channel center frequency index of the 160 MHz.
+ * @min_rate: Minimum rate, in units of 1 Mb/s, that the non-AP STA is allowed
+ * to use for sending PPDUs.
+ */
+struct ieee80211_he_oper_6ghz_op_info {
+ u8 primary_chan;
+ u8 control;
+ u8 center_freq_seg0_idx;
+ u8 center_freq_seg1_idx;
+ u8 min_rate;
+} __packed;
+
+/**
* struct ieee80211_he_operation - HE capabilities element
*
* This structure is the "HE operation element" fields as
@@ -1682,6 +1720,15 @@ struct ieee80211_mu_edca_param_set {
struct ieee80211_he_mu_edca_param_ac_rec ac_vo;
} __packed;

+/**
+ * struct ieee80211_he_6ghz_band_cap - HE 6 GHz Band Capabilities element
+ *
+ * This structure is defined as described in IEEE P802.11ax/D6.0, 9.4.2.261.
+ */
+struct ieee80211_he_6ghz_band_cap {
+ __le16 capab;
+} __packed;
+
/* 802.11ac VHT Capabilities */
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
@@ -1982,6 +2029,15 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
#define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0
#define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800

+/* 802.11ax HE 6 GHz Band Capability */
+#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK GENMASK(2, 0)
+#define IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK GENMASK(5, 3)
+#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK GENMASK(7, 6)
+#define IEEE80211_HE_6GHZ_CAP_SMPS_MASK GENMASK(10, 9)
+#define IEEE80211_HE_6GHZ_CAP_RD_RESP BIT(11)
+#define IEEE80211_HE_6GHZ_CAP_RX_ANTENNA_PATTERN BIT(12)
+#define IEEE80211_HE_6GHZ_CAP_TX_ANTENNA_PATTERN BIT(13)
+
/* TX/RX HE MCS Support field Highest MCS subfield encoding */
enum ieee80211_he_highest_mcs_supported_subfield_enc {
HIGHEST_MCS_SUPPORTED_MCS7 = 0,
@@ -2059,6 +2115,7 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24
#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000
#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x80000000
+#define IEEE80211_HE_OPERATION_6GHZ_OP_INFO_CTRL_CHAN_WIDTH 0x3

/*
* ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
--
2.7.4

2020-05-13 19:49:20

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 06/11] mac80211: handle HE 6 GHz Capability in HE STA processing

During association or mesh peering of HE STA in 6 GHz band, required
HT/VHT information has to be processed from 6 GHz band capabilities
as HT/VHT IEs are not allowed in 6 GHz.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/net/cfg80211.h | 10 +++++++++
net/mac80211/cfg.c | 3 ++-
net/mac80211/he.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mesh_plink.c | 4 +++-
net/mac80211/mlme.c | 1 +
6 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0797a296c083..2c7bfc170604 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -332,15 +332,25 @@ struct ieee80211_sta_vht_cap {
* to describe 802.11ax HE capabilities for a STA.
*
* @has_he: true iff HE data is valid.
+ * @has_he_6ghz: true iff HE 6 GHz data is valid.
* @he_cap_elem: Fixed portion of the HE capabilities element.
* @he_mcs_nss_supp: The supported NSS/MCS combinations.
* @ppe_thres: Holds the PPE Thresholds data.
+ * @ampdu_factor: Maximum A-MPDU length factor used in 6 GHz.
+ * @ampdu_density: Minimum A-MPDU spacing used in 6 GHz.
+ * @cap: HE 6 GHz Band capability.
*/
struct ieee80211_sta_he_cap {
bool has_he;
+ bool has_he_6ghz;
struct ieee80211_he_cap_elem he_cap_elem;
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
+ struct {
+ u8 ampdu_factor;
+ u8 ampdu_density;
+ u16 cap;
+ } he_6ghz;
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0f72813fed53..591c3c7324e3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1508,7 +1508,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
if (params->he_capa)
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
(void *)params->he_capa,
- params->he_capa_len, sta);
+ params->he_capa_len,
+ params->he_6ghz_capa, sta);

if (params->opmode_notif_used) {
/* returned value is only needed for rc update, but the
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index f520552b22be..4376fa5e6336 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -12,10 +12,14 @@ void
ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
const u8 *he_cap_ie, u8 he_cap_len,
+ const struct ieee80211_he_6ghz_band_cap
+ *he_6ghz_cap_ie,
struct sta_info *sta)
{
struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
+ enum ieee80211_smps_mode smps_mode;
+ u16 cap;
u8 he_ppe_size;
u8 mcs_nss_size;
u8 he_total_size;
@@ -53,6 +57,53 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,

sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+
+ if (!he_6ghz_cap_ie)
+ return;
+
+ cap = __le16_to_cpu(he_6ghz_cap_ie->capab);
+
+ he_cap->he_6ghz.ampdu_density =
+ FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK,
+ cap);
+ he_cap->he_6ghz.ampdu_factor =
+ FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ cap);
+
+ switch (FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK, cap)) {
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
+ sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ break;
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
+ sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ break;
+ case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
+ default:
+ sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ break;
+ }
+
+ switch (FIELD_GET(IEEE80211_HE_6GHZ_CAP_SMPS_MASK, cap)) {
+ case WLAN_HT_CAP_SM_PS_INVALID:
+ case WLAN_HT_CAP_SM_PS_STATIC:
+ smps_mode = IEEE80211_SMPS_STATIC;
+ break;
+ case WLAN_HT_CAP_SM_PS_DYNAMIC:
+ smps_mode = IEEE80211_SMPS_DYNAMIC;
+ break;
+ case WLAN_HT_CAP_SM_PS_DISABLED:
+ smps_mode = IEEE80211_SMPS_OFF;
+ break;
+ }
+
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sta->sta.smps_mode = smps_mode;
+ else
+ sta->sta.smps_mode = IEEE80211_SMPS_OFF;
+
+ he_cap->he_6ghz.cap = cap;
+ he_cap->has_he_6ghz = true;
}

void
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5e33746d7210..78a95a11458c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1892,6 +1892,8 @@ void
ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
const u8 *he_cap_ie, u8 he_cap_len,
+ const struct ieee80211_he_6ghz_band_cap
+ *he_6ghz_cap_ie,
struct sta_info *sta);
void
ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 737c5f4dbf52..e3e29b8d641d 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -441,7 +441,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
elems->vht_cap_elem, sta);

ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
- elems->he_cap_len, sta);
+ elems->he_cap_len,
+ elems->he_6ghz_cap_elem,
+ sta);

if (bw != sta->sta.bandwidth)
changed |= IEEE80211_RC_BW_CHANGED;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 16d75da0996a..58a082efc3b3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3381,6 +3381,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
elems->he_cap,
elems->he_cap_len,
+ elems->he_6ghz_cap_elem,
sta);

bss_conf->he_support = sta->sta.he_cap.has_he;
--
2.7.4

2020-05-13 19:49:20

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 07/11] mac80211: add HE 6 GHz Band Capability IE in Assoc. Request

Construct HE 6 GHz band capability element element (IEEE 802.11ax/D6.0,
9.4.2.261) for association request and mesh beacon. The 6 GHz capability
information is passed by driver through iftypes caps.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mesh.c | 34 ++++++++++++++++++++++++++++++++++
net/mac80211/mesh.h | 2 ++
net/mac80211/mesh_plink.c | 3 ++-
net/mac80211/mlme.c | 12 ++++++++++--
net/mac80211/util.c | 15 +++++++++++++++
6 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 78a95a11458c..6517a56970b7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2174,6 +2174,7 @@ u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
u8 *ieee80211_ie_build_he_cap(u8 *pos,
const struct ieee80211_sta_he_cap *he_cap,
u8 *end);
+u8 *ieee80211_ie_build_he_6ghz_band_cap(u8 *pos, u16 he_6ghz_cap);
u8 *ieee80211_ie_build_he_oper(u8 *pos);
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
const struct ieee80211_supported_band *sband,
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 36978a0e5000..2ca34869538d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -587,6 +587,39 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
return 0;
}

+int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
+{
+ const struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_supported_band *sband;
+ u8 ie_len;
+ u8 *pos;
+
+ sband = ieee80211_get_sband(sdata);
+ if (!sband)
+ return -EINVAL;
+
+ he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
+
+ if (!he_cap ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
+ return 0;
+
+ if (!he_cap->has_he_6ghz)
+ return 0;
+
+ ie_len = 2 + 1 + sizeof(struct ieee80211_he_6ghz_band_cap);
+ if (skb_tailroom(skb) < ie_len)
+ return -ENOMEM;
+
+ pos = skb_put(skb, ie_len);
+ ieee80211_ie_build_he_6ghz_band_cap(pos, he_cap->he_6ghz.cap);
+
+ return 0;
+}
+
static void ieee80211_mesh_path_timer(struct timer_list *t)
{
struct ieee80211_sub_if_data *sdata =
@@ -885,6 +918,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
mesh_add_vht_oper_ie(sdata, skb) ||
mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
mesh_add_he_oper_ie(sdata, skb) ||
+ mesh_add_he_6ghz_cap_ie(sdata, skb) ||
mesh_add_vendor_ies(sdata, skb))
goto out_free;

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 953f720754e8..40492d1bd8fd 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -222,6 +222,8 @@ int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u8 ie_len);
int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index e3e29b8d641d..dedb2341ebdd 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -328,7 +328,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
mesh_add_vht_cap_ie(sdata, skb) ||
mesh_add_vht_oper_ie(sdata, skb) ||
mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
- mesh_add_he_oper_ie(sdata, skb))
+ mesh_add_he_oper_ie(sdata, skb) ||
+ mesh_add_he_6ghz_cap_ie(sdata, skb))
goto free;
}

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 58a082efc3b3..b4dfefd482a6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -654,6 +654,12 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
he_cap->he_cap_elem.phy_cap_info);
pos = skb_put(skb, he_cap_size);
ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
+
+ if (!he_cap->has_he_6ghz)
+ return;
+
+ pos = skb_put(skb, 5); /* 2 + 1 + sizeof(he_cap->he_6ghz.cap) */
+ ieee80211_ie_build_he_6ghz_band_cap(pos, he_cap->he_6ghz.cap);
}

static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
@@ -4803,7 +4809,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
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->band != NL80211_BAND_6GHZ)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
}

if (!sband->vht_cap.vht_supported)
@@ -5493,7 +5500,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & ASSOC_REQ_DISABLE_HT) {
ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
- ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
+ if (sband->band != NL80211_BAND_6GHZ)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
}

if (req->flags & ASSOC_REQ_DISABLE_VHT)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5a33755c22f4..2bcebe672c0d 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2839,6 +2839,21 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
return pos;
}

+u8 *ieee80211_ie_build_he_6ghz_band_cap(u8 *pos, u16 he_6ghz_cap)
+{
+ __le16 cap = cpu_to_le16(he_6ghz_cap);
+
+ *pos++ = WLAN_EID_EXTENSION;
+ *pos++ = 3;
+ *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
+
+ /* Fixed data */
+ memcpy(pos, &cap, sizeof(cap));
+ pos += sizeof(cap);
+
+ return pos;
+}
+
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
const struct cfg80211_chan_def *chandef,
u16 prot_mode, bool rifs_mode)
--
2.7.4

2020-05-13 19:49:26

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH v3 11/11] ath11k: build HE 6 GHz capability

Build 6 GHz band capability from HT and VHT capabilities reported
by firmware.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/mac.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 6e7b8ecd09a6..3325e692f7fd 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -537,6 +537,7 @@ struct ath11k_band_cap {
u32 he_mcs;
u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE];
struct ath11k_ppe_threshold he_ppet;
+ u16 he_6ghz_cap;
};

struct ath11k_pdev_cap {
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 06d063274eea..8babba45d879 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3522,6 +3522,34 @@ ath11k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
he_cap_elem->phy_cap_info[9] &= ~m;
}

+static u16 ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap *pcap,
+ struct ath11k_band_cap *bcap)
+{
+ u8 val;
+
+ bcap->he_6ghz_cap = IEEE80211_HT_MPDU_DENSITY_NONE;
+ if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
+ bcap->he_6ghz_cap |=
+ FIELD_PREP(IEEE80211_HE_6GHZ_CAP_SMPS_MASK,
+ WLAN_HT_CAP_SM_PS_DYNAMIC);
+ val = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ pcap->vht_cap);
+ bcap->he_6ghz_cap |=
+ FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ val);
+ val = FIELD_GET(IEEE80211_VHT_CAP_MAX_MPDU_MASK, pcap->vht_cap);
+ bcap->he_6ghz_cap |=
+ FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK, val);
+ if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)
+ bcap->he_6ghz_cap |=
+ IEEE80211_HE_6GHZ_CAP_RX_ANTENNA_PATTERN;
+ if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)
+ bcap->he_6ghz_cap |=
+ IEEE80211_HE_6GHZ_CAP_TX_ANTENNA_PATTERN;
+
+ return bcap->he_6ghz_cap;
+}
+
static int ath11k_mac_copy_he_cap(struct ath11k *ar,
struct ath11k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
@@ -3602,6 +3630,12 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
ath11k_gen_ppe_thresh(&band_cap->he_ppet,
he_cap->ppe_thres);
+
+ if (band == NL80211_BAND_6GHZ) {
+ he_cap->has_he_6ghz = true;
+ he_cap->he_6ghz.cap =
+ ath11k_mac_setup_he_6ghz_cap(cap, band_cap);
+ }
idx++;
}

--
2.7.4

2020-05-27 13:47:31

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 01/11] cfg80211: use only HE capability to set prohibited flags in 6 GHz

Hi,

This is what we have in this area:
https://p.sipsolutions.net/d8e56772a261199a.txt

but I see it's also incomplete.

> +static bool cfg80211_is_6ghz_freq(u32 freq)
> +{
> + return (freq > 5940 && freq < 7105);
> +}

That doesn't really make sense, I don't want to see those hardcoded
frequencies all over the place.

> case NL80211_CHAN_WIDTH_40:
> width = 40;
> + if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {

You can check chandef->chan->band instead. (In fact, we did)

> + if (!he_cap)
> + return false;
> + if (!he_cap->has_he_6ghz)
> + return false;

I'm not sure you should even _get_ here with a 6 GHz channel if you
don't have 6 GHz capability? I mean, why did you register the channel in
the first place then? This seems unnecessarily complex. If the channel
didn't exist, it was rejected long before here.

However, looking at D6.0, maybe we do need some checks of the HE
capability?

> + if (!(he_cap->he_cap_elem.phy_cap_info[0] &
> + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
> + return false;

Looks like even D6.0 still changed something in this area...

Evidently our patch just assumed that in 6 GHz all of this is supported,
but the spec doesn't support that theory :-)

Can you respin this with D6.0 taken into account?

johannes

2020-05-27 14:03:01

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 02/11] cfg80211: handle 6 GHz capability of new station

On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
> Handle 6 GHz HE capability while adding new station. It will be used
> later in mac80211 station processing.

This doesn't compile without the next patch.

> + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capa;

This we made just an __le16, any particular reason to have the struct?
It does need to be a pointer for the "no changes" case, but the struct
seems a bit overkill?

> + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from
> + * association request when used with NL80211_CMD_NEW_STATION).

That we have pretty much identically.

> @@ -2998,6 +3003,7 @@ enum nl80211_attrs {
> #define NL80211_HE_MAX_CAPABILITY_LEN 54
> #define NL80211_MAX_NR_CIPHER_SUITES 5
> #define NL80211_MAX_NR_AKM_SUITES 2
> +#define NL80211_HE_6GHZ_CAPABILITY_LEN 2

This not, we defined it just to be a U16.

> + [NL80211_ATTR_HE_6GHZ_CAPABILITY] = {
> + .type = NLA_EXACT_LEN,
> + .len = NL80211_HE_6GHZ_CAPABILITY_LEN,
> + },

This no longer exists, but I guess I'll just take our patch for the U16
here.

> + /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
> + if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
> + return -EINVAL;

Not sure this makes much sense? We can only check what's being set at
the same time, so multiple calls here would still be possible ...
doesn't hurt much though.

We didn't have this check, and have one additional check:

@@ -6170,7 +6200,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
params.vht_capa = NULL;

/* HE requires WME */
- if (params.he_capa_len)
+ if (params.he_capa_len || params.he_6ghz_capa)
return -EINVAL;
}


johannes

2020-05-27 14:29:40

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 05/11] mac80211: fix memory overlap due to variable length param

On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
> As of now HE operation element in bss_conf includes variable length
> optional field followed by other HE variable. Though the optional
> field never be used, actually it is referring to next member of the
> bss_conf structure which is not correct. Fix it by declaring needed
> HE operation fields within bss_conf itself.

I had already applied this.

johannes

2020-05-27 14:29:40

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 04/11] mac80211: add HE 6 GHz Band Capabilities into parse extension

On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
> Handle 6 GHz band capability element parsing for association.

Yeah, pretty much have the same here...

johannes

2020-05-27 14:31:13

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 03/11] nl80211: add HE 6 GHz Band Capability support

On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
>
> /**
> + * enum ieee80211_he_6ghz_chanwidth - HE 6 GHz channel width
> + * @IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ: 20 MHz bandwidth
> + * @IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ: 40 MHz bandwidth
> + * @IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ: 80 MHz bandwidth
> + * @IEEE80211_HE_6GHZ_CHANWIDTH_80P80MHZ: 160 or 80+80 MHz bandwidth
> + */
> +enum ieee80211_he_6ghz_chanwidth {
> + IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ = 0,
> + IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ = 1,
> + IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ = 2,
> + IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ = 3,
> +};
> +
> +/**
> + * struct ieee80211_he_oper_6ghz_op_info - 6 GHz Operation Information
> + *
> + * This structure is defined as described in IEEE P802.11ax/D6.0,
> + * Figure 9-787k—6 GHz Operation Information field.
> + *
> + * @primary_chan: The channel number of the primary channel in the 6 GHz band.
> + * @control: First two bits defines channel width field indicates the BSS
> + * channel width and is set to 0 for 20 MHz, 1 for 40 MHz, 2 for 80 MHz,
> + * and 3 for 80+80 or 160 MHz.
> + * @center_freq_seg0_idx: Channel center frequency index for the 20 MHz,
> + * 40 MHz, or 80 MHz, or 80+80 MHz.
> + * @center_freq_seg1_idx: Channel center frequency index of the 160 MHz.
> + * @min_rate: Minimum rate, in units of 1 Mb/s, that the non-AP STA is allowed
> + * to use for sending PPDUs.
> + */
> +struct ieee80211_he_oper_6ghz_op_info {
> + u8 primary_chan;
> + u8 control;
> + u8 center_freq_seg0_idx;
> + u8 center_freq_seg1_idx;
> + u8 min_rate;
> +} __packed;
>

Looks like I had

+/**
+ * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
+ * @primary: primary channel
+ * @control: control flags
+ * @ccfs0: channel center frequency segment 0
+ * @ccfs1: channel center frequency segment 1
+ * @minrate: minimum rate (in 1 Mbps units)
+ */
+struct ieee80211_he_6ghz_oper {
+ u8 primary;
+#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH 0x3
+#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ 0
+#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ 1
+#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ 2
+#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3
+#define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4
+ u8 control;
+ u8 ccfs0;
+ u8 ccfs1;
+ u8 minrate;
+} __packed;


Any objection to that? The names are getting _really_ long the way you
had them ...

FWIW, I also had a fix in ieee80211_he_oper_size() where the size of the
oper is now sizeof(struct ieee80211_he_6ghz_oper).

And this, to find it:

+/**
+ * ieee80211_he_6ghz_oper - obtain 6 GHz operation field
+ * @he_oper: HE operation element (must be pre-validated for size)
+ * but may be %NULL
+ *
+ * Return: a pointer to the 6 GHz operation field, or %NULL
+ */
+static inline const struct ieee80211_he_6ghz_oper *
+ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper)
+{
+ const u8 *ret = (void *)&he_oper->optional;
+ u32 he_oper_params;
+
+ if (!he_oper)
+ return NULL;
+
+ he_oper_params = le32_to_cpu(he_oper->he_oper_params);
+
+ if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO))
+ return NULL;
+ if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO)
+ ret += 3;
+ if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS)
+ ret++;
+
+ return (void *)ret;
+}
+


> #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
> #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
> @@ -1982,6 +2029,15 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
> #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0
> #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800
>
> +/* 802.11ax HE 6 GHz Band Capability */
> +#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK GENMASK(2, 0)
> +#define IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK GENMASK(5, 3)
> +#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK GENMASK(7, 6)
> +#define IEEE80211_HE_6GHZ_CAP_SMPS_MASK GENMASK(10, 9)
> +#define IEEE80211_HE_6GHZ_CAP_RD_RESP BIT(11)
> +#define IEEE80211_HE_6GHZ_CAP_RX_ANTENNA_PATTERN BIT(12)
> +#define IEEE80211_HE_6GHZ_CAP_TX_ANTENNA_PATTERN BIT(13)

I don't like GENMASK() much ... but ok. FWIW, I had

+struct ieee80211_he_6ghz_capa {
+ /* uses IEEE80211_HE_6GHZ_CAP_* below */
+ __le16 capa;
+} __packed;
+
+/* HE 6 GHz band capabilities */
+/* uses enum ieee80211_min_mpdu_spacing values */
+#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START 0x0007
+/* uses enum ieee80211_vht_max_ampdu_length_exp values */
+#define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP 0x0038
+/* uses IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_* values */
+#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN 0x00c0
+/* WLAN_HT_CAP_SM_PS_* values */
+#define IEEE80211_HE_6GHZ_CAP_SM_PS_SHIFT 9
+#define IEEE80211_HE_6GHZ_CAP_SM_PS 0x0600
+#define IEEE80211_HE_6GHZ_CAP_RD_RESPONDER 0x0800
+#define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS 0x1000
+#define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS 0x2000


again, just shorter names ...


johannes

2020-05-27 14:33:57

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 08/11] mac80211: build HE operation with 6 GHz oper information

On Wed, 2020-05-13 at 12:45 -0700, Rajkumar Manoharan wrote:
> Add 6 GHz operation information (IEEE 802.11ax/D6.0, Figure 9-787k)
> while building HE operation element for non-HE AP. This field is used to
> determine channel information in the absence of HT/VHT IEs.

We didn't have this at all since we focused on client side.

Looks good.

johannes

2020-05-27 14:38:20

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] mac80211: add HE 6 GHz Band Capability IE in Assoc. Request

On Wed, 2020-05-13 at 12:45 -0700, Rajkumar Manoharan wrote:

> +int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
> + struct sk_buff *skb)
> +{
> + const struct ieee80211_sta_he_cap *he_cap;
> + struct ieee80211_supported_band *sband;
> + u8 ie_len;
> + u8 *pos;
> +
> + sband = ieee80211_get_sband(sdata);
> + if (!sband)
> + return -EINVAL;
> +
> + he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
> +
> + if (!he_cap ||
> + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
> + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
> + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
> + return 0;
> +
> + if (!he_cap->has_he_6ghz)
> + return 0;

I saw this before and thought it may actually exist, but it doesn't?

Like I said before though, there doesn't seem much point in this, if you
don't have 6 GHz then don't advertise those channels ...

> static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
> @@ -4803,7 +4809,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
> 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->band != NL80211_BAND_6GHZ)
> + ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
> }
>
> if (!sband->vht_cap.vht_supported)
> @@ -5493,7 +5500,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
> if (req->flags & ASSOC_REQ_DISABLE_HT) {
> ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
> ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
> - ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
> + if (sband->band != NL80211_BAND_6GHZ)
> + ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
> }

These changes really sort of belong more into the next patch, I guess?
Not sure.


> if (req->flags & ASSOC_REQ_DISABLE_VHT)
> diff --git a/net/mac80211/util.c b/net/mac80211/util.c
> index 5a33755c22f4..2bcebe672c0d 100644
> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -2839,6 +2839,21 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
> return pos;
> }
>
> +u8 *ieee80211_ie_build_he_6ghz_band_cap(u8 *pos, u16 he_6ghz_cap)
> +{
> + __le16 cap = cpu_to_le16(he_6ghz_cap);
> +
> + *pos++ = WLAN_EID_EXTENSION;
> + *pos++ = 3;
> + *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
> +
> + /* Fixed data */
> + memcpy(pos, &cap, sizeof(cap));
> + pos += sizeof(cap);
> +
> + return pos;
> +}

You forgot SMPS, so this needs to be a bit different, but it's probably
better as a separate function since it's in multiple places, I guess
I'll combine our two patches.

johannes

2020-05-27 14:44:12

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

On Wed, 2020-05-13 at 12:45 -0700, Rajkumar Manoharan wrote:
> In 6 GHz band, determine chandef from 6 GHz operation information
> of HE operation element.

So here we get to real differences ...

> Reported-by: kernel test robot <[email protected]>

Huh?

> +bool ieee80211_chandef_he_oper(struct ieee80211_sub_if_data *sdata,
> + const struct ieee80211_he_operation *heop,
> + struct cfg80211_chan_def *chandef)
> +{
> + struct ieee80211_he_oper_6ghz_op_info info;
> + const struct ieee80211_sta_he_cap *he_cap;
> + struct ieee80211_supported_band *sband;
> + struct cfg80211_chan_def new = *chandef;
> + int cf0, cf1;
> + int ccf0, ccf1;
> + bool support_80_80;
> + bool support_160;
> + u8 he_phy_cap;
> + u8 pos = 0;
> +
> + /* Below HE Operation check is required only for 6 GHz band */
> + if (chandef->chan->band != NL80211_BAND_6GHZ)
> + return true;
> +
> + if (!heop)
> + return false;
> +
> + sband = sdata->local->hw.wiphy->bands[chandef->chan->band];
> + if (!sband)
> + return false;
> +
> + he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type);
> + if (!he_cap)
> + return false;
> +
> + if (!(le32_to_cpu(heop->he_oper_params) &
> + IEEE80211_HE_OPERATION_6GHZ_OP_INFO))
> + return false;
> +
> + he_phy_cap = he_cap->he_cap_elem.phy_cap_info[0];
> + support_160 =
> + !!(he_phy_cap &
> + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
> + support_80_80 =
> + !!(he_phy_cap &
> + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G);
> +
> + if (le32_to_cpu(heop->he_oper_params) &
> + IEEE80211_HE_OPERATION_VHT_OPER_INFO)
> + pos += 3;
> + if (le32_to_cpu(heop->he_oper_params) &
> + IEEE80211_HE_OPERATION_CO_HOSTED_BSS)
> + pos += 1;

This really gets better with the ieee80211_he_6ghz_oper() inline I wrote
and posted in the other reply.

> + case IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ:
> + new.center_freq1 = cf0;
> + new.width = NL80211_CHAN_WIDTH_80;
> + if (ccf1) {
> + unsigned int diff;
> +
> + diff = abs(ccf1 - ccf0);
> + if (diff == 8 && support_160) {
> + new.width = NL80211_CHAN_WIDTH_160;
> + new.center_freq1 = cf1;
> + } else if ((diff > 8) && support_80_80) {
> + new.width = NL80211_CHAN_WIDTH_80P80;
> + new.center_freq2 = cf1;
> + }
> + }

Hmm. Yes, we just had

+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ:
+ if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8)
+ he_chandef.width = NL80211_CHAN_WIDTH_160;
+ else
+ he_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ break;


but that breaks if you don't support 80+80 or 160.

OTOH, we check this later again, I think, and downgrade if we don't
support it, so no harm done?

I think I'd prefer the parsing to be exact, and then downgrade as
necessary. That makes things a bit simpler.

That may mean the place where you call this should be different though.

johannes

2020-05-27 14:44:23

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 06/11] mac80211: handle HE 6 GHz Capability in HE STA processing

On Wed, 2020-05-13 at 12:45 -0700, Rajkumar Manoharan wrote:
> During association or mesh peering of HE STA in 6 GHz band, required
> HT/VHT information has to be processed from 6 GHz band capabilities
> as HT/VHT IEs are not allowed in 6 GHz.
>
> * @has_he: true iff HE data is valid.
> + * @has_he_6ghz: true iff HE 6 GHz data is valid.

I guess here things start compiling ;-)

But like I said before, I'm not sure why this is needed?

Surely if the STA connected on 6 GHz it has capability ...

johannes

2020-05-27 14:46:04

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

Oh, that was the last patch, ok.

So let's hear what you want to say regarding my comments - but please
don't respin.

I will put some order into our patches tomorrow and post them, or
perhaps better, post a combined series of yours and mine.

Sounds OK?

johannes

2020-05-27 19:18:21

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH v3 03/11] nl80211: add HE 6 GHz Band Capability support

On 2020-05-27 07:27, Johannes Berg wrote:
> On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
>>
>> /**
>> + * enum ieee80211_he_6ghz_chanwidth - HE 6 GHz channel width
>> + * @IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ: 20 MHz bandwidth
>> + * @IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ: 40 MHz bandwidth
>> + * @IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ: 80 MHz bandwidth
>> + * @IEEE80211_HE_6GHZ_CHANWIDTH_80P80MHZ: 160 or 80+80 MHz bandwidth
>> + */
>> +enum ieee80211_he_6ghz_chanwidth {
>> + IEEE80211_HE_6GHZ_CHANWIDTH_20MHZ = 0,
>> + IEEE80211_HE_6GHZ_CHANWIDTH_40MHZ = 1,
>> + IEEE80211_HE_6GHZ_CHANWIDTH_80MHZ = 2,
>> + IEEE80211_HE_6GHZ_CHANWIDTH_160MHZ_80P80MHZ = 3,
>> +};
>> +
>> +/**
>> + * struct ieee80211_he_oper_6ghz_op_info - 6 GHz Operation
>> Information
>> + *
>> + * This structure is defined as described in IEEE P802.11ax/D6.0,
>> + * Figure 9-787k—6 GHz Operation Information field.
>> + *
>> + * @primary_chan: The channel number of the primary channel in the 6
>> GHz band.
>> + * @control: First two bits defines channel width field indicates the
>> BSS
>> + * channel width and is set to 0 for 20 MHz, 1 for 40 MHz, 2 for 80
>> MHz,
>> + * and 3 for 80+80 or 160 MHz.
>> + * @center_freq_seg0_idx: Channel center frequency index for the 20
>> MHz,
>> + * 40 MHz, or 80 MHz, or 80+80 MHz.
>> + * @center_freq_seg1_idx: Channel center frequency index of the 160
>> MHz.
>> + * @min_rate: Minimum rate, in units of 1 Mb/s, that the non-AP STA
>> is allowed
>> + * to use for sending PPDUs.
>> + */
>> +struct ieee80211_he_oper_6ghz_op_info {
>> + u8 primary_chan;
>> + u8 control;
>> + u8 center_freq_seg0_idx;
>> + u8 center_freq_seg1_idx;
>> + u8 min_rate;
>> +} __packed;
>>
>
> Looks like I had
>
> +/**
> + * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
> + * @primary: primary channel
> + * @control: control flags
> + * @ccfs0: channel center frequency segment 0
> + * @ccfs1: channel center frequency segment 1
> + * @minrate: minimum rate (in 1 Mbps units)
> + */
> +struct ieee80211_he_6ghz_oper {
> + u8 primary;
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH 0x3
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ
> 0
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ
> 1
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ
> 2
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ
> 3
> +#define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4
> + u8 control;
> + u8 ccfs0;
> + u8 ccfs1;
> + u8 minrate;
> +} __packed;
>
>
> Any objection to that? The names are getting _really_ long the way you
> had them ...
>
Neat.. LGTM.. :)

> FWIW, I also had a fix in ieee80211_he_oper_size() where the size of
> the
> oper is now sizeof(struct ieee80211_he_6ghz_oper).
>
> And this, to find it:
>
> +/**
> + * ieee80211_he_6ghz_oper - obtain 6 GHz operation field
> + * @he_oper: HE operation element (must be pre-validated for size)
> + * but may be %NULL
> + *
> + * Return: a pointer to the 6 GHz operation field, or %NULL
> + */
> +static inline const struct ieee80211_he_6ghz_oper *
> +ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper)
> +{
> + const u8 *ret = (void *)&he_oper->optional;
> + u32 he_oper_params;
> +
> + if (!he_oper)
> + return NULL;
> +
> + he_oper_params = le32_to_cpu(he_oper->he_oper_params);
> +
> + if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO))
> + return NULL;
> + if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO)
> + ret += 3;
> + if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS)
> + ret++;
> +
> + return (void *)ret;
> +}
> +
>
Great.

>
>> #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
>> #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
>> @@ -1982,6 +2029,15 @@ int ieee80211_get_vht_max_nss(struct
>> ieee80211_vht_cap *cap,
>> #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0
>> #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800
>>
>> +/* 802.11ax HE 6 GHz Band Capability */
>> +#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK GENMASK(2,
>> 0)
>> +#define
>> IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK GENMASK(5, 3)
>> +#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK GENMASK(7, 6)
>> +#define IEEE80211_HE_6GHZ_CAP_SMPS_MASK GENMASK(10, 9)
>> +#define IEEE80211_HE_6GHZ_CAP_RD_RESP BIT(11)
>> +#define IEEE80211_HE_6GHZ_CAP_RX_ANTENNA_PATTERN BIT(12)
>> +#define IEEE80211_HE_6GHZ_CAP_TX_ANTENNA_PATTERN BIT(13)
>
> I don't like GENMASK() much ... but ok. FWIW, I had
>
Hope GENMASK defined in backports for older kernel. I started using this
since ath11k.
I feel GENMASK is more user readable and avoid masking errors.

> +struct ieee80211_he_6ghz_capa {
> + /* uses IEEE80211_HE_6GHZ_CAP_* below */
> + __le16 capa;
> +} __packed;
> +
> +/* HE 6 GHz band capabilities */
> +/* uses enum ieee80211_min_mpdu_spacing values */
> +#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START 0x0007
> +/* uses enum ieee80211_vht_max_ampdu_length_exp values */
> +#define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP 0x0038
> +/* uses IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_* values */
> +#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN 0x00c0
> +/* WLAN_HT_CAP_SM_PS_* values */
> +#define IEEE80211_HE_6GHZ_CAP_SM_PS_SHIFT 9
> +#define IEEE80211_HE_6GHZ_CAP_SM_PS 0x0600
> +#define IEEE80211_HE_6GHZ_CAP_RD_RESPONDER 0x0800
> +#define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS 0x1000
> +#define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS 0x2000
>
>
> again, just shorter names ...
>
I am fine with this.. Leave it to you. Cheers.

-Rajkumar

2020-05-27 19:22:41

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

On Wed, 2020-05-27 at 11:34 -0700, Rajkumar Manoharan wrote:
> On 2020-05-27 07:44, Johannes Berg wrote:
> > Oh, that was the last patch, ok.
> >
> > So let's hear what you want to say regarding my comments - but please
> > don't respin.
> >
> > I will put some order into our patches tomorrow and post them, or
> > perhaps better, post a combined series of yours and mine.
> >
> > Sounds OK?
> >
> Sounds great. There is one more followup patch I posted later. Sorry for
> that..
> This is needed to propagate HE 6 GHz cap to user space.
>
> https://patchwork.kernel.org/patch/11569921/

Oh right, I saw that, just hadn't really looked at it yet.

> As you aware that the related hostapd series were submitted.
>
> http://patchwork.ozlabs.org/project/hostap/list/?series=179527

Yeah, haven't looked either.

Thanks!

johannes

2020-05-27 19:23:48

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

On 2020-05-27 07:44, Johannes Berg wrote:
> Oh, that was the last patch, ok.
>
> So let's hear what you want to say regarding my comments - but please
> don't respin.
>
> I will put some order into our patches tomorrow and post them, or
> perhaps better, post a combined series of yours and mine.
>
> Sounds OK?
>
Sounds great. There is one more followup patch I posted later. Sorry for
that..
This is needed to propagate HE 6 GHz cap to user space.

https://patchwork.kernel.org/patch/11569921/

As you aware that the related hostapd series were submitted.

http://patchwork.ozlabs.org/project/hostap/list/?series=179527

-Rajkumar

2020-05-27 23:28:07

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH v3 02/11] cfg80211: handle 6 GHz capability of new station

On 2020-05-27 07:00, Johannes Berg wrote:
> On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
>> Handle 6 GHz HE capability while adding new station. It will be used
>> later in mac80211 station processing.
>
> This doesn't compile without the next patch.
>
My bad.. I must have overlooked while splitting the patch. :(

>> + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capa;
>
> This we made just an __le16, any particular reason to have the struct?
> It does need to be a pointer for the "no changes" case, but the struct
> seems a bit overkill?
>
Initially I thought of splitting into two u8 for a_mpdu_params and info.
Later changed to __le16 but retained struct. Nothing else :)

>> + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element
>> (from
>> + * association request when used with NL80211_CMD_NEW_STATION).
>
> That we have pretty much identically.
>
>> @@ -2998,6 +3003,7 @@ enum nl80211_attrs {
>> #define NL80211_HE_MAX_CAPABILITY_LEN 54
>> #define NL80211_MAX_NR_CIPHER_SUITES 5
>> #define NL80211_MAX_NR_AKM_SUITES 2
>> +#define NL80211_HE_6GHZ_CAPABILITY_LEN 2
>
> This not, we defined it just to be a U16.
>
>> + [NL80211_ATTR_HE_6GHZ_CAPABILITY] = {
>> + .type = NLA_EXACT_LEN,
>> + .len = NL80211_HE_6GHZ_CAPABILITY_LEN,
>> + },
>
> This no longer exists, but I guess I'll just take our patch for the U16
> here.
>
>> + /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
>> + if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
>> + return -EINVAL;
>
> Not sure this makes much sense? We can only check what's being set at
> the same time, so multiple calls here would still be possible ...
> doesn't hurt much though.
>
> We didn't have this check, and have one additional check:
>
> @@ -6170,7 +6200,7 @@ static int nl80211_new_station(struct sk_buff
> *skb, struct genl_info *info)
> params.vht_capa = NULL;
>
> /* HE requires WME */
> - if (params.he_capa_len)
> + if (params.he_capa_len || params.he_6ghz_capa)
> return -EINVAL;
> }
>
Fine. One more thing. Pradeep found that 6 GHz capability is not filled
in set_station.
Please handle that in your series. I'm fine with rest of the changes you
mentioned.

--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5893,6 +5893,10 @@ static int nl80211_set_station_tdls(struct
genl_info *info,
return -EINVAL;
}

+ if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
+ params->he_6ghz_capa =
+
nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
+

-Rajkumar

2020-05-27 23:34:33

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH v3 01/11] cfg80211: use only HE capability to set prohibited flags in 6 GHz

On 2020-05-27 06:43, Johannes Berg wrote:
> Hi,
>
> This is what we have in this area:
> https://p.sipsolutions.net/d8e56772a261199a.txt
>
> but I see it's also incomplete.
>
>> +static bool cfg80211_is_6ghz_freq(u32 freq)
>> +{
>> + return (freq > 5940 && freq < 7105);
>> +}
>
> That doesn't really make sense, I don't want to see those hardcoded
> frequencies all over the place.
>
>> case NL80211_CHAN_WIDTH_40:
>> width = 40;
>> + if (cfg80211_is_6ghz_freq(chandef->center_freq1)) {
>
> You can check chandef->chan->band instead. (In fact, we did)
>
Got it..

>> + if (!he_cap)
>> + return false;
>> + if (!he_cap->has_he_6ghz)
>> + return false;
>
> I'm not sure you should even _get_ here with a 6 GHz channel if you
> don't have 6 GHz capability? I mean, why did you register the channel
> in
> the first place then? This seems unnecessarily complex. If the channel
> didn't exist, it was rejected long before here.
>
Hmm... Agreed.

> However, looking at D6.0, maybe we do need some checks of the HE
> capability?
>
>> + if (!(he_cap->he_cap_elem.phy_cap_info[0] &
>> + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
>> + return false;
>
> Looks like even D6.0 still changed something in this area...
>
> Evidently our patch just assumed that in 6 GHz all of this is
> supported,
> but the spec doesn't support that theory :-)
>
IIUC the same bits are applicable for both 5 GHz & 6 GHz. I understand
the macro doesn't
capture both.

> Can you respin this with D6.0 taken into account?
>
Let me check again and respin after your series. Does it sound good?

-Rajkumar

2020-05-28 07:41:28

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 02/11] cfg80211: handle 6 GHz capability of new station

On Wed, 2020-05-27 at 16:24 -0700, Rajkumar Manoharan wrote:
> On 2020-05-27 07:00, Johannes Berg wrote:
> > On Wed, 2020-05-13 at 12:44 -0700, Rajkumar Manoharan wrote:
> > > Handle 6 GHz HE capability while adding new station. It will be used
> > > later in mac80211 station processing.
> >
> > This doesn't compile without the next patch.
> >
> My bad.. I must have overlooked while splitting the patch. :(

No worries. Looks like I'm reshuffling everything anyway :)


> > > + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capa;
> >
> > This we made just an __le16, any particular reason to have the struct?
> > It does need to be a pointer for the "no changes" case, but the struct
> > seems a bit overkill?
> >
> Initially I thought of splitting into two u8 for a_mpdu_params and info.
> Later changed to __le16 but retained struct. Nothing else :)

Right. I even saw that we're inconsistent - in mac80211 we used a struct
too, and in cfg80211 I just did __le16 ... I'll be consistent with a
struct, I guess.

> > > @@ -2998,6 +3003,7 @@ enum nl80211_attrs {
> > > #define NL80211_HE_MAX_CAPABILITY_LEN 54
> > > #define NL80211_MAX_NR_CIPHER_SUITES 5
> > > #define NL80211_MAX_NR_AKM_SUITES 2
> > > +#define NL80211_HE_6GHZ_CAPABILITY_LEN 2
> >
> > This not, we defined it just to be a U16.

And this should probably not be defined anyway since it comes from the
spec (and we now export the policy to userspace even!) and in the policy
we can then use sizeof(struct ...).

> > > + [NL80211_ATTR_HE_6GHZ_CAPABILITY] = {
> > > + .type = NLA_EXACT_LEN,
> > > + .len = NL80211_HE_6GHZ_CAPABILITY_LEN,
> > > + },
> >
> > This no longer exists, but I guess I'll just take our patch for the U16
> > here.

Sorry, I was confused - of course this still exists. NLA_EXACT_LEN_WARN
no longer exists since my recent rework in this area.

> > /* HE requires WME */
> > - if (params.he_capa_len)
> > + if (params.he_capa_len || params.he_6ghz_capa)
> > return -EINVAL;
> > }
> >
> Fine. One more thing. Pradeep found that 6 GHz capability is not filled
> in set_station.
> Please handle that in your series. I'm fine with rest of the changes you
> mentioned.
>
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -5893,6 +5893,10 @@ static int nl80211_set_station_tdls(struct
> genl_info *info,
> return -EINVAL;
> }
>
> + if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
> + params->he_6ghz_capa =
> +
> nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
> +

OK, thanks!

johannes

2020-05-28 07:43:19

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 01/11] cfg80211: use only HE capability to set prohibited flags in 6 GHz

On Wed, 2020-05-27 at 16:32 -0700, Rajkumar Manoharan wrote:
>
> > However, looking at D6.0, maybe we do need some checks of the HE
> > capability?
> >
> > > + if (!(he_cap->he_cap_elem.phy_cap_info[0] &
> > > + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
> > > + return false;
> >
> > Looks like even D6.0 still changed something in this area...
> >
> > Evidently our patch just assumed that in 6 GHz all of this is
> > supported,
> > but the spec doesn't support that theory :-)
> >
> IIUC the same bits are applicable for both 5 GHz & 6 GHz. I understand
> the macro doesn't capture both.

Yeah, I think you're right. I looked at D6.0 (though there seems to be
D6.1?) but I couldn't quite

> > Can you respin this with D6.0 taken into account?
> >
> Let me check again and respin after your series. Does it sound good?

Ok. I'll include our more limited code in the series for now then, and
we can make changes to that after we're on the same page.

Thanks,
johannes

2020-05-28 07:43:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 01/11] cfg80211: use only HE capability to set prohibited flags in 6 GHz

Hello brain, meet fingers, they're a bit slower ...

> > >
> > IIUC the same bits are applicable for both 5 GHz & 6 GHz. I understand
> > the macro doesn't capture both.
>
> Yeah, I think you're right. I looked at D6.0 (though there seems to be
> D6.1?) but I couldn't quite

... couldn't fully understand it in the limited time I had left
yesterday :)

johannes

2020-05-28 08:55:45

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 06/11] mac80211: handle HE 6 GHz Capability in HE STA processing


> +++ b/include/net/cfg80211.h
> @@ -332,15 +332,25 @@ struct ieee80211_sta_vht_cap {
> * to describe 802.11ax HE capabilities for a STA.
> *
> * @has_he: true iff HE data is valid.
> + * @has_he_6ghz: true iff HE 6 GHz data is valid.
> * @he_cap_elem: Fixed portion of the HE capabilities element.
> * @he_mcs_nss_supp: The supported NSS/MCS combinations.
> * @ppe_thres: Holds the PPE Thresholds data.
> + * @ampdu_factor: Maximum A-MPDU length factor used in 6 GHz.
> + * @ampdu_density: Minimum A-MPDU spacing used in 6 GHz.
> + * @cap: HE 6 GHz Band capability.
> */
> struct ieee80211_sta_he_cap {
> bool has_he;
> + bool has_he_6ghz;
> struct ieee80211_he_cap_elem he_cap_elem;
> struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
> u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
> + struct {
> + u8 ampdu_factor;
> + u8 ampdu_density;
> + u16 cap;
> + } he_6ghz;
> };

So ... I'm a bit unsure about this now. What I had done was this (well,
I adjusted it slightly now):

https://p.sipsolutions.net/2d0eb7c7e23a1b92.txt


But it's only half related? Maybe you're also using that for the
associated stations, not just for "self"? But then again, you *already*
added

@@ -1270,6 +1271,7 @@ struct station_parameters {
u8 he_capa_len;
u16 airtime_weight;
struct sta_txpwr txpwr;
+ const struct ieee80211_he_6ghz_capa *he_6ghz_capa;
};

right?


But no ... that's different. We still have a need to store the station's
capabilities.

But even then,

> + struct {
> + u8 ampdu_factor;
> + u8 ampdu_density;
> + u16 cap;
> + } he_6ghz;

doesn't really make sense, does it? "cap' already includes the
ampdu_factor and ampdu_density flags, so that's doubled...


I think I would prefer to have this separate. We need it as I put into
my patch that I linked to above, and we also need it in the station in
mac80211 for AP, but we don't really need it for cfg80211 as you put it
here.

I'll continue with my other patches, and then maybe see how this fits in
later.

johannes

2020-05-28 09:42:25

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

On Wed, 2020-05-27 at 16:41 +0200, Johannes Berg wrote:
>
> Hmm. Yes, we just had
>
> + case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ:
> + if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8)
> + he_chandef.width = NL80211_CHAN_WIDTH_160;
> + else
> + he_chandef.width = NL80211_CHAN_WIDTH_80P80;
> + break;
>
>
> but that breaks if you don't support 80+80 or 160.
>
> OTOH, we check this later again, I think, and downgrade if we don't
> support it, so no harm done?
>
> I think I'd prefer the parsing to be exact, and then downgrade as
> necessary. That makes things a bit simpler.

Except that won't work for mesh.

I actually kinda like this better than what I did, because what I did
required all kinds of contortions with DISABLE_HT/VHT/HE ...

Still checking.

johannes


2020-05-28 09:44:31

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 06/11] mac80211: handle HE 6 GHz Capability in HE STA processing

So I'm dropping this one for now.

I'm going to send a series right now with what I have, and you can start
looking at how to put this on top.

I'd prefer for *mac80211* to add the 6ghz capa sub-struct to the station
and use that while parsing, I think that should still be reasonable from
the driver's POV. You'll see I didn't change ieee80211_sta_he_cap, and I
am thinking now that it shouldn't change.

I'm still working on
* the HE oper -> channel parsing (MLME, and you also had mesh)
* 6 GHz scan bits that we had.

But I think you should be able to work on this patch without those two
things.

johannes

2020-05-28 11:47:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 10/11] mac80211: determine chantype from HE operation in 6 GHz

On Thu, 2020-05-28 at 11:41 +0200, Johannes Berg wrote:
>
> I actually kinda like this better than what I did, because what I did
> required all kinds of contortions with DISABLE_HT/VHT/HE ...

Actually, that's orthogonal. You had some of that, but not fully ...

This patch is doing almost the same thing we did, except you're taking
the capabilities into account immediately.

I'll go combine them and factor in the STA_DISABLE_BITS you had too, if
needed.

johannes

2020-05-28 12:21:36

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] mac80211: add HE 6 GHz Band Capability IE in Assoc. Request

Hi again :)

So ...

> @@ -4803,7 +4809,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
> 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->band != NL80211_BAND_6GHZ)
> + ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
> }
>
> if (!sband->vht_cap.vht_supported)
> @@ -5493,7 +5500,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
> if (req->flags & ASSOC_REQ_DISABLE_HT) {
> ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
> ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
> - ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
> + if (sband->band != NL80211_BAND_6GHZ)
> + ifmgd->flags |= IEEE80211_STA_DISABLE_HE;

I had dropped these bits from the patch earlier, because they didn't
really seem to belong here.

Now that I look at them in more detail, and compare to what I had done
before, it seems that this isn't really suitable...

For example for better or worse, IEEE80211_STA_DISABLE_HT and
IEEE80211_STA_DISABLE_VHT are checked in various places, for example in
the CSA code.

I had instead done here

bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;

[...]

- if (!sband->ht_cap.ht_supported) {
+ if (!sband->ht_cap.ht_supported && !is_6ghz) {

and so on.


Technically, *of course* you're right in that HT/VHT are disabled on 6
GHz channels. In practice, we've clearly not disentangled that enough
yet, I think.

I'll post the patch as I had it, wrt. these flags, and then we can see
about cleaning it up?

johannes

2020-05-28 13:16:12

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 06/11] mac80211: handle HE 6 GHz Capability in HE STA processing

On Thu, 2020-05-28 at 11:43 +0200, Johannes Berg wrote:

> I'd prefer for *mac80211* to add the 6ghz capa sub-struct to the station
> and use that while parsing, I think that should still be reasonable from
> the driver's POV. You'll see I didn't change ieee80211_sta_he_cap, and I
> am thinking now that it shouldn't change.

Actually. I had this patch too, sending it out soon.

johannes

2020-06-01 22:47:12

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH v3 11/11] ath11k: build HE 6 GHz capability

On 2020-05-13 12:45, Rajkumar Manoharan wrote:
> Build 6 GHz band capability from HT and VHT capabilities reported
> by firmware.
>
> Signed-off-by: Rajkumar Manoharan <[email protected]>
> ---
> drivers/net/wireless/ath/ath11k/core.h | 1 +
> drivers/net/wireless/ath/ath11k/mac.c | 34
> ++++++++++++++++++++++++++++++++++
> 2 files changed, 35 insertions(+)
>
Kalle,

Please drop this patch as it needs to be reworked on top of latest
mac80211 series.
Will submit ath11k patch again as the rest of the series were handled by
Johannes.

-Rajkumar