2020-04-24 22:43:09

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 00/10] mac80211: add 6 GHz IEs support

This series includes following changes.

* Add 6 GHz band capability element (IEEE 802.11ax/D6.0, 9.4.2.261)
in mesh beacon and assoc. request.
* Add 6 GHz operation information in HE operation.
* Parse 6 GHz information elements.
* Decouple HT/VHT capability and do not allow HT/VHT overrides in 6 GHz.
* Determine channel information from HE information.

-Rajkumar

Rajkumar Manoharan (10):
mac80211: fix memory overlap due to variable length param
cfg80211: validate 6 GHz chandef
nl80211: add HE 6 GHz Band Capability support
mac80211: add HE 6 GHz Band Capabilities into parse extension
mac80211: handle HE 6 GHz Capability in HE STA processing
mac80211: add HE 6 GHz Band Capability IE in assoc. request
mac80211: build HE operation with 6 GHz oper information
mac80211: do not allow HT/VHT IEs in 6 GHz mesh mode
mac80211: determine chantype from HE operation in 6 GHz
ath11k: build HE 6 GHz capability

drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/mac.c | 33 ++++++-
include/linux/ieee80211.h | 58 +++++++++++
include/net/cfg80211.h | 24 +++++
include/net/mac80211.h | 7 +-
include/uapi/linux/nl80211.h | 6 ++
net/mac80211/cfg.c | 3 +-
net/mac80211/he.c | 65 ++++++++++--
net/mac80211/ieee80211_i.h | 8 +-
net/mac80211/mesh.c | 62 +++++++++++-
net/mac80211/mesh.h | 2 +
net/mac80211/mesh_plink.c | 7 +-
net/mac80211/mlme.c | 25 ++++-
net/mac80211/util.c | 174 ++++++++++++++++++++++++++++++++-
net/wireless/chan.c | 46 +++++++++
net/wireless/nl80211.c | 14 +++
16 files changed, 510 insertions(+), 25 deletions(-)

--
2.7.4


2020-04-24 22:43:09

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 01/10] 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-04-24 22:43:09

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 02/10] cfg80211: validate 6 GHz chandef

Validate the params of set_channel against 6 GHz frequency range
and bandwidth allowed.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/net/cfg80211.h | 14 ++++++++++++++
net/wireless/chan.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 70e48f66dac8..13d3d8f92c99 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -730,6 +730,20 @@ cfg80211_chandef_is_edmg(const struct cfg80211_chan_def *chandef)
}

/**
+ * cfg80211_chandef_is_6ghz - check if chandef represents an 6 GHz channel
+ *
+ * @chandef: the channel definition
+ *
+ * Return: %true if frequency is in 6 GHz range, %false otherwise.
+ */
+static inline bool
+cfg80211_chandef_is_6ghz(const struct cfg80211_chan_def *chandef)
+{
+ return (chandef->center_freq1 > 5940 && chandef->center_freq1 < 7105);
+}
+
+
+/**
* cfg80211_chandef_compatible - check if two channel definitions are compatible
* @chandef1: first channel definition
* @chandef2: second channel definition
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index fcac5c6366e1..42d27cada237 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -19,6 +19,29 @@ 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);
+}
+
+static enum nl80211_chan_width cfg80211_chan_to_bw_6ghz(u8 idx)
+{
+ /* channels: 1, 5, 9, 13... */
+ if ((idx & 0x3) == 0x1)
+ return NL80211_CHAN_WIDTH_20;
+ /* channels 3, 11, 19... */
+ if ((idx & 0x7) == 0x3)
+ return NL80211_CHAN_WIDTH_40;
+ /* channels 7, 23, 39.. */
+ if ((idx & 0xf) == 0x7)
+ return NL80211_CHAN_WIDTH_80;
+ /* channels 15, 47, 79...*/
+ if ((idx & 0x1f) == 0xf)
+ return NL80211_CHAN_WIDTH_160;
+
+ return NL80211_CHAN_WIDTH_20;
+}
+
void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *chan,
enum nl80211_channel_type chan_type)
@@ -139,6 +162,25 @@ static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
return true;
}

