diff mbox series

[2/6] nl80211: add support to advertise driver's EHT capabilities

Message ID 1640163883-12696-3-git-send-email-quic_vjakkam@quicinc.com
State New
Headers show
Series cfg80211/nl80211: add support for EHT | expand

Commit Message

Veerendranath Jakkam Dec. 22, 2021, 9:04 a.m. UTC
From: Vikram Kandukuri <quic_vikram@quicinc.com>

Add nl80211 support to advertise EHT capabilities to the userspace.

Add new attributes in enum nl80211_band_iftype_attr to indicate EHT MAC
capabilities, PHY capabilities, supported MCC-NSS set and PPE threshold
fields.

Signed-off-by: Vikram Kandukuri <quic_vikram@quicinc.com>
Co-authored-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Co-authored-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
---
 include/net/cfg80211.h       | 56 ++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/nl80211.h | 12 ++++++++++
 net/wireless/nl80211.c       | 17 ++++++++++++++
 3 files changed, 85 insertions(+)

Comments

Aloka Dixit Feb. 10, 2022, 5:14 a.m. UTC | #1
Hi Johannes,

Considering that 20MHz-only STA and one that supports other bandwidths will not occur at the same time,
instead of a separate field for struct ieee80211_eht_mcs_nss_supp_20mhz_only inside struct ieee80211_eht_mcs_nss_supp, we can use a byte array as we added in here:
https://patchwork.kernel.org/project/linux-wireless/patch/1640163883-12696-3-git-send-email-quic_vjakkam@quicinc.com/
Instead of length field with dynamic allocation we can have an array of size 9 bytes.

Anyway most operations still need to differentiate between 20MHz-only and other cases, it will just change how many bytes those operations process (4 vs 3,6,9).

What do you think?
Johannes Berg Feb. 10, 2022, 8:26 a.m. UTC | #2
On Thu, 2022-02-10 at 05:14 +0000, Aloka Dixit (QUIC) wrote:
> Hi Johannes,
> 
> Considering that 20MHz-only STA and one that supports other bandwidths will not occur at the same time,
> instead of a separate field for struct ieee80211_eht_mcs_nss_supp_20mhz_only inside struct ieee80211_eht_mcs_nss_supp, we can use a byte array as we added in here:
> https://patchwork.kernel.org/project/linux-wireless/patch/1640163883-12696-3-git-send-email-quic_vjakkam@quicinc.com/
> Instead of length field with dynamic allocation we can have an array of size 9 bytes.
> 

We did something like that in our patches:

https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.b0eeb527d761.I2413a37c8f7d2d6d638038a3d95360a3fce0114d@changeid/
https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.1ee92202ac30.Id30a3ef2844b296efbd5486fe1da9ca36a95c5cf@changeid/

Not overlapping wastes like 4 bytes of memory, I think I can live with
that, vs. the extra complexity? If you overlap you need another bit to
indicate which one you're using ...

johannes
Johannes Berg Feb. 10, 2022, 11:17 a.m. UTC | #3
On Thu, 2022-02-10 at 09:26 +0100, Johannes Berg wrote:
> > 
> > Considering that 20MHz-only STA and one that supports other bandwidths will not occur at the same time,
> > instead of a separate field for struct ieee80211_eht_mcs_nss_supp_20mhz_only inside struct ieee80211_eht_mcs_nss_supp, we can use a byte array as we added in here:
> > https://patchwork.kernel.org/project/linux-wireless/patch/1640163883-12696-3-git-send-email-quic_vjakkam@quicinc.com/
> > Instead of length field with dynamic allocation we can have an array of size 9 bytes.
> > 
> 
> We did something like that in our patches:
> 
> https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.b0eeb527d761.I2413a37c8f7d2d6d638038a3d95360a3fce0114d@changeid/
> https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.1ee92202ac30.Id30a3ef2844b296efbd5486fe1da9ca36a95c5cf@changeid/
> 
> Not overlapping wastes like 4 bytes of memory, I think I can live with
> that, vs. the extra complexity? If you overlap you need another bit to
> indicate which one you're using ...
> 

OTOH, that means we need to unwrap it in userspace, which is also
strange ... So yeah I'm changing it to a union.

johannes
Aloka Dixit Feb. 10, 2022, 3:57 p.m. UTC | #4
> We did something like that in our patches:
> 
> https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.b0eeb527d761.I2413a37c8f7d2d6d638038a3d95360a3fce0114d@changeid/
> https://patchwork.kernel.org/project/linux-wireless/patch/20220204230119.1ee92202ac30.Id30a3ef2844b296efbd5486fe1da9ca36a95c5cf@changeid/
> 
> Not overlapping wastes like 4 bytes of memory, I think I can live with
> that, vs. the extra complexity? If you overlap you need another bit to
> indicate which one you're using ...
> 

OTOH, that means we need to unwrap it in userspace, which is also
strange ... So yeah I'm changing it to a union.

Johannes

My comment was actually about your Patches but realized I hadn't subscribed this email with the mailing list so never got emails for those.
So replied here (as I am in cc), just pasted wrong link 😊

But yeah, union would work.
Thanks.
Johannes Berg Feb. 10, 2022, 4:29 p.m. UTC | #5
On Thu, 2022-02-10 at 15:57 +0000, Aloka Dixit (QUIC) wrote:
> 
> 
> My comment was actually about your Patches but realized I hadn't
> subscribed this email with the mailing list so never got emails for
> those.

