Add data structures to capture UHR capabilities and advertise UHR capabilities to user space when supported via NL attributes. Signed-off-by: Karthikeyan Kathirvel --- include/net/cfg80211.h | 16 ++++++++++++++++ include/uapi/linux/nl80211.h | 6 ++++++ net/wireless/nl80211.c | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 899f267b7cf9..378fd54c282c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -429,6 +429,20 @@ struct ieee80211_sta_eht_cap { u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN]; }; +/** + * struct ieee80211_sta_uhr_cap - STA's UHR capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11bn UHR capabilities for a STA. + * + * @has_uhr: true if UHR data is valid. + * @uhr_cap_elem: Fixed portion of the uhr capabilities element. + */ +struct ieee80211_sta_uhr_cap { + bool has_uhr; + struct ieee80211_uhr_cap_elem_fixed uhr_cap_elem; +}; + /* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */ #ifdef __CHECKER__ /* @@ -454,6 +468,7 @@ struct ieee80211_sta_eht_cap { * @he_6ghz_capa: HE 6 GHz capabilities, must be filled in for a * 6 GHz band channel (and 0 may be valid value). * @eht_cap: STA's EHT capabilities + * @uhr_cap: STA's UHR capabilities * @vendor_elems: vendor element(s) to advertise * @vendor_elems.data: vendor element(s) data * @vendor_elems.len: vendor element(s) length @@ -463,6 +478,7 @@ struct ieee80211_sband_iftype_data { struct ieee80211_sta_he_cap he_cap; struct ieee80211_he_6ghz_capa he_6ghz_capa; struct ieee80211_sta_eht_cap eht_cap; + struct ieee80211_sta_uhr_cap uhr_cap; struct { const u8 *data; unsigned int len; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 8134f10e4e6c..8d9038ba1208 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4248,6 +4248,10 @@ enum nl80211_mpath_info { * capabilities element * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as * defined in EHT capabilities element + * @NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC: UHR MAC capabilities as in UHR + * capabilities element + * @NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY: UHR PHY capabilities as in UHR + * capabilities element * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined */ @@ -4265,6 +4269,8 @@ enum nl80211_band_iftype_attr { NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, + NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC, + NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY, /* keep last */ __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6b99416862a4..d05d098c4dc7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1947,6 +1947,7 @@ nl80211_send_iftype_data(struct sk_buff *msg, { const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap; + const struct ieee80211_sta_uhr_cap *uhr_cap = &iftdata->uhr_cap; if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, iftdata->types_mask)) @@ -2004,6 +2005,16 @@ nl80211_send_iftype_data(struct sk_buff *msg, &iftdata->he_6ghz_capa)) return -ENOBUFS; + if (uhr_cap->has_uhr && eht_cap->has_eht && he_cap->has_he) { + if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC, + sizeof(uhr_cap->uhr_cap_elem.mac_cap_info), + uhr_cap->uhr_cap_elem.mac_cap_info) || + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY, + sizeof(uhr_cap->uhr_cap_elem.phy_cap_info), + uhr_cap->uhr_cap_elem.phy_cap_info)) + 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)) -- 2.34.1