+static bool cfg80211_6ghz_chandef_valid(const struct cfg80211_chan_def *chandef)
+{
+ enum nl80211_chan_width bw;
+ int chan_idx;
+
+ if (!cfg80211_is_6ghz_freq(chandef->center_freq1))
+ return false;
+
+ chan_idx = ieee80211_frequency_to_channel(chandef->center_freq1);
+ if (chan_idx <= 0)
+ return false;
+
+ bw = cfg80211_chan_to_bw_6ghz(chan_idx);
+ if (bw != chandef->width)
+ return false;
+
+ return true;
+}
+
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{
u32 control_freq;
@@ -213,6 +255,10 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
!cfg80211_edmg_chandef_valid(chandef))
return false;

+ if (cfg80211_chandef_is_6ghz(chandef) &&
+ !cfg80211_6ghz_chandef_valid(chandef))
+ return false;
+
return true;
}
EXPORT_SYMBOL(cfg80211_chandef_valid);
--
2.7.4

2020-04-24 22:43:09

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 07/10] 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 d8b03b657431..d5f4fb3a7a73 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2174,7 +2174,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 72a7a38a470c..ced032d21cdb 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-04-24 22:43:09

by Rajkumar Manoharan

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

Define new structures for HE 6 GHz band capabilities as per

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
include/linux/ieee80211.h | 57 ++++++++++++++++++++++++++++++++++++++++++++
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 6 +++++
net/wireless/nl80211.c | 14 +++++++++++
4 files changed, 79 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
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 13d3d8f92c99..bb5c3e2ec96c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1239,6 +1239,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_cap: HE 6 GHz Band capabilities of station
*/
struct station_parameters {
const u8 *supported_rates;
@@ -1271,6 +1272,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..fd1aa70d1f5c 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_WARN,
+ .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,12 @@ 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 = NULL;
+ params.vht_capa = NULL;
+ }
+
/* 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-04-24 22:43:11

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 04/10] 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..bed4983bcb32 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 u8 *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-04-24 22:43:15

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 08/10] 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 ced032d21cdb..f6e46b18c304 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-04-24 22:44:19

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 05/10] 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 | 52 ++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mesh_plink.c | 4 +++-
net/mac80211/mlme.c | 1 +
6 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bb5c3e2ec96c..608b4107d0cd 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -332,15 +332,23 @@ 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.
+ * @he_6gz_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];
+ u8 ampdu_factor;
+ u8 ampdu_density;
+ u16 he_6ghz_cap;
};

/**
@@ -1272,7 +1280,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;
+ const u8 *he_6ghz_capa;
};

/**
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..b983c7d396e5 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 u8 *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;
+ struct ieee80211_he_6ghz_band_cap *he_6ghz_cap_elem;
+ enum ieee80211_smps_mode smps_mode;
+ u16 cap;
u8 he_ppe_size;
u8 mcs_nss_size;
u8 he_total_size;
@@ -53,6 +57,54 @@ 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;
+
+ he_6ghz_cap_elem = (struct ieee80211_he_6ghz_band_cap *)he_6ghz_cap_ie;
+ cap = __le16_to_cpu(he_6ghz_cap_elem->capab);
+
+ he_cap->ampdu_density =
+ FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK,
+ cap);
+ he_cap->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 bed4983bcb32..450f11e820cc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1892,6 +1892,7 @@ 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 u8 *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-04-24 22:46:02

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 10/10] 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 | 30 ++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 6e7b8ecd09a6..730829eaee23 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;
+ u32 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..eb4dc6fc4209 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3522,6 +3522,32 @@ 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)
+{
+ 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);
+ bcap->he_6ghz_cap |=
+ FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ 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_MPDU_LENGTH_MASK,
+ FIELD_GET(IEEE80211_VHT_CAP_MAX_MPDU_MASK,
+ pcap->vht_cap));
+ 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 +3628,10 @@ 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->he_6ghz_cap =
+ ath11k_mac_setup_he_6ghz_cap(cap, band_cap);
idx++;
}

--
2.7.4

2020-04-24 22:46:02

by Rajkumar Manoharan

[permalink] [raw]
Subject: [PATCH 06/10] mac80211: add HE 6 GHz Band Capability IE in assoc. request

Construct HE 6 GHz band capability element (IEEE 802.11ax/D6.0, 9.4.2.261)
for association request and mesh beacon. The 6 GHz capability information
is passed from 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 450f11e820cc..d8b03b657431 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2173,6 +2173,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..72a7a38a470c 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->he_6ghz_cap)
+ 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..6ff1087e3bba 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->he_6ghz_cap)
+ 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-04-24 22:46:03

by Rajkumar Manoharan

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

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

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 | 92 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 108 insertions(+)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d5f4fb3a7a73..70393084a1cb 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2193,6 +2193,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 f6e46b18c304..daa2d6abef3f 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 6ff1087e3bba..02d7d28594e5 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..660cf52913f1 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3170,6 +3170,98 @@ 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;
+
+ if (!heop)
+ return false;
+
+ sband = ieee80211_get_sband(sdata);
+ 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-04-29 14:27:42

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 02/10] cfg80211: validate 6 GHz chandef

On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>
> +static inline bool
> +cfg80211_chandef_is_6ghz(const struct cfg80211_chan_def *chandef)
> +{
> + return (chandef->center_freq1 > 5940 && chandef->center_freq1 < 7105);
> +}

Seems like this

> +++ b/net/wireless/chan.c
> @@ -19,6 +19,29 @@ 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);
> +}

should use this, by also exposing it, or something.

> +static enum nl80211_chan_width cfg80211_chan_to_bw_6ghz(u8 idx)
> +{
> + /* channels: 1, 5, 9, 13... */
> + if ((idx & 0x3) == 0x1)
> + return NL80211_CHAN_WIDTH_20;
> + /* channels 3, 11, 19... */
> + if ((idx & 0x7) == 0x3)
> + return NL80211_CHAN_WIDTH_40;
> + /* channels 7, 23, 39.. */
> + if ((idx & 0xf) == 0x7)
> + return NL80211_CHAN_WIDTH_80;
> + /* channels 15, 47, 79...*/
> + if ((idx & 0x1f) == 0xf)
> + return NL80211_CHAN_WIDTH_160;
> +
> + return NL80211_CHAN_WIDTH_20;
> +}

