From: Johannes Berg Date: Tue, 28 Apr 2026 08:36:57 +0000 (+0200) Subject: wifi: mac80211: update UHR capabilities field order X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=f6310f043fb4f45f0027da842e46fcddf9c859fe;p=thirdparty%2Flinux.git wifi: mac80211: update UHR capabilities field order Since 802.11bn D1.4 the DBE capabilities are after the PHY capabilities, not between MAC and PHY, adjust the code accordingly. Also add a struct for DBE capabilities and use it for checking the correct length instead of hard-coding the lengths. Signed-off-by: Johannes Berg Reviewed-by: Miriam Rachel Korenblit Link: https://patch.msgid.link/20260428103657.b40af50f182d.I75306a092dc2c8a9eb7276160f0b7144b4846d18@changeid Signed-off-by: Johannes Berg --- diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h index d199f3ebdba0..f4f4bd8256df 100644 --- a/include/linux/ieee80211-uhr.h +++ b/include/linux/ieee80211-uhr.h @@ -372,6 +372,12 @@ ieee80211_uhr_npca_dis_subch_bitmap(const struct ieee80211_uhr_operation *oper) #define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES 0x08 #define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES 0x10 +struct ieee80211_uhr_cap_dbe { + u8 cap; + /* present 0, 1 or 2 times depending on _PRES bits */ + struct ieee80211_eht_mcs_nss_supp_bw eht_mcs_map[]; +} __packed; + /** * enum ieee80211_uhr_dbe_max_supported_bw - DBE Maximum Supported Bandwidth * @@ -394,12 +400,6 @@ struct ieee80211_uhr_cap_mac { u8 mac_cap[5]; } __packed; -struct ieee80211_uhr_cap { - struct ieee80211_uhr_cap_mac mac; - /* DBE, PHY capabilities */ - u8 variable[]; -} __packed; - #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 0x01 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 0x02 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 0x04 @@ -413,11 +413,18 @@ struct ieee80211_uhr_cap_phy { u8 cap; } __packed; +struct ieee80211_uhr_cap { + struct ieee80211_uhr_cap_mac mac; + struct ieee80211_uhr_cap_phy phy; + /* optional DBE capabilities */ + u8 variable[]; +} __packed; + static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len, bool from_ap) { const struct ieee80211_uhr_cap *cap = (const void *)data; - size_t needed = sizeof(*cap) + sizeof(struct ieee80211_uhr_cap_phy); + size_t needed = sizeof(*cap); if (len < needed) return false; @@ -427,44 +434,24 @@ static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len, * in the UHR MAC Capabilities Information field. */ if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) { - u8 dbe; + const struct ieee80211_uhr_cap_dbe *dbe; - needed += 1; + needed += sizeof(struct ieee80211_uhr_cap_dbe); if (len < needed) return false; - dbe = cap->variable[0]; + dbe = (const void *)cap->variable; - if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES) - needed += 3; + if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES) + needed += sizeof(dbe->eht_mcs_map[0]); - if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES) - needed += 3; + if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES) + needed += sizeof(dbe->eht_mcs_map[0]); } return len >= needed; } -static inline const struct ieee80211_uhr_cap_phy * -ieee80211_uhr_phy_cap(const struct ieee80211_uhr_cap *cap, bool from_ap) -{ - u8 offs = 0; - - if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) { - u8 dbe = cap->variable[0]; - - offs += 1; - - if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES) - offs += 3; - - if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES) - offs += 3; - } - - return (const void *)&cap->variable[offs]; -} - #define IEEE80211_SMD_INFO_CAPA_DL_DATA_FWD 0x01 #define IEEE80211_SMD_INFO_CAPA_MAX_NUM_PREP 0x0E #define IEEE80211_SMD_INFO_CAPA_TYPE 0x10 diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8400792d67e2..90d295cc364f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1463,8 +1463,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (supp_uhr) local->scan_ies_len += - 3 + sizeof(struct ieee80211_uhr_cap) + - sizeof(struct ieee80211_uhr_cap_phy); + 3 + sizeof(struct ieee80211_uhr_cap); if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 870711fb8e7e..f404dd0fce43 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2225,8 +2225,7 @@ ieee80211_link_common_elems_size(struct ieee80211_sub_if_data *sdata, sizeof(struct ieee80211_eht_mcs_nss_supp) + IEEE80211_EHT_PPE_THRES_MAX_LEN; - size += 2 + 1 + sizeof(struct ieee80211_uhr_cap) + - sizeof(struct ieee80211_uhr_cap_phy); + size += 2 + 1 + sizeof(struct ieee80211_uhr_cap); return size; } diff --git a/net/mac80211/uhr.c b/net/mac80211/uhr.c index 2d8f5e5480ef..ca3b471b7981 100644 --- a/net/mac80211/uhr.c +++ b/net/mac80211/uhr.c @@ -15,7 +15,6 @@ ieee80211_uhr_cap_ie_to_sta_uhr_cap(struct ieee80211_sub_if_data *sdata, struct link_sta_info *link_sta) { struct ieee80211_sta_uhr_cap *sta_uhr_cap = &link_sta->pub->uhr_cap; - bool from_ap; memset(sta_uhr_cap, 0, sizeof(*sta_uhr_cap)); @@ -23,8 +22,6 @@ ieee80211_uhr_cap_ie_to_sta_uhr_cap(struct ieee80211_sub_if_data *sdata, return; sta_uhr_cap->has_uhr = true; - sta_uhr_cap->mac = uhr_cap->mac; - from_ap = sdata->vif.type == NL80211_IFTYPE_STATION; - sta_uhr_cap->phy = *ieee80211_uhr_phy_cap(uhr_cap, from_ap); + sta_uhr_cap->phy = uhr_cap->phy; } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 61ec2116fab2..00e46b5bc020 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -4641,8 +4641,7 @@ int ieee80211_put_uhr_cap(struct sk_buff *skb, if (!uhr_cap) return 0; - len = 2 + 1 + sizeof(struct ieee80211_uhr_cap) + - sizeof(struct ieee80211_uhr_cap_phy); + len = 2 + 1 + sizeof(struct ieee80211_uhr_cap); if (skb_tailroom(skb) < len) return -ENOBUFS;