]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: update UHR capabilities field order
authorJohannes Berg <johannes.berg@intel.com>
Tue, 28 Apr 2026 08:36:57 +0000 (10:36 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 5 May 2026 12:49:01 +0000 (14:49 +0200)
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 <johannes.berg@intel.com>
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260428103657.b40af50f182d.I75306a092dc2c8a9eb7276160f0b7144b4846d18@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211-uhr.h
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/uhr.c
net/mac80211/util.c

index d199f3ebdba0ae76007c403a1932fedc8c2bc139..f4f4bd8256dff06c7be31c046fdc7ef1537a79d6 100644 (file)
@@ -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
index 8400792d67e286185d02a99b6d449aacd772232e..90d295cc364fb3d5839753b5e2c1112970de0330 100644 (file)
@@ -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. */
index 870711fb8e7e05b98aeabc290e3e518983266dbf..f404dd0fce434702b67f74360eb25e787420f01a 100644 (file)
@@ -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;
 }
index 2d8f5e5480ef41c6d4f52df5b839c41f8f6dd2e9..ca3b471b7981b9d226eb81c7fccee53ee64394e1 100644 (file)
@@ -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;
 }
index 61ec2116fab23e2104dfd3dfb0caf6ba37183e27..00e46b5bc0201adaa1132eed754149aff2981a1e 100644 (file)
@@ -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;