We haven't really done that for anything else - is that really
necessary?

> +static bool cfg80211_6ghz_chandef_valid(const struct cfg80211_chan_def *chandef)
> +{
> + enum nl80211_chan_width bw;
> + int chan_idx;
> +
> + if (!cfg80211_is_6ghz_freq(chandef->center_freq1))
> + return false;

this is kinda pointless,

> @@ -213,6 +255,10 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
> !cfg80211_edmg_chandef_valid(chandef))
> return false;
>
> + if (cfg80211_chandef_is_6ghz(chandef) &&
> + !cfg80211_6ghz_chandef_valid(chandef))
> + return false;

You only get there if it was in range ...

Not sure about this whole patch, it seems a bit pointless?

johannes

2020-04-29 14:29:10

by Johannes Berg

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

On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
> Define new structures for HE 6 GHz band capabilities as per

per?

> include/linux/ieee80211.h | 57 ++++++++++++++++++++++++++++++++++++++++++++
> include/net/cfg80211.h | 2 ++
> include/uapi/linux/nl80211.h | 6 +++++
> net/wireless/nl80211.c | 14 +++++++++++

This is a bit mixed up, I'd prefer the raw ieee80211.h definitions in a
separate patch.

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

Shouldn't use _WARN for a new attribute. Just reject it if userspace
gets it wrong.

> @@ -6177,6 +6185,12 @@ 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 = NULL;
> + params.vht_capa = NULL;
> + }

IMHO better to reject (with a message)

johannes

2020-04-29 14:32:17

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 05/10] mac80211: handle HE 6 GHz Capability in HE STA processing

On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>
> * @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.
> + * @he_6gz_cap: HE 6 GHz Band capability.

typo

> */
> 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];
> + u8 ampdu_factor;
> + u8 ampdu_density;
> + u16 he_6ghz_cap;

Maybe these should be in some kind of sub-struct so it's clear what the
"has_he_6ghz" applies to?

