carl9170 toolchain: update binutils, gcc
[carl9170fw.git] / include / linux / ieee80211.h
index a4e66d4bce86291500da3f721d6fbfb9a4a5600d..8c9c9c6cae692e2b67d3d470c5bb0cb42ccf95ff 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
  * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (c) 2018 - 2022 Intel Corporation
+ * Copyright (c) 2018 - 2023 Intel Corporation
  */
 
 #ifndef __LINUX_IEEE80211_H
@@ -263,6 +263,11 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 /* Mesh Control 802.11s */
 #define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT  0x0100
 
+/* Mesh Power Save Level */
+#define IEEE80211_QOS_CTL_MESH_PS_LEVEL                0x0200
+/* Mesh Receiver Service Period Initiated */
+#define IEEE80211_QOS_CTL_RSPI                 0x0400
+
 /* U-APSD queue for WMM IEs sent by AP */
 #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD      (1<<7)
 #define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f
@@ -326,6 +331,17 @@ struct ieee80211_qos_hdr {
        __le16 qos_ctrl;
 } __packed __aligned(2);
 
+struct ieee80211_qos_hdr_4addr {
+       __le16 frame_control;
+       __le16 duration_id;
+       u8 addr1[6];
+       u8 addr2[6];
+       u8 addr3[6];
+       __le16 seq_ctrl;
+       u8 addr4[6];
+       __le16 qos_ctrl;
+} __packed __aligned(2);
+
 struct ieee80211_trigger {
        __le16 frame_control;
        __le16 duration;
@@ -775,20 +791,6 @@ static inline bool ieee80211_is_any_nullfunc(__le16 fc)
        return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc));
 }
 
