@@ -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
@@ -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,
@@ -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))