> };
>
> /**
> @@ -1272,7 +1280,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;
> + const u8 *he_6ghz_capa;

hm?

johannes

2020-04-29 14:35:35

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 06/10] mac80211: add HE 6 GHz Band Capability IE in assoc. request

On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
> Construct HE 6 GHz band capability element (IEEE 802.11ax/D6.0, 9.4.2.261)
> for association request and mesh beacon. The 6 GHz capability information
> is passed from driver through iftypes caps.

Oh. I had some patches for this too but Luca never sent them out...

I'll have to check the differences to see if either of us missed
something :)

johannes

2020-04-29 14:36:18

by Johannes Berg

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

On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
> In 6 GHz band, determine chandef from 6 GHz operation information
> of HE operation element.

Yeah... I had this too. Oh well.

johannes

2020-04-30 00:03:30

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 02/10] cfg80211: validate 6 GHz chandef

On 2020-04-29 07:26, Johannes Berg wrote:
> On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>>
>> +static inline bool
>> +cfg80211_chandef_is_6ghz(const struct cfg80211_chan_def *chandef)
>> +{
>> + return (chandef->center_freq1 > 5940 && chandef->center_freq1 <
>> 7105);
>> +}
>
> Seems like this
>
>> +++ b/net/wireless/chan.c
>> @@ -19,6 +19,29 @@ 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);
>> +}
>
> should use this, by also exposing it, or something.
>
Sure. Export this and remove the above one.

>> +static enum nl80211_chan_width cfg80211_chan_to_bw_6ghz(u8 idx)
>> +{
>> + /* channels: 1, 5, 9, 13... */
>> + if ((idx & 0x3) == 0x1)
>> + return NL80211_CHAN_WIDTH_20;
>> + /* channels 3, 11, 19... */
>> + if ((idx & 0x7) == 0x3)
>> + return NL80211_CHAN_WIDTH_40;
>> + /* channels 7, 23, 39.. */
>> + if ((idx & 0xf) == 0x7)
>> + return NL80211_CHAN_WIDTH_80;
>> + /* channels 15, 47, 79...*/
>> + if ((idx & 0x1f) == 0xf)
>> + return NL80211_CHAN_WIDTH_160;
>> +
>> + return NL80211_CHAN_WIDTH_20;
>> +}
>
> We haven't really done that for anything else - is that really
> necessary?
>
Hmm.. to check whether give center_freq1 chan_idx is allowed to operate
in given bandwidth.
Similar to center_idx_to_bw_6ghz of hostapd, this API is used to chandef
bw.

[...]
>> @@ -213,6 +255,10 @@ bool cfg80211_chandef_valid(const struct
>> cfg80211_chan_def *chandef)
>> !cfg80211_edmg_chandef_valid(chandef))
>> return false;
>>
>> + if (cfg80211_chandef_is_6ghz(chandef) &&
>> + !cfg80211_6ghz_chandef_valid(chandef))
>> + return false;
>
> You only get there if it was in range ...
>
> Not sure about this whole patch, it seems a bit pointless?
>

Don't we have to check chandef bw? If not, I will drop the change.

-Rajkumar

2020-04-30 00:05:30

by Rajkumar Manoharan

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

On 2020-04-29 07:28, Johannes Berg wrote:
> On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>> Define new structures for HE 6 GHz band capabilities as per
>
> per?
>
Oops.. My bad. Accidentally removed the commit log.

>> include/linux/ieee80211.h | 57
>> ++++++++++++++++++++++++++++++++++++++++++++
>> include/net/cfg80211.h | 2 ++
>> include/uapi/linux/nl80211.h | 6 +++++
>> net/wireless/nl80211.c | 14 +++++++++++
>
> This is a bit mixed up, I'd prefer the raw ieee80211.h definitions in a
> separate patch.
>
Sure.

>> + [NL80211_ATTR_HE_6GHZ_CAPABILITY] = {
>> + .type = NLA_EXACT_LEN_WARN,
>> + .len = NL80211_HE_6GHZ_CAPABILITY_LEN,
>> + },
>
> Shouldn't use _WARN for a new attribute. Just reject it if userspace
> gets it wrong.
>
Done. :)

>> @@ -6177,6 +6185,12 @@ 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 = NULL;
>> + params.vht_capa = NULL;
>> + }
>
> IMHO better to reject (with a message)
>
Got it.

-Rajkumar

2020-04-30 00:12:35

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 05/10] mac80211: handle HE 6 GHz Capability in HE STA processing

On 2020-04-29 07:31, Johannes Berg wrote:
> On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>>
>> * @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.
>> + * @he_6gz_cap: HE 6 GHz Band capability.
>
> typo
>
>> */
>> 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];
>> + u8 ampdu_factor;
>> + u8 ampdu_density;
>> + u16 he_6ghz_cap;
>
> Maybe these should be in some kind of sub-struct so it's clear what the
> "has_he_6ghz" applies to?
>
Got it.