-/**
- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
- * @fc: frame control field in little-endian byteorder
- */
-static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
-{
-       /* IEEE 802.11-2012, definition of "bufferable management frame";
-        * note that this ignores the IBSS special case. */
-       return ieee80211_is_mgmt(fc) &&
-              (ieee80211_is_action(fc) ||
-               ieee80211_is_disassoc(fc) ||
-               ieee80211_is_deauth(fc));
-}
-
 /**
  * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
@@ -843,9 +845,14 @@ enum ieee80211_preq_target_flags {
 };
 
 /**
- * struct ieee80211_quiet_ie
+ * struct ieee80211_quiet_ie - Quiet element
+ * @count: Quiet Count
+ * @period: Quiet Period
+ * @duration: Quiet Duration
+ * @offset: Quiet Offset
  *
- * This structure refers to "Quiet information element"
+ * This structure represents the payload of the "Quiet element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.22.
  */
 struct ieee80211_quiet_ie {
        u8 count;
@@ -855,9 +862,15 @@ struct ieee80211_quiet_ie {
 } __packed;
 
 /**
- * struct ieee80211_msrment_ie
+ * struct ieee80211_msrment_ie - Measurement element
+ * @token: Measurement Token
+ * @mode: Measurement Report Mode
+ * @type: Measurement Type
+ * @request: Measurement Request or Measurement Report
  *
- * This structure refers to "Measurement Request/Report information element"
+ * This structure represents the payload of both the "Measurement
+ * Request element" and the "Measurement Report element" as described
+ * in IEEE Std 802.11-2020 sections 9.4.2.20 and 9.4.2.21.
  */
 struct ieee80211_msrment_ie {
        u8 token;
@@ -867,9 +880,14 @@ struct ieee80211_msrment_ie {
 } __packed;
 
 /**
- * struct ieee80211_channel_sw_ie
+ * struct ieee80211_channel_sw_ie - Channel Switch Announcement element
+ * @mode: Channel Switch Mode
+ * @new_ch_num: New Channel Number
+ * @count: Channel Switch Count
  *
- * This structure refers to "Channel Switch Announcement information element"
+ * This structure represents the payload of the "Channel Switch
+ * Announcement element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.18.
  */
 struct ieee80211_channel_sw_ie {
        u8 mode;
@@ -878,9 +896,14 @@ struct ieee80211_channel_sw_ie {
 } __packed;
 
 /**
- * struct ieee80211_ext_chansw_ie
+ * struct ieee80211_ext_chansw_ie - Extended Channel Switch Announcement element
+ * @mode: Channel Switch Mode
+ * @new_operating_class: New Operating Class
+ * @new_ch_num: New Channel Number
+ * @count: Channel Switch Count
  *
- * This structure represents the "Extended Channel Switch Announcement element"
+ * This structure represents the "Extended Channel Switch Announcement
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.52.
  */
 struct ieee80211_ext_chansw_ie {
        u8 mode;
@@ -901,8 +924,14 @@ struct ieee80211_sec_chan_offs_ie {
 
 /**
  * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE
+ * @mesh_ttl: Time To Live
+ * @mesh_flags: Flags
+ * @mesh_reason: Reason Code
+ * @mesh_pre_value: Precedence Value
  *
- * This structure represents the "Mesh Channel Switch Paramters element"
+ * This structure represents the payload of the "Mesh Channel Switch
+ * Parameters element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.102.
  */
 struct ieee80211_mesh_chansw_params_ie {
        u8 mesh_ttl;
@@ -913,6 +942,13 @@ struct ieee80211_mesh_chansw_params_ie {
 
 /**
  * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
+ * @new_channel_width: New Channel Width
+ * @new_center_freq_seg0: New Channel Center Frequency Segment 0
+ * @new_center_freq_seg1: New Channel Center Frequency Segment 1
+ *
+ * This structure represents the payload of the "Wide Bandwidth
+ * Channel Switch element" as described in IEEE Std 802.11-2020
+ * section 9.4.2.160.
  */
 struct ieee80211_wide_bw_chansw_ie {
        u8 new_channel_width;
@@ -920,9 +956,14 @@ struct ieee80211_wide_bw_chansw_ie {
 } __packed;
 
 /**
- * struct ieee80211_tim
+ * struct ieee80211_tim_ie - Traffic Indication Map information element
+ * @dtim_count: DTIM Count
+ * @dtim_period: DTIM Period
+ * @bitmap_ctrl: Bitmap Control
+ * @virtual_map: Partial Virtual Bitmap
  *
- * This structure refers to "Traffic Indication Map information element"
+ * This structure represents the payload of the "TIM element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.5.
  */
 struct ieee80211_tim_ie {
        u8 dtim_count;
@@ -933,9 +974,17 @@ struct ieee80211_tim_ie {
 } __packed;
 
 /**
- * struct ieee80211_meshconf_ie
+ * struct ieee80211_meshconf_ie - Mesh Configuration element
+ * @meshconf_psel: Active Path Selection Protocol Identifier
+ * @meshconf_pmetric: Active Path Selection Metric Identifier
+ * @meshconf_congest: Congestion Control Mode Identifier
+ * @meshconf_synch: Synchronization Method Identifier
+ * @meshconf_auth: Authentication Protocol Identifier
+ * @meshconf_form: Mesh Formation Info
+ * @meshconf_cap: Mesh Capability (see &enum mesh_config_capab_flags)
  *
- * This structure refers to "Mesh Configuration information element"
+ * This structure represents the payload of the "Mesh Configuration
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.97.
  */
 struct ieee80211_meshconf_ie {
        u8 meshconf_psel;
@@ -955,16 +1004,22 @@ struct ieee80211_meshconf_ie {
  * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
  * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
  *     is ongoing
+ * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has
+ *     neighbors in deep sleep mode
+ *
+ * Enumerates the "Mesh Capability" as described in IEEE Std
+ * 802.11-2020 section 9.4.2.97.7.
  */
 enum mesh_config_capab_flags {
        IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS          = 0x01,
        IEEE80211_MESHCONF_CAPAB_FORWARDING             = 0x08,
        IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING         = 0x20,
+       IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL       = 0x40,
 };
 
 #define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1
 
-/**
+/*
  * mesh channel switch parameters element's flag indicator
  *
  */
@@ -973,9 +1028,17 @@ enum mesh_config_capab_flags {
 #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2)
 
 /**
- * struct ieee80211_rann_ie
+ * struct ieee80211_rann_ie - RANN (root announcement) element
+ * @rann_flags: Flags
+ * @rann_hopcount: Hop Count
+ * @rann_ttl: Element TTL
+ * @rann_addr: Root Mesh STA Address
+ * @rann_seq: HWMP Sequence Number
+ * @rann_interval: Interval
+ * @rann_metric: Metric
  *
- * This structure refers to "Root Announcement information element"
+ * This structure represents the payload of the "RANN element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.111.
  */
 struct ieee80211_rann_ie {
        u8 rann_flags;
@@ -997,7 +1060,7 @@ enum ieee80211_ht_chanwidth_values {
 };
 
 /**
- * enum ieee80211_opmode_bits - VHT operating mode field bits
+ * enum ieee80211_vht_opmode_bits - VHT operating mode field bits
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK: channel width mask
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: 20 MHz channel width
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width
@@ -1046,9 +1109,12 @@ enum ieee80211_s1g_chanwidth {
 #define WLAN_USER_POSITION_LEN 16
 
 /**
- * struct ieee80211_tpc_report_ie
+ * struct ieee80211_tpc_report_ie - TPC Report element
+ * @tx_power: Transmit Power
+ * @link_margin: Link Margin
  *
- * This structure refers to "TPC Report element"
+ * This structure represents the payload of the "TPC Report element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.16.
  */
 struct ieee80211_tpc_report_ie {
        u8 tx_power;
@@ -1066,9 +1132,14 @@ struct ieee80211_addba_ext_ie {
 } __packed;
 
 /**
- * struct ieee80211_s1g_bcn_compat_ie
+ * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element
+ * @compat_info: Compatibility Information
+ * @beacon_int: Beacon Interval
+ * @tsf_completion: TSF Completion
  *
- * S1G Beacon Compatibility element
+ * This structure represents the payload of the "S1G Beacon
+ * Compatibility element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.196.
  */
 struct ieee80211_s1g_bcn_compat_ie {
        __le16 compat_info;
@@ -1077,9 +1148,15 @@ struct ieee80211_s1g_bcn_compat_ie {
 } __packed;
 
 /**
- * struct ieee80211_s1g_oper_ie
+ * struct ieee80211_s1g_oper_ie - S1G Operation element
+ * @ch_width: S1G Operation Information Channel Width
+ * @oper_class: S1G Operation Information Operating Class
+ * @primary_ch: S1G Operation Information Primary Channel Number
+ * @oper_ch: S1G Operation Information  Channel Center Frequency
+ * @basic_mcs_nss: Basic S1G-MCS and NSS Set
  *
- * S1G Operation element
+ * This structure represents the payload of the "S1G Operation
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.212.
  */
 struct ieee80211_s1g_oper_ie {
        u8 ch_width;
@@ -1090,9 +1167,13 @@ struct ieee80211_s1g_oper_ie {
 } __packed;
 
 /**
- * struct ieee80211_aid_response_ie
+ * struct ieee80211_aid_response_ie - AID Response element
+ * @aid: AID/Group AID
+ * @switch_count: AID Switch Count
+ * @response_int: AID Response Interval
  *
- * AID Response element
+ * This structure represents the payload of the "AID Response element"
+ * as described in IEEE Std 802.11-2020 section 9.4.2.194.
  */
 struct ieee80211_aid_response_ie {
        __le16 aid;
@@ -1346,14 +1427,18 @@ struct ieee80211_mgmt {
                                } __packed wnm_timing_msr;
                        } u;
                } __packed __aligned(4) action;
+               DECLARE_FLEX_ARRAY(u8, body); /* Generic frame body */
        } u __aligned(2);
 } __packed __aligned(2);
 
 /* Supported rates membership selectors */
 #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
 #define BSS_MEMBERSHIP_SELECTOR_VHT_PHY        126
-#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
+#define BSS_MEMBERSHIP_SELECTOR_GLK    125
+#define BSS_MEMBERSHIP_SELECTOR_EPS    124
 #define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123
+#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
+#define BSS_MEMBERSHIP_SELECTOR_EHT_PHY        121
 
 /* mgmt header + 1 byte category code */
 #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
@@ -1489,7 +1574,7 @@ struct ieee80211_tdls_data {
 /*
  * Peer-to-Peer IE attribute related definitions.
  */
-/**
+/*
  * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute.
  */
 enum ieee80211_p2p_attr_id {
@@ -1539,11 +1624,17 @@ struct ieee80211_p2p_noa_attr {
 #define IEEE80211_P2P_OPPPS_CTWINDOW_MASK      0x7F
 
 /**
- * struct ieee80211_bar - HT Block Ack Request
+ * struct ieee80211_bar - Block Ack Request frame format
+ * @frame_control: Frame Control
+ * @duration: Duration
+ * @ra: RA
+ * @ta: TA
+ * @control: BAR Control
+ * @start_seq_num: Starting Sequence Number (see Figure 9-37)
  *
- * This structure refers to "HT BlockAckReq" as
- * described in 802.11n draft section 7.2.1.7.1
- */
+ * This structure represents the "BlockAckReq frame format"
+ * as described in IEEE Std 802.11-2020 section 9.3.1.7.
+*/
 struct ieee80211_bar {
        __le16 frame_control;
        __le16 duration;
@@ -1553,7 +1644,7 @@ struct ieee80211_bar {
        __le16 start_seq_num;
 } __packed __aligned(2);
 
-/* 802.11 BA(R) control masks */
+/* 802.11 BAR control masks */
 #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL   0x0000
 #define IEEE80211_BAR_CTRL_MULTI_TID           0x0002
 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA        0x0004
@@ -1580,13 +1671,17 @@ struct ieee80211_ba {
 #define IEEE80211_HT_MCS_MASK_LEN              10
 
 /**
- * struct ieee80211_mcs_info - MCS information
+ * struct ieee80211_mcs_info - Supported MCS Set field
  * @rx_mask: RX mask
  * @rx_highest: highest supported RX rate. If set represents
  *     the highest supported RX data rate in units of 1 Mbps.
  *     If this field is 0 this value should not be used to
  *     consider the highest RX data rate supported.
  * @tx_params: TX parameters
+ * @reserved: Reserved bits
+ *
+ * This structure represents the "Supported MCS Set field" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.55.4.
  */
 struct ieee80211_mcs_info {
        u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
@@ -1617,10 +1712,16 @@ struct ieee80211_mcs_info {
        (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
 
 /**
- * struct ieee80211_ht_cap - HT capabilities
+ * struct ieee80211_ht_cap - HT capabilities element
+ * @cap_info: HT Capability Information
+ * @ampdu_params_info: A-MPDU Parameters
+ * @mcs: Supported MCS Set
+ * @extended_ht_cap_info: HT Extended Capabilities
+ * @tx_BF_cap_info: Transmit Beamforming Capabilities
+ * @antenna_selection_info: ASEL Capability
  *
- * This structure is the "HT capabilities element" as
- * described in 802.11n D5.0 7.3.2.57
+ * This structure represents the payload of the "HT Capabilities
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.55.
  */
 struct ieee80211_ht_cap {
        __le16 cap_info;
@@ -1708,9 +1809,14 @@ enum ieee80211_min_mpdu_spacing {
 
 /**
  * struct ieee80211_ht_operation - HT operation IE
+ * @primary_chan: Primary Channel
+ * @ht_param: HT Operation Information parameters
+ * @operation_mode: HT Operation Information operation mode
+ * @stbc_param: HT Operation Information STBC params
+ * @basic_set: Basic HT-MCS Set
  *
- * This structure is the "HT operation element" as
- * described in 802.11n-2009 7.3.2.57
+ * This structure represents the payload of the "HT Operation
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.56.
  */
 struct ieee80211_ht_operation {
        u8 primary_chan;
@@ -1879,9 +1985,12 @@ struct ieee80211_vht_operation {
 
 /**
  * struct ieee80211_he_cap_elem - HE capabilities element
+ * @mac_cap_info: HE MAC Capabilities Information
+ * @phy_cap_info: HE PHY Capabilities Information
  *
- * This structure is the "HE capabilities element" fixed fields as
- * described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3
+ * This structure represents the fixed fields of the payload of the
+ * "HE capabilities element" as described in IEEE Std 802.11ax-2021
+ * sections 9.4.2.248.2 and 9.4.2.248.3.
  */
 struct ieee80211_he_cap_elem {
        u8 mac_cap_info[6];
@@ -1940,35 +2049,45 @@ struct ieee80211_he_mcs_nss_supp {
 } __packed;
 
 /**
- * struct ieee80211_he_operation - HE capabilities element
+ * struct ieee80211_he_operation - HE Operation element
+ * @he_oper_params: HE Operation Parameters + BSS Color Information
+ * @he_mcs_nss_set: Basic HE-MCS And NSS Set
+ * @optional: Optional fields VHT Operation Information, Max Co-Hosted
+ *            BSSID Indicator, and 6 GHz Operation Information
  *
- * This structure is the "HE operation element" fields as
- * described in P802.11ax_D4.0 section 9.4.2.243
+ * This structure represents the payload of the "HE Operation
+ * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.249.
  */
 struct ieee80211_he_operation {
        __le32 he_oper_params;
        __le16 he_mcs_nss_set;
-       /* Optional 0,1,3,4,5,7 or 8 bytes: depends on @he_oper_params */
        u8 optional[];
 } __packed;
 
 /**
- * struct ieee80211_he_spr - HE spatial reuse element
+ * struct ieee80211_he_spr - Spatial Reuse Parameter Set element
+ * @he_sr_control: SR Control
+ * @optional: Optional fields Non-SRG OBSS PD Max Offset, SRG OBSS PD
+ *            Min Offset, SRG OBSS PD Max Offset, SRG BSS Color
+ *            Bitmap, and SRG Partial BSSID Bitmap
  *
- * This structure is the "HE spatial reuse element" element as
- * described in P802.11ax_D4.0 section 9.4.2.241
+ * This structure represents the payload of the "Spatial Reuse
+ * Parameter Set element" as described in IEEE Std 802.11ax-2021
+ * section 9.4.2.252.
  */
 struct ieee80211_he_spr {
        u8 he_sr_control;
-       /* Optional 0 to 19 bytes: depends on @he_sr_control */
        u8 optional[];
 } __packed;
 
 /**
  * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
+ * @aifsn: ACI/AIFSN
+ * @ecw_min_max: ECWmin/ECWmax
+ * @mu_edca_timer: MU EDCA Timer
  *
- * This structure is the "MU AC Parameter Record" fields as
- * described in P802.11ax_D4.0 section 9.4.2.245
+ * This structure represents the "MU AC Parameter Record" as described
+ * in IEEE Std 802.11ax-2021 section 9.4.2.251, Figure 9-788p.
  */
 struct ieee80211_he_mu_edca_param_ac_rec {
        u8 aifsn;
@@ -1978,9 +2097,14 @@ struct ieee80211_he_mu_edca_param_ac_rec {
 
 /**
  * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element
+ * @mu_qos_info: QoS Info
+ * @ac_be: MU AC_BE Parameter Record
+ * @ac_bk: MU AC_BK Parameter Record
+ * @ac_vi: MU AC_VI Parameter Record
+ * @ac_vo: MU AC_VO Parameter Record
  *
- * This structure is the "MU EDCA Parameter Set element" fields as
- * described in P802.11ax_D4.0 section 9.4.2.245
+ * This structure represents the payload of the "MU EDCA Parameter Set
+ * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.251.
  */
 struct ieee80211_mu_edca_param_set {
        u8 mu_qos_info;
@@ -2013,12 +2137,18 @@ struct ieee80211_mu_edca_param_set {
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_20mhz_only {
-       u8 rx_tx_mcs7_max_nss;
-       u8 rx_tx_mcs9_max_nss;
-       u8 rx_tx_mcs11_max_nss;
-       u8 rx_tx_mcs13_max_nss;
+       union {
+               struct {
+                       u8 rx_tx_mcs7_max_nss;
+                       u8 rx_tx_mcs9_max_nss;
+                       u8 rx_tx_mcs11_max_nss;
+                       u8 rx_tx_mcs13_max_nss;
+               };
+               u8 rx_tx_max_nss[4];
+       };
 };
 
 /**
@@ -2038,11 +2168,17 @@ struct ieee80211_eht_mcs_nss_supp_20mhz_only {
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_bw {
-       u8 rx_tx_mcs9_max_nss;
-       u8 rx_tx_mcs11_max_nss;
-       u8 rx_tx_mcs13_max_nss;
+       union {
+               struct {
+                       u8 rx_tx_mcs9_max_nss;
+                       u8 rx_tx_mcs11_max_nss;
+                       u8 rx_tx_mcs13_max_nss;
+               };
+               u8 rx_tx_max_nss[3];
+       };
 };
 
 /**
@@ -2095,7 +2231,7 @@ struct ieee80211_eht_cap_elem {
  */
 struct ieee80211_eht_operation {
        u8 params;
-       __le32 basic_mcs_nss;
+       struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss;
        u8 optional[];
 } __packed;
 
@@ -2182,9 +2318,9 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
  * enum ieee80211_ap_reg_power - regulatory power for a Access Point
  *
  * @IEEE80211_REG_UNSET_AP: Access Point has no regulatory power mode
- * @IEEE80211_REG_LPI: Indoor Access Point
- * @IEEE80211_REG_SP: Standard power Access Point
- * @IEEE80211_REG_VLP: Very low power Access Point
+ * @IEEE80211_REG_LPI_AP: Indoor Access Point
+ * @IEEE80211_REG_SP_AP: Standard power Access Point
+ * @IEEE80211_REG_VLP_AP: Very low power Access Point
  * @IEEE80211_REG_AP_POWER_AFTER_LAST: internal
  * @IEEE80211_REG_AP_POWER_MAX: maximum value
  */
@@ -2572,7 +2708,7 @@ static inline bool ieee80211_he_capa_size_ok(const u8 *data, u8 len)
 #define IEEE80211_6GHZ_CTRL_REG_SP_AP  1
 
 /**
- * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
+ * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
  * @primary: primary channel
  * @control: control flags
  * @ccfs0: channel center frequency segment 0
@@ -2619,9 +2755,13 @@ enum ieee80211_tx_power_intrpt_type {
 };
 
 /**
- * struct ieee80211_tx_pwr_env
+ * struct ieee80211_tx_pwr_env - Transmit Power Envelope
+ * @tx_power_info: Transmit Power Information field
+ * @tx_power: Maximum Transmit Power field
  *
- * This structure represents the "Transmit Power Envelope element"
+ * This structure represents the payload of the "Transmit Power
+ * Envelope element" as described in IEEE Std 802.11ax-2021 section
+ * 9.4.2.161
  */
 struct ieee80211_tx_pwr_env {
        u8 tx_power_info;
@@ -2876,6 +3016,7 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
 
 /* Maximum number of supported EHT LTF is split */
 #define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK       0xc0
+#define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF              0x40
 #define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK       0x07
 
 #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK                 0x78
@@ -2955,7 +3096,7 @@ ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
 
        n = hweight16(ppe_thres_hdr &
                      IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
-       n *= 1 + (ppe_thres_hdr & IEEE80211_EHT_PPE_THRES_NSS_MASK);
+       n *= 1 + u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_NSS_MASK);
 
        /*
         * Each pair is 6 bits, and we need to add the 9 "header" bits to the
@@ -2989,7 +3130,7 @@ ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len,
                if (len < needed + sizeof(ppe_thres_hdr))
                        return false;
 
-               ppe_thres_hdr = (data[needed] >> 8) + data[needed + 1];
+               ppe_thres_hdr = get_unaligned_le16(data + needed);
                needed += ieee80211_eht_ppe_size(ppe_thres_hdr,
                                                 elem->phy_cap_info);
        }
@@ -3563,11 +3704,6 @@ enum ieee80211_unprotected_wnm_actioncode {
        WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE = 1,
 };
 
-/* Public action codes */
-enum ieee80211_public_actioncode {
-       WLAN_PUBLIC_ACTION_FTM_RESPONSE = 33,
-};
-
 /* Security key length */
 enum ieee80211_key_len {
        WLAN_KEY_LEN_WEP40 = 5,
@@ -3659,7 +3795,7 @@ enum ieee80211_pub_actioncode {
        WLAN_PUB_ACTION_NETWORK_CHANNEL_CONTROL = 30,
        WLAN_PUB_ACTION_WHITE_SPACE_MAP_ANN = 31,
        WLAN_PUB_ACTION_FTM_REQUEST = 32,
-       WLAN_PUB_ACTION_FTM = 33,
+       WLAN_PUB_ACTION_FTM_RESPONSE = 33,
        WLAN_PUB_ACTION_FILS_DISCOVERY = 34,
 };
 
@@ -4078,16 +4214,21 @@ struct ieee80211_he_6ghz_capa {
  * @hdr: the frame
  *
  * The qos ctrl bytes come after the frame_control, duration, seq_num
- * and 3 or 4 addresses of length ETH_ALEN.
- * 3 addr: 2 + 2 + 2 + 3*6 = 24
- * 4 addr: 2 + 2 + 2 + 4*6 = 30
+ * and 3 or 4 addresses of length ETH_ALEN. Checks frame_control to choose
+ * between struct ieee80211_qos_hdr_4addr and struct ieee80211_qos_hdr.
  */
 static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr)
 {
-       if (ieee80211_has_a4(hdr->frame_control))
-               return (u8 *)hdr + 30;
+       union {
+               struct ieee80211_qos_hdr        addr3;
+               struct ieee80211_qos_hdr_4addr  addr4;
+       } *qos;
+
+       qos = (void *)hdr;
+       if (ieee80211_has_a4(qos->addr3.frame_control))
+               return (u8 *)&qos->addr4.qos_ctrl;
        else
-               return (u8 *)hdr + 24;
+               return (u8 *)&qos->addr3.qos_ctrl;
 }
 
 /**
@@ -4138,6 +4279,44 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
                return hdr->addr1;
 }
 
+/**
+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
+ * @skb: the skb to check, starting with the 802.11 header
+ */
+static inline bool ieee80211_is_bufferable_mmpdu(struct ieee80211_hdr *hdr, size_t len)
+{
+       struct ieee80211_mgmt *mgmt = (void *)hdr;
+       __le16 fc = mgmt->frame_control;
+
+       /*
+        * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
+        * note that this ignores the IBSS special case.
+        */
+       if (!ieee80211_is_mgmt(fc))
+               return false;
+
+       if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
+               return true;
+
+       if (!ieee80211_is_action(fc))
+               return false;
+
+       if (len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
+               return true;
+
+       /* action frame - additionally check for non-bufferable FTM */
+
+       if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
+           mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
+               return true;
+
+       if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
+           mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_RESPONSE)
+               return false;
+
+       return true;
+}
+
 /**
  * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
  * @hdr: the frame (buffer must include at least the first octet of payload)
@@ -4232,29 +4411,41 @@ static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim,
                                       u8 tim_len, u16 aid)
 {
        u8 mask;
-       u8 indexn0, indexn1, indexn2;
+       u8 index, indexn1, indexn2;
 
        if (unlikely(!tim || tim_len < sizeof(*tim)))
                return false;
 
        aid &= 0x3fff;
-       indexn0 = aid / 8;
+       index = aid / 8;
        mask  = 1 << (aid & 7);
 
        indexn1 = tim->bitmap_ctrl & 0xfe;
        indexn2 = tim_len + indexn1 - 4;
 
-       if (indexn0 < indexn1 || indexn0 > indexn2)
+       if (index < indexn1 || index > indexn2)
                return false;
 
-       indexn0 -= indexn1;
+       index -= indexn1;
 
-       return !!(tim->virtual_map[indexn0] & mask);
+       return !!(tim->virtual_map[index] & mask);
 }
 
 /* convert time units */
-#define TU_TO_JIFFIES(x)       (usecs_to_jiffies((x) * 1024))
-#define TU_TO_EXP_TIME(x)      (jiffies + TU_TO_JIFFIES(x))
+#define TU_TO_JIFFIES(x)       (usecs_to_jiffies((x) * 1024))
+#define TU_TO_EXP_TIME(x)      (jiffies + TU_TO_JIFFIES(x))
+
+/* convert frequencies */
+#define MHZ_TO_KHZ(freq) ((freq) * 1000)
+#define KHZ_TO_MHZ(freq) ((freq) / 1000)
+#define PR_KHZ(f) KHZ_TO_MHZ(f), f % 1000
+#define KHZ_F "%d.%03d"
+
+/* convert powers */
+#define DBI_TO_MBI(gain) ((gain) * 100)
+#define MBI_TO_DBI(gain) ((gain) / 100)
+#define DBM_TO_MBM(gain) ((gain) * 100)
+#define MBM_TO_DBM(gain) ((gain) / 100)
 
 static inline bool ieee80211_is_timing_measurement(struct ieee80211_hdr *hdr, size_t len)
 {
@@ -4283,7 +4474,7 @@ static inline bool ieee80211_is_ftm(struct ieee80211_hdr *hdr, size_t len)
                return false;
 
        if (mgmt->u.action.u.ftm.action_code ==
-               WLAN_PUBLIC_ACTION_FTM_RESPONSE &&
+               WLAN_PUB_ACTION_FTM_RESPONSE &&
            len >= offsetofend(typeof(*mgmt), u.action.u.ftm))
                return true;
 
@@ -4324,18 +4515,6 @@ struct element {
 #define for_each_subelement_extid(sub, extid, element)                 \
        for_each_element_extid(sub, extid, (element)->data, (element)->datalen)
 
-/* convert frequencies */
-#define MHZ_TO_KHZ(freq) ((freq) * 1000)
-#define KHZ_TO_MHZ(freq) ((freq) / 1000)
-#define PR_KHZ(f) KHZ_TO_MHZ(f), f % 1000
-#define KHZ_F "%d.%03d"
-
-/* convert powers */
-#define DBI_TO_MBI(gain) ((gain) * 100)
-#define MBI_TO_DBI(gain) ((gain) / 100)
-#define DBM_TO_MBM(gain) ((gain) * 100)
-#define MBM_TO_DBM(gain) ((gain) / 100)
-
 /**
  * for_each_element_completed - determine if element parsing consumed all data
  * @element: element pointer after for_each_element() or friends
@@ -4355,7 +4534,7 @@ static inline bool for_each_element_completed(const struct element *element,
        return (const u8 *)element == (const u8 *)data + datalen;
 }
 
-/**
+/*
  * RSNX Capabilities:
  * bits 0-3: Field length (n-1)
  */
@@ -4370,8 +4549,8 @@ static inline bool for_each_element_completed(const struct element *element,
 #define IEEE80211_AP_INFO_TBTT_HDR_FILTERED                    0x04
 #define IEEE80211_AP_INFO_TBTT_HDR_COLOC                       0x08
 #define IEEE80211_AP_INFO_TBTT_HDR_COUNT                       0xF0
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM             9
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM       13
+#define IEEE80211_TBTT_INFO_TYPE_TBTT                          0
+#define IEEE80211_TBTT_INFO_TYPE_MLD                           1
 
 #define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED              0x01
 #define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID                    0x02
@@ -4381,6 +4560,9 @@ static inline bool for_each_element_completed(const struct element *element,
 #define IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE                 0x20
 #define IEEE80211_RNR_TBTT_PARAMS_COLOC_AP                     0x40
 
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_NO_LIMIT                 127
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED                 -128
+
 struct ieee80211_neighbor_ap_info {
        u8 tbtt_info_hdr;
        u8 tbtt_info_len;
@@ -4395,6 +4577,42 @@ enum ieee80211_range_params_max_total_ltf {
        IEEE80211_RANGE_PARAMS_MAX_TOTAL_LTF_UNSPECIFIED,
 };
 
+/*
+ * reduced neighbor report, based on Draft P802.11be_D3.0,
+ * section 9.4.2.170.2.
+ */
+struct ieee80211_rnr_mld_params {
+       u8 mld_id;
+       __le16 params;
+} __packed;
+
+#define IEEE80211_RNR_MLD_PARAMS_LINK_ID                       0x000F
+#define IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT              0x0FF0
+#define IEEE80211_RNR_MLD_PARAMS_UPDATES_INCLUDED              0x1000
+#define IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK                 0x2000
+
+/* Format of the TBTT information element if it has 7, 8 or 9 bytes */
+struct ieee80211_tbtt_info_7_8_9 {
+       u8 tbtt_offset;
+       u8 bssid[6];
+
+       /* The following element is optional, structure may not grow */
+       u8 bss_params;
+       s8 psd_20;
+} __packed;
+
+/* Format of the TBTT information element if it has >= 11 bytes */
+struct ieee80211_tbtt_info_ge_11 {
+       u8 tbtt_offset;
+       u8 bssid[6];
+       __le32 short_ssid;
+
+       /* The following elements are optional, structure may grow */
+       u8 bss_params;
+       s8 psd_20;
+       struct ieee80211_rnr_mld_params mld_params;
+} __packed;
+
 /* multi-link device */
 #define IEEE80211_MLD_MAX_NUM_LINKS    15
 
@@ -4422,6 +4640,14 @@ struct ieee80211_multi_link_elem {
 #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH   0x0f00
 #define IEEE80211_MED_SYNC_DELAY_SYNC_MAX_NUM_TXOPS    0xf000
 
+/*
+ * Described in P802.11be_D3.0
+ * dot11MSDTimerDuration should default to 5484 (i.e. 171.375)
+ * dot11MSDOFDMEDthreshold defaults to -72 (i.e. 0)
+ * dot11MSDTXOPMAX defaults to 1
+ */
+#define IEEE80211_MED_SYNC_DELAY_DEFAULT               0x10ac
+
 #define IEEE80211_EML_CAP_EMLSR_SUPP                   0x0001
 #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY          0x000e
 #define  IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_0US             0
@@ -4504,15 +4730,12 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
        case IEEE80211_ML_CONTROL_TYPE_BASIC:
        case IEEE80211_ML_CONTROL_TYPE_PREQ:
        case IEEE80211_ML_CONTROL_TYPE_TDLS:
+       case IEEE80211_ML_CONTROL_TYPE_RECONF:
                /*
                 * The length is the first octet pointed by mle->variable so no
                 * need to add anything
                 */
                break;
-       case IEEE80211_ML_CONTROL_TYPE_RECONF:
-               if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR)
-                       common += 6;
-               return common;
        case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS:
                if (control & IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR)
                        common += 6;
@@ -4521,7 +4744,96 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
                return 0;
        }
 
-       return common + mle->variable[0];
+       return sizeof(*mle) + common + mle->variable[0];
+}
+
+/**
+ * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count
+ * @mle: the basic multi link element
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the BSS parameter change count value can't be found (the presence bit
+ * for it is clear), 0 will be returned.
+ */
+static inline u8
+ieee80211_mle_get_bss_param_ch_cnt(const struct ieee80211_multi_link_elem *mle)
+{
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       /* common points now at the beginning of ieee80211_mle_basic_common_info */
+       common += sizeof(struct ieee80211_mle_basic_common_info);
+
+       if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT))
+               return 0;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+
+       return *common;
+}
+
+/**
+ * ieee80211_mle_get_eml_med_sync_delay - returns the medium sync delay
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the medium synchronization is not present, then the default value is
+ * returned.
+ */
+static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data)
+{
+       const struct ieee80211_multi_link_elem *mle = (const void *)data;
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       /* common points now at the beginning of ieee80211_mle_basic_common_info */
+       common += sizeof(struct ieee80211_mle_basic_common_info);
+
+       if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY))
+               return IEEE80211_MED_SYNC_DELAY_DEFAULT;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+               common += 1;
+
+       return get_unaligned_le16(common);
+}
+
+/**
+ * ieee80211_mle_get_eml_cap - returns the EML capability
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the EML capability is not present, 0 will be returned.
+ */
+static inline u16 ieee80211_mle_get_eml_cap(const u8 *data)
+{
+       const struct ieee80211_multi_link_elem *mle = (const void *)data;
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       /* common points now at the beginning of ieee80211_mle_basic_common_info */
+       common += sizeof(struct ieee80211_mle_basic_common_info);
+
+       if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA))
+               return 0;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)
+               common += 2;
+
+       return get_unaligned_le16(common);
 }
 
 /**
@@ -4592,6 +4904,28 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len)
        return mle->variable[0] >= common;
 }
 
+/**
+ * ieee80211_mle_type_ok - validate multi-link element type and size
+ * @data: pointer to the element data
+ * @type: expected type of the element
+ * @len: length of the containing element
+ */
+static inline bool ieee80211_mle_type_ok(const u8 *data, u8 type, size_t len)
+{
+       const struct ieee80211_multi_link_elem *mle = (const void *)data;
+       u16 control;
+
+       if (!ieee80211_mle_size_ok(data, len))
+               return false;
+
+       control = le16_to_cpu(mle->control);
+
+       if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) == type)
+               return true;
+
+       return false;
+}
+
 enum ieee80211_mle_subelems {
        IEEE80211_MLE_SUBELEM_PER_STA_PROFILE           = 0,
        IEEE80211_MLE_SUBELEM_FRAGMENT                  = 254,
@@ -4614,11 +4948,13 @@ struct ieee80211_mle_per_sta_profile {
 } __packed;
 
 /**
- * ieee80211_mle_sta_prof_size_ok - validate multi-link element sta profile size
+ * ieee80211_mle_basic_sta_prof_size_ok - validate basic multi-link element sta
+ *     profile size
  * @data: pointer to the sub element data
  * @len: length of the containing sub element
  */
-static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len)
+static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data,
+                                                       size_t len)
 {
        const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;
        u16 control;
@@ -4638,21 +4974,93 @@ static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len)
                info_len += 8;
        if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
                info_len += 2;
-       if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)
-               info_len += 1;
-
        if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
-           control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) {
+           control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
                if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
                        info_len += 2;
                else
                        info_len += 1;
        }
+       if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)
+               info_len += 1;
 
        return prof->sta_info_len >= info_len &&
               fixed + prof->sta_info_len <= len;
 }
 
+/**
+ * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS
+ *     parameter change count
+ * @prof: the per-STA profile, having been checked with
+ *     ieee80211_mle_basic_sta_prof_size_ok() for the correct length
+ *
+ * Return: The BSS parameter change count value if present, 0 otherwise.
+ */
+static inline u8
+ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof)
+{
+       u16 control = le16_to_cpu(prof->control);
+       const u8 *pos = prof->variable;
+
+       if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT))
+               return 0;
+
+       if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT)
+               pos += 6;
+       if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT)
+               pos += 2;
+       if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT)
+               pos += 8;
+       if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
+               pos += 2;
+       if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
+           control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
+               if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
+                       pos += 2;
+               else
+                       pos += 1;
+       }
+
+       return *pos;
+}
+
+#define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID                       0x000f
+#define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE              0x0010
+#define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT          0x0020
+#define IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT          0x0040
+#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_UPDATE_TYPE         0x0780
+#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT      0x0800
+
+/**
+ * ieee80211_mle_reconf_sta_prof_size_ok - validate reconfiguration multi-link
+ *     element sta profile size.
+ * @data: pointer to the sub element data
+ * @len: length of the containing sub element
+ */
+static inline bool ieee80211_mle_reconf_sta_prof_size_ok(const u8 *data,
+                                                        size_t len)
+{
+       const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;
+       u16 control;
+       u8 fixed = sizeof(*prof);
+       u8 info_len = 1;
+
+       if (len < fixed)
+               return false;
+
+       control = le16_to_cpu(prof->control);
+
+       if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT)
+               info_len += 6;
+       if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
+               info_len += 2;
+       if (control & IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT)
+               info_len += 2;
+
+       return prof->sta_info_len >= info_len &&
+              ((size_t)(fixed + prof->sta_info_len - 1) <= len);
+}
+
 #define for_each_mle_subelement(_elem, _data, _len)                    \
        if (ieee80211_mle_size_ok(_data, _len))                         \
                for_each_element(_elem,                                 \