Oh.

> So replied here (as I am in cc), just pasted wrong link 😊

Ah ok :)

> 
> But yeah, union would work.

I'll also make all the pieces have the right size in nl80211.

johannes
diff mbox series

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d19e48f..df197c6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -361,6 +361,28 @@  struct ieee80211_sta_he_cap {
 };
 
 /**
+ * struct ieee80211_sta_eht_cap - STA's EHT capabilities
+ *
+ * This structure describes parameters needed to describe 802.11be EHT
+ * capabilities for a STA.
+ *
+ * @has_eht: true if EHT data is valid.
+ * @eht_cap_elem: Fixed portion of the EHT capabilities element.
+ * @mcs_nss: The supported NSS/MCS combinations.
+ * @mcs_nss_len: Length of NSS/MCS combinations data.
+ * @ppe_thres: Holds the PPE Thresholds data.
+ * @ppe_thres_len: Length PPE Thresholds data.
+ */
+struct ieee80211_sta_eht_cap {
+	bool has_eht;
+	struct ieee80211_eht_cap_elem eht_cap_elem;
+	u8 *mcs_nss;
+	u8 mcs_nss_len;
+	u8 *ppe_thres;
+	u8 ppe_thres_len;
+};
+
+/**
  * struct ieee80211_sband_iftype_data - sband data per interface type
  *
  * This structure encapsulates sband data that is relevant for the
@@ -374,6 +396,7 @@  struct ieee80211_sta_he_cap {
  * @vendor_elems: vendor element(s) to advertise
  * @vendor_elems.data: vendor element(s) data
  * @vendor_elems.len: vendor element(s) length
+ * @eht_cap: holds the EHT capabilities.
  */
 struct ieee80211_sband_iftype_data {
 	u16 types_mask;
@@ -383,6 +406,7 @@  struct ieee80211_sband_iftype_data {
 		const u8 *data;
 		unsigned int len;
 	} vendor_elems;
+	struct ieee80211_sta_eht_cap eht_cap;
 };
 
 /**
@@ -522,6 +546,38 @@  ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
 }
 
 /**
+ * ieee80211_get_eht_iftype_cap - return EHT capabilities for an sband's iftype
+ * @sband: the sband to search for the iftype on
+ * @iftype: enum nl80211_iftype
+ *
+ * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found
+ */
+static inline const struct ieee80211_sta_eht_cap *
+ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *sband,
+			     u8 iftype)
+{
+	const struct ieee80211_sband_iftype_data *data =
+		ieee80211_get_sband_iftype_data(sband, iftype);
+
+	if (data && data->eht_cap.has_eht)
+		return &data->eht_cap;
+
+	return NULL;
+}
+
+/**
+ * ieee80211_get_eht_sta_cap - return EHT capabilities for an sband's STA
+ * @sband: the sband to search for the STA on
+ *
+ * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found
+ */
+static inline const struct ieee80211_sta_eht_cap *
+ieee80211_get_eht_sta_cap(const struct ieee80211_supported_band *sband)
+{
+	return ieee80211_get_eht_iftype_cap(sband, NL80211_IFTYPE_STATION);
+}
+
+/**
  * ieee80211_get_he_iftype_cap - return HE capabilities for an sband's iftype
  * @sband: the sband to search for the iftype on
  * @iftype: enum nl80211_iftype
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f1a9d65..a709f5c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3766,6 +3766,14 @@  enum nl80211_mpath_info {
  *	given for all 6 GHz band channels
  * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are
  *	advertised on this band/for this iftype (binary)
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT
+ *     capabilities IE
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT
+ *     capabilities IE
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT
+ *     capabilities IE
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as
+ *     defined in EHT capabilities IE
  * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use
  * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined
  */
@@ -3779,6 +3787,10 @@  enum nl80211_band_iftype_attr {
 	NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
 	NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
 	NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
+	NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
+	NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
+	NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
+	NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
 
 	/* keep last */
 	__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 578bff9..0ece4d3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1729,6 +1729,7 @@  nl80211_send_iftype_data(struct sk_buff *msg,
 			 const struct ieee80211_sband_iftype_data *iftdata)
 {
 	const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
+	const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
 
 	if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
 				iftdata->types_mask))
@@ -1755,6 +1756,22 @@  nl80211_send_iftype_data(struct sk_buff *msg,
 		    &iftdata->he_6ghz_capa))
 		return -ENOBUFS;
 
+	if (eht_cap->has_eht) {
+		if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
+			    sizeof(eht_cap->eht_cap_elem.mac_cap_info),
+			    eht_cap->eht_cap_elem.mac_cap_info) ||
+		    nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
+			    sizeof(eht_cap->eht_cap_elem.phy_cap_info),
+			    eht_cap->eht_cap_elem.phy_cap_info) ||
+		    (eht_cap->mcs_nss_len &&
+		     nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
+			     eht_cap->mcs_nss_len, eht_cap->mcs_nss)) ||
+		    (eht_cap->ppe_thres_len &&
+		     nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
+			     eht_cap->ppe_thres_len, eht_cap->ppe_thres)))
+			return -ENOBUFS;
+	}
+
 	if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
 	    nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
 		    iftdata->vendor_elems.len, iftdata->vendor_elems.data))