>> };
>>
>> /**
>> @@ -1272,7 +1280,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;
>> + const u8 *he_6ghz_capa;
>
> hm?
>

I realized later ;) that ieee80211_he_cap_ie_to_sta_he_cap accepting u8*
for IEs.
To align with the existing pattern changed to u8 *. Let me correct it
first.

-Rajkumar

2020-04-30 00:16:31

by Rajkumar Manoharan

[permalink] [raw]
Subject: Re: [PATCH 06/10] mac80211: add HE 6 GHz Band Capability IE in assoc. request

On 2020-04-29 07:33, Johannes Berg wrote:
> On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>> Construct HE 6 GHz band capability element (IEEE 802.11ax/D6.0,
>> 9.4.2.261)
>> for association request and mesh beacon. The 6 GHz capability
>> information
>> is passed from driver through iftypes caps.
>
> Oh. I had some patches for this too but Luca never sent them out...
>
> I'll have to check the differences to see if either of us missed
> something :)
>
Great.. Would like to see yours changes. I also posted similar changes
in hostapd
for AP mode. Please check them as well.

-Rajkumar

2020-04-30 00:19:57

by Rajkumar Manoharan

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

On 2020-04-29 07:34, Johannes Berg wrote:
> On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
>> In 6 GHz band, determine chandef from 6 GHz operation information
>> of HE operation element.
>
> Yeah... I had this too. Oh well.
>
Thanks for feedback. Have few more changes on top this series.
Before posting next version, would prefer to bundle with your changes.
thoughts?

-Rajkumar

2020-04-30 19:53:22

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 06/10] mac80211: add HE 6 GHz Band Capability IE in assoc. request

On Wed, 2020-04-29 at 17:14 -0700, Rajkumar Manoharan wrote:
> On 2020-04-29 07:33, Johannes Berg wrote:
> > On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
> > > Construct HE 6 GHz band capability element (IEEE 802.11ax/D6.0,
> > > 9.4.2.261)
> > > for association request and mesh beacon. The 6 GHz capability
> > > information
> > > is passed from driver through iftypes caps.
> >
> > Oh. I had some patches for this too but Luca never sent them out...
> >
> > I'll have to check the differences to see if either of us missed
> > something :)
> >
> Great.. Would like to see yours changes.

Sure. I'll get to this next week I hope.

> I also posted similar changes
> in hostapd for AP mode. Please check them as well.

I saw, but didn't really consider AP mode much yet.

johannes

2020-04-30 19:54:23

by Johannes Berg

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

On Wed, 2020-04-29 at 17:18 -0700, Rajkumar Manoharan wrote:
> On 2020-04-29 07:34, Johannes Berg wrote:
> > On Fri, 2020-04-24 at 15:41 -0700, Rajkumar Manoharan wrote:
> > > In 6 GHz band, determine chandef from 6 GHz operation information
> > > of HE operation element.
> >
> > Yeah... I had this too. Oh well.
> >
> Thanks for feedback. Have few more changes on top this series.
> Before posting next version, would prefer to bundle with your changes.
> thoughts?

I guess post whatever you have already? That shouldn't be any real work
:-)

And then I can compare to what I have internally already. I guess I'll
just send that out too so you can see it.

johannes

2020-04-30 19:55:33

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 02/10] cfg80211: validate 6 GHz chandef


> > > +static enum nl80211_chan_width cfg80211_chan_to_bw_6ghz(u8 idx)
> > > +{
> > > + /* channels: 1, 5, 9, 13... */
> > > + if ((idx & 0x3) == 0x1)
> > > + return NL80211_CHAN_WIDTH_20;
> > > + /* channels 3, 11, 19... */
> > > + if ((idx & 0x7) == 0x3)
> > > + return NL80211_CHAN_WIDTH_40;
> > > + /* channels 7, 23, 39.. */
> > > + if ((idx & 0xf) == 0x7)
> > > + return NL80211_CHAN_WIDTH_80;
> > > + /* channels 15, 47, 79...*/
> > > + if ((idx & 0x1f) == 0xf)
> > > + return NL80211_CHAN_WIDTH_160;
> > > +
> > > + return NL80211_CHAN_WIDTH_20;
> > > +}
> >
> > We haven't really done that for anything else - is that really
> > necessary?
> >
> Hmm.. to check whether give center_freq1 chan_idx is allowed to operate
> in given bandwidth.
> Similar to center_idx_to_bw_6ghz of hostapd, this API is used to chandef
> bw.

Yeah, but good enough if hostapd does that check? I don't really see the
kernel caring too much?

> Don't we have to check chandef bw? If not, I will drop the change.

I'm not really sure why we should, tbh.

johannes