cfg80211: Add data structures to capture EHT capabilities
authorIlan Peer <ilan.peer@intel.com>
Mon, 14 Feb 2022 16:29:53 +0000 (17:29 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 16 Feb 2022 14:42:29 +0000 (15:42 +0100)
And advertise EHT capabilities to user space when supported.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Link: https://lore.kernel.org/r/20220214173004.6fb70658529f.I2413a37c8f7d2d6d638038a3d95360a3fce0114d@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c

index f6db085..7bec15f 100644 (file)
@@ -361,6 +361,48 @@ struct ieee80211_sta_he_cap {
 };
 
 /**
+ * struct ieee80211_eht_mcs_nss_supp - EHT max supported NSS per MCS
+ *
+ * See P802.11be_D1.3 Table 9-401k - "Subfields of the Supported EHT-MCS
+ * and NSS Set field"
+ *
+ * @only_20mhz: MCS/NSS support for 20 MHz-only STA.
+ * @bw._80: MCS/NSS support for BW <= 80 MHz
+ * @bw._160: MCS/NSS support for BW = 160 MHz
+ * @bw._320: MCS/NSS support for BW = 320 MHz
+ */
+struct ieee80211_eht_mcs_nss_supp {
+       union {
+               struct ieee80211_eht_mcs_nss_supp_20mhz_only only_20mhz;
+               struct {
+                       struct ieee80211_eht_mcs_nss_supp_bw _80;
+                       struct ieee80211_eht_mcs_nss_supp_bw _160;
+                       struct ieee80211_eht_mcs_nss_supp_bw _320;
+               } __packed bw;
+       } __packed;
+} __packed;
+
+#define IEEE80211_EHT_PPE_THRES_MAX_LEN                32
+
+/**
+ * struct ieee80211_sta_eht_cap - STA's EHT capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11be EHT capabilities for a STA.
+ *
+ * @has_eht: true iff EHT data is valid.
+ * @eht_cap_elem: Fixed portion of the eht capabilities element.
+ * @eht_mcs_nss_supp: The supported NSS/MCS combinations.
+ * @eht_ppe_thres: Holds the PPE Thresholds data.
+ */
+struct ieee80211_sta_eht_cap {
+       bool has_eht;
+       struct ieee80211_eht_cap_elem_fixed eht_cap_elem;
+       struct ieee80211_eht_mcs_nss_supp eht_mcs_nss_supp;
+       u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN];
+};
+
+/**
  * struct ieee80211_sband_iftype_data - sband data per interface type
  *
  * This structure encapsulates sband data that is relevant for the
@@ -379,6 +421,7 @@ struct ieee80211_sband_iftype_data {
        u16 types_mask;
        struct ieee80211_sta_he_cap he_cap;
        struct ieee80211_he_6ghz_capa he_6ghz_capa;
+       struct ieee80211_sta_eht_cap eht_cap;
        struct {
                const u8 *data;
                unsigned int len;
@@ -562,6 +605,26 @@ ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband,
 }
 
 /**
+ * ieee80211_get_eht_iftype_cap - return ETH 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,
+                            enum nl80211_iftype 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;
+}
+
+/**
  * wiphy_read_of_freq_limits - read frequency limits from device tree
  *
  * @wiphy: the wireless device to get extra limits for
index 195a238..d305a8b 100644 (file)
@@ -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 element
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT
+ *     capabilities element
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT
+ *     capabilities element
+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as
+ *     defined in EHT capabilities element
  * @__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,
index 5c49d7c..2dfd45f 100644 (file)
@@ -1737,6 +1737,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))
@@ -1757,6 +1758,32 @@ nl80211_send_iftype_data(struct sk_buff *msg,
                        return -ENOBUFS;
        }
 
+       if (eht_cap->has_eht && he_cap->has_he) {
+               u8 mcs_nss_size, ppe_thresh_size;
+               u16 ppe_thres_hdr;
+
+               mcs_nss_size =
+                       ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
+                                                  &eht_cap->eht_cap_elem);
+
+               ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
+               ppe_thresh_size =
+                       ieee80211_eht_ppe_size(ppe_thres_hdr,
+                                              eht_cap->eht_cap_elem.phy_cap_info);
+
+               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) ||
+                   nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
+                           mcs_nss_size, &eht_cap->eht_mcs_nss_supp) ||
+                   nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
+                           ppe_thresh_size, eht_cap->eht_ppe_thres))
+                       return -ENOBUFS;
+       }
+
        if (sband->band == NL80211_BAND_6GHZ &&
            nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
                    sizeof(iftdata->he_6ghz_capa),