/* SPDX-License-Identifier: GPL-2.0-only */ /* * IEEE 802.11 UHR definitions * * Copyright (c) 2025-2026 Intel Corporation */ #ifndef LINUX_IEEE80211_UHR_H #define LINUX_IEEE80211_UHR_H #include #include #include #include "ieee80211-eht.h" #define IEEE80211_UHR_OPER_PARAMS_DPS_ENA 0x0001 #define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA 0x0002 #define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0004 #define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0008 #define IEEE80211_UHR_OPER_PARAMS_DBE_BW 0x0070 struct ieee80211_uhr_operation { __le16 params; u8 basic_mcs_nss_set[4]; u8 variable[]; } __packed; #define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS 0x0000000F #define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x000000F0 #define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x00003F00 #define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x000FC000 #define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x00300000 #define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x00400000 #define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x00800000 /** * struct ieee80211_uhr_npca_info - npca operation information * * This structure is the "NPCA Operation Parameters field format" of "UHR * Operation Element" fields as described in P802.11bn_D1.3 * subclause 9.4.2.353. See Figure 9-aa4. * * Refer to IEEE80211_UHR_NPCA* * @params: * NPCA Primary Channel - NPCA primary channel * NPCA_Min Duration Threshold - Minimum duration of inter-BSS activity * NPCA Switching Delay - * Time needed by an NPCA AP to switch from the * BSS primary channel to the NPCA primary channel * in the unit of 4 µs. * NPCA Switching Back Delay - * Time to switch from the NPCA primary channel * to the BSS primary channel in the unit of 4 µs. * NPCA Initial QSRC - * Initialize the EDCAF QSRC[AC] variables * when an NPCA STA in the BSS * switches to NPCA operation. * NPCA MOPLEN - * Indicates which conditions can be used to * initiate an NPCA operation, * 1 -> both PHYLEN NPCA operation and MOPLEN * NPCA operation are * permitted in the BSS * 0 -> only PHYLEN NPCA operation is allowed in the BSS. * NPCA Disabled Subchannel Bitmap Present - * Indicates whether the NPCA Disabled Subchannel * Bitmap field is present. A 1 in this field indicates that * the NPCA Disabled Subchannel Bitmap field is present * @dis_subch_bmap: * A bit in the bitmap that lies within the BSS bandwidth is set * to 1 to indicate that the corresponding 20 MHz subchannel is * punctured and is set to 0 to indicate that the corresponding * 20 MHz subchannel is not punctured. A bit in the bitmap that * falls outside of the BSS bandwidth is reserved. This field is * present when the value of the NPCA Disabled Subchannel Bitmap * Field Present field is equal to 1, and not present, otherwise */ struct ieee80211_uhr_npca_info { __le32 params; __le16 dis_subch_bmap[]; } __packed; #define IEEE80211_UHR_DPS_PADDING_DELAY 0x0000003F #define IEEE80211_UHR_DPS_TRANSITION_DELAY 0x00003F00 #define IEEE80211_UHR_DPS_ICF_REQUIRED 0x00010000 #define IEEE80211_UHR_DPS_PARAMETERIZED_FLAG 0x00020000 #define IEEE80211_UHR_DPS_LC_MODE_BW 0x001C0000 #define IEEE80211_UHR_DPS_LC_MODE_NSS 0x01E00000 #define IEEE80211_UHR_DPS_LC_MODE_MCS 0x1E000000 #define IEEE80211_UHR_DPS_MOBILE_AP_DPS_STATIC_HCM 0x20000000 /** * struct ieee80211_uhr_dps_info - DPS operation information * * This structure is the "DPS Operation Parameter field" of "UHR * Operation Element" fields as described in P802.11bn_D1.3 * subclause 9.4.1.87. See Figure 9-207u. * * Refer to IEEE80211_UHR_DPS* * @params: * DPS Padding Delay - * Indicates the minimum MAC padding * duration that is required by a DPS STA * in an ICF to cause the STA to transition * from the lower capability mode to the * higher capability mode. The DPS Padding * Delay field is in units of 4 µs. * DPS Transition Delay - * Indicates the amount of time required by a * DPS STA to transition from the higher * capability mode to the lower capability * mode. The DPS Transition Delay field is in * units of 4 µs. * ICF Required - * Indicates when the DPS assisting STA needs * to transmit an ICF frame to the peer DPS STA * before performing the frame exchanges with * the peer DPS STA in a TXOP. * 1 -> indicates that the transmission of the * ICF frame to the peer DPS STA prior to * any frame exchange is needed. * 0 -> ICF transmission before the frame * exchanges with the peer DPS STA is only * needed if the frame exchange is performed * in the HC mode. * Parameterized Flag - * 0 -> indicates that only 20 MHz, 1 SS, * non-HT PPDU format with the data * rate of 6, 12, and 24 Mb/s as the * default mode are supported by the * DPS STA in the LC mode * 1 -> indicates that a bandwidth up to the * bandwidth indicated in the LC Mode * Bandwidth field, a number of spatial * streams up to the NSS indicated in * the LC Mode Nss field, and an MCS up * to the MCS indicated in the LC Mode * MCS fields are supported by the DPS * STA in the LC mode as the * parameterized mode. * LC Mode Bandwidth - * Indicates the maximum bandwidth supported * by the STA in the LC mode. * LC Mode NSS - * Indicates the maximum number of the spatial * streams supported by the STA in the LC mode. * LC Mode MCS - * Indicates the highest MCS supported by the STA * in the LC mode. * Mobile AP DPS Static HCM - * 1 -> indicates that it will remain in the DPS high * capability mode until the next TBTT on that * link. * 0 -> otherwise. */ struct ieee80211_uhr_dps_info { __le32 params; } __packed; #define IEEE80211_UHR_DBE_OPER_BANDWIDTH 0x07 #define IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES 0x08 /** * enum ieee80211_uhr_dbe_oper_bw - DBE Operational Bandwidth * * Encoding for the DBE Operational Bandwidth field in the UHR Operation * element (DBE Operation Parameters). * * @IEEE80211_UHR_DBE_OPER_BW_40: 40 MHz operational DBE bandwidth * @IEEE80211_UHR_DBE_OPER_BW_80: 80 MHz operational DBE bandwidth * @IEEE80211_UHR_DBE_OPER_BW_160: 160 MHz operational DBE bandwidth * @IEEE80211_UHR_DBE_OPER_BW_320_1: 320-1 MHz operational DBE bandwidth * @IEEE80211_UHR_DBE_OPER_BW_320_2: 320-2 MHz operational DBE bandwidth */ enum ieee80211_uhr_dbe_oper_bw { IEEE80211_UHR_DBE_OPER_BW_40 = 1, IEEE80211_UHR_DBE_OPER_BW_80 = 2, IEEE80211_UHR_DBE_OPER_BW_160 = 3, IEEE80211_UHR_DBE_OPER_BW_320_1 = 4, IEEE80211_UHR_DBE_OPER_BW_320_2 = 5, }; /** * ieee80211_uhr_dbe_bw_mhz - get bandwidth in MHz from UHR DBE bandwidth * @bw: UHR DBE bandwidth * * Return: the bandwidth in MHz, or -1 for invalid values */ static inline int ieee80211_uhr_dbe_bw_mhz(enum ieee80211_uhr_dbe_oper_bw bw) { switch (bw) { case IEEE80211_UHR_DBE_OPER_BW_40: return 40; case IEEE80211_UHR_DBE_OPER_BW_80: return 80; case IEEE80211_UHR_DBE_OPER_BW_160: return 160; case IEEE80211_UHR_DBE_OPER_BW_320_1: case IEEE80211_UHR_DBE_OPER_BW_320_2: return 320; default: return -1; } } /** * struct ieee80211_uhr_dbe_info - DBE operation information * * This structure is the "DBE Operation Parameters field" of * "UHR Operation Element" fields as described in P802.11bn_D1.3 * subclause 9.4.2.353. See Figure 9-aa6. * * Refer to IEEE80211_UHR_DBE_OPER* * @params: * B0-B2 - DBE Operational Bandwidth field, see * "enum ieee80211_uhr_dbe_oper_bw" for values. * Value 0 is reserved. * Value 1 indicates 40 MHz operational DBE bandwidth. * Value 2 indicates 80 MHz operational DBE bandwidth. * Value 3 indicates 160 MHz operational DBE bandwidth. * Value 4 indicates 320-1 MHz operational DBE bandwidth. * Value 5 indicates 320-2 MHz operational DBE bandwidth. * Values 6 to 7 are reserved. * B3 - DBE Disabled Subchannel Bitmap Present. * @dis_subch_bmap: DBE Disabled Subchannel Bitmap field is set to indicate * disabled 20 MHz subchannels within the DBE Bandwidth. */ struct ieee80211_uhr_dbe_info { u8 params; __le16 dis_subch_bmap[]; } __packed; #define IEEE80211_UHR_P_EDCA_ECWMIN 0x0F #define IEEE80211_UHR_P_EDCA_ECWMAX 0xF0 #define IEEE80211_UHR_P_EDCA_AIFSN 0x000F #define IEEE80211_UHR_P_EDCA_CW_DS 0x0030 #define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD 0x01C0 #define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD 0x0600 /** * struct ieee80211_uhr_p_edca_info - P-EDCA operation information * * This structure is the "P-EDCA Operation Parameters field" of * "UHR Operation Element" fields as described in P802.11bn_D1.3 * subclause 9.4.2.353. See Figure 9-aa5. * * Refer to IEEE80211_UHR_P_EDCA* * @p_edca_ec: P-EDCA ECWmin and ECWmax. * These fields indicate the CWmin and CWmax values used by a * P-EDCA STA during P-EDCA contention. * @params: AIFSN, CW DS, PSRC threshold, and QSRC threshold. * - The AIFSN field indicates the AIFSN value used by a P-EDCA STA * during P-EDCA contention. * - The CW DS field indicates the value used for randomization of the * transmission slot of the DS-CTS frame. The value 3 is reserved. * The value 0 indicates that randomization is not enabled. * - The P-EDCA PSRC threshold field indicates the maximum number of * allowed consecutive DS-CTS transmissions. The value 0 and values * greater than 4 are reserved. * - The P-EDCA QSRC threshold field indicates the value of the * QSRC[AC_VO] counter required to start P-EDCA contention. The * value 0 is reserved. */ struct ieee80211_uhr_p_edca_info { u8 p_edca_ec; __le16 params; } __packed; static inline bool ieee80211_uhr_oper_size_ok(const u8 *data, u8 len, bool beacon) { const struct ieee80211_uhr_operation *oper = (const void *)data; u8 needed = sizeof(*oper); if (len < needed) return false; /* nothing else present in beacons */ if (beacon) return true; /* DPS Operation Parameters (fixed 4 bytes) */ if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA)) { needed += sizeof(struct ieee80211_uhr_dps_info); if (len < needed) return false; } /* NPCA Operation Parameters (fixed 4 bytes + optional 2 bytes) */ if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)) { const struct ieee80211_uhr_npca_info *npca = (const void *)(data + needed); needed += sizeof(*npca); if (len < needed) return false; if (npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)) { needed += sizeof(npca->dis_subch_bmap[0]); if (len < needed) return false; } } /* P-EDCA Operation Parameters (fixed 3 bytes) */ if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA)) { needed += sizeof(struct ieee80211_uhr_p_edca_info); if (len < needed) return false; } /* DBE Operation Parameters (fixed 1 byte + optional 2 bytes) */ if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DBE_ENA)) { const struct ieee80211_uhr_dbe_info *dbe = (const void *)(data + needed); needed += sizeof(*dbe); if (len < needed) return false; if (dbe->params & IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES) { needed += sizeof(dbe->dis_subch_bmap[0]); if (len < needed) return false; } } return len >= needed; } /* * Note: cannot call this on the element coming from a beacon, * must ensure ieee80211_uhr_oper_size_ok(..., false) first */ static inline const struct ieee80211_uhr_npca_info * ieee80211_uhr_npca_info(const struct ieee80211_uhr_operation *oper) { const u8 *pos = oper->variable; if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA))) return NULL; if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA)) pos += sizeof(struct ieee80211_uhr_dps_info); return (const void *)pos; } static inline const __le16 * ieee80211_uhr_npca_dis_subch_bitmap(const struct ieee80211_uhr_operation *oper) { const struct ieee80211_uhr_npca_info *npca; npca = ieee80211_uhr_npca_info(oper); if (!npca) return NULL; if (!(npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES))) return NULL; return npca->dis_subch_bmap; } /* * Note: cannot call this on the element coming from a beacon, * must ensure ieee80211_uhr_oper_size_ok(..., false) first */ static inline const struct ieee80211_uhr_dbe_info * ieee80211_uhr_oper_dbe_info(const struct ieee80211_uhr_operation *oper) { const u8 *pos = oper->variable; if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DBE_ENA))) return NULL; if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA)) pos += sizeof(struct ieee80211_uhr_dps_info); if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)) { const struct ieee80211_uhr_npca_info *npca = (const void *)pos; pos += sizeof(*npca); if (npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)) pos += sizeof(npca->dis_subch_bmap[0]); } if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA)) pos += sizeof(struct ieee80211_uhr_p_edca_info); return (const void *)pos; } #define IEEE80211_UHR_MAC_CAP0_DPS_SUPP 0x01 #define IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP 0x02 #define IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP 0x04 #define IEEE80211_UHR_MAC_CAP0_NPCA_SUPP 0x10 #define IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP 0x20 #define IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP 0x40 #define IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP 0x80 #define IEEE80211_UHR_MAC_CAP1_DSO_SUPP 0x01 #define IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP 0x02 #define IEEE80211_UHR_MAC_CAP1_DBE_SUPP 0x04 #define IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP 0x08 #define IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP 0x10 #define IEEE80211_UHR_MAC_CAP1_PUO_SUPP 0x20 #define IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP 0x40 #define IEEE80211_UHR_MAC_CAP1_DUO_SUPP 0x80 #define IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP 0x01 #define IEEE80211_UHR_MAC_CAP2_AOM_SUPP 0x02 #define IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP 0x04 #define IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP 0x08 #define IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP 0x10 #define IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG 0x20 #define IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW 0xC0 #define IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH 0x03 #define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x1C #define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0xE0 #define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x03 #define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04 #define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08 #define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x10 #define IEEE80211_UHR_MAC_CAP_DBE_MAX_BW 0x07 #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 * * As per spec P802.11bn_D1.3 "Table 9-bb5—Encoding of the DBE Maximum * Supported Bandwidth field". * * @IEEE80211_UHR_DBE_MAX_BW_40: Indicates 40 MHz DBE max supported bw * @IEEE80211_UHR_DBE_MAX_BW_80: Indicates 80 MHz DBE max supported bw * @IEEE80211_UHR_DBE_MAX_BW_160: Indicates 160 MHz DBE max supported bw * @IEEE80211_UHR_DBE_MAX_BW_320: Indicates 320 MHz DBE max supported bw */ enum ieee80211_uhr_dbe_max_supported_bw { IEEE80211_UHR_DBE_MAX_BW_40 = 1, IEEE80211_UHR_DBE_MAX_BW_80 = 2, IEEE80211_UHR_DBE_MAX_BW_160 = 3, IEEE80211_UHR_DBE_MAX_BW_320 = 4, }; struct ieee80211_uhr_cap_mac { u8 mac_cap[6]; } __packed; #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 0x00000001 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 0x00000002 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 0x00000004 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 0x00000008 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 0x00000010 #define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 0x00000020 #define IEEE80211_UHR_PHY_CAP_ELR_TX 0x00000040 #define IEEE80211_UHR_PHY_CAP_ELR_RX 0x00000080 #define IEEE80211_UHR_PHY_CAP_PART_BW_DL_MUMIMO 0x00000100 #define IEEE80211_UHR_PHY_CAP_PART_BW_UL_MUMIMO 0x00000200 #define IEEE80211_UHR_PHY_CAP_MCS15 0x00000400 #define IEEE80211_UHR_PHY_CAP_2XLDPC_TX 0x00000800 #define IEEE80211_UHR_PHY_CAP_2XLDPC_RX 0x00001000 #define IEEE80211_UHR_PHY_CAP_UEQM_TX_MAX_NSS 0x00006000 #define IEEE80211_UHR_PHY_CAP_UEQM_RX_MAX_NSS 0x00018000 #define IEEE80211_UHR_PHY_CAP_CO_BF_JOINT_SOUNDING 0x00040000 #define IEEE80211_UHR_PHY_CAP_IM_TX 0x00080000 #define IEEE80211_UHR_PHY_CAP_IM_RX 0x00100000 #define IEEE80211_UHR_PHY_CAP_CO_SR_MODE_1 0x00200000 #define IEEE80211_UHR_PHY_CAP_CO_SR_MODE_2 0x00400000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_20_IN_PBW_20 0x00800000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_40_IN_PBW_40 0x01000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_80_IN_PBW_80 0x02000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_80_IN_PBW_160 0x04000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_80_IN_PBW_320 0x08000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_20_IN_PBW_GE80 0x10000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_40_IN_PBW_GE80 0x20000000 #define IEEE80211_UHR_PHY_CAP_DRU_DBW_60_IN_PBW_GE80 0x40000000 #define IEEE80211_UHR_PHY_CAP_DRU_RRU_HYBRID_MODE 0x80000000 struct ieee80211_uhr_cap_phy { __le32 cap; u8 reserved; } __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); if (len < needed) return false; /* * A non-AP STA does not include the DBE Capability Parameters field * in the UHR MAC Capabilities Information field. */ if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) { const struct ieee80211_uhr_cap_dbe *dbe; needed += sizeof(struct ieee80211_uhr_cap_dbe); if (len < needed) return false; dbe = (const void *)cap->variable; if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES) needed += sizeof(dbe->eht_mcs_map[0]); if (dbe->cap & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES) needed += sizeof(dbe->eht_mcs_map[0]); } return len >= needed; } #define IEEE80211_UHR_OM_PU_TO_128TU 11 /** * ieee80211_uhr_capa_get_om_pu_to_us - get OM parameter update timeout in usec * @cap: the UHR capability element, size must be validated * * Return: the OM parameter update timeout in usec, or -1 if it's not valid */ static inline int ieee80211_uhr_capa_get_om_pu_to_us(const struct ieee80211_uhr_cap *cap) { u8 timeout; timeout = u8_get_bits(cap->mac.mac_cap[3], IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH); timeout <<= 2; timeout |= u8_get_bits(cap->mac.mac_cap[2], IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW); if (timeout > IEEE80211_UHR_OM_PU_TO_128TU) return -1; if (!timeout) return 0; return 128 << (timeout - 1); } /* only valid from AP, must check ieee80211_uhr_capa_size_ok(..., true) */ static inline const struct ieee80211_uhr_cap_dbe * ieee80211_uhr_dbe_cap(const struct ieee80211_uhr_cap *cap) { if (!(cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP)) return NULL; return (const void *)cap->variable; } #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 #define IEEE80211_SMD_INFO_CAPA_PTK_PER_AP_MLD 0x20 struct ieee80211_smd_info { u8 id[ETH_ALEN]; u8 capa; __le16 timeout; } __packed; enum ieee80211_protected_uhr_action { IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_REQUEST = 0, IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_RESPONSE = 1, IEEE80211_PROTECTED_UHR_ACTION_LINK_RECONFIG_NOTIFY = 2, }; enum ieee80211_uhr_link_reconfig_request_type { IEEE80211_UHR_LINK_RECONFIG_REQUEST_ST_PREP = 0, IEEE80211_UHR_LINK_RECONFIG_REQUEST_ST_EXEC = 1, IEEE80211_UHR_LINK_RECONFIG_REQUEST_OMP_REQUEST = 3, }; enum ieee80211_uhr_link_reconfig_response_type { IEEE80211_UHR_LINK_RECONFIG_RESPONSE_ST_PREP = 0, IEEE80211_UHR_LINK_RECONFIG_RESPONSE_ST_EXEC = 1, }; enum ieee80211_uhr_link_reconfig_notify_type { IEEE80211_UHR_LINK_RECONFIG_NOTIFY_DL_DRAINED = 2, IEEE80211_UHR_LINK_RECONFIG_NOTIFY_OMP_RESPONSE = 3, }; enum ieee80211_uhr_mode_change_control { IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_ID = 0x003f, IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_ENABLE = 0x0040, IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_UPDATE = 0x0080, IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_LENGTH = 0x0f00, IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_SPECIFIC = 0xf000, }; enum ieee80211_uhr_mode_change_mode_id { IEEE80211_UHR_MODE_CHANGE_MODE_ID_DPS = 0, IEEE80211_UHR_MODE_CHANGE_MODE_ID_NPCA = 1, IEEE80211_UHR_MODE_CHANGE_MODE_ID_DUO = 2, IEEE80211_UHR_MODE_CHANGE_MODE_ID_DSO = 3, IEEE80211_UHR_MODE_CHANGE_MODE_ID_P_EDCA = 4, IEEE80211_UHR_MODE_CHANGE_MODE_ID_ELR_RX = 5, IEEE80211_UHR_MODE_CHANGE_MODE_ID_AOM = 6, IEEE80211_UHR_MODE_CHANGE_MODE_ID_LLI = 7, IEEE80211_UHR_MODE_CHANGE_MODE_ID_CO_BF = 8, IEEE80211_UHR_MODE_CHANGE_MODE_ID_CO_SR = 9, IEEE80211_UHR_MODE_CHANGE_MODE_ID_EMLSR = 10, IEEE80211_UHR_MODE_CHANGE_MODE_ID_DBE = 11, }; struct ieee80211_uhr_mode_change_tuple { __le16 control; u8 variable[]; } __packed; static inline int ieee80211_uhr_mode_change_tuple_size(const struct ieee80211_uhr_mode_change_tuple *tuple) { return sizeof(*tuple) + le16_get_bits(tuple->control, IEEE80211_UHR_MODE_CHANGE_CONTROL_MODE_LENGTH); } #define for_each_uhr_mode_change_tuple(data, len, tuple) \ for (tuple = (const void *)(data); \ (len) - ((const u8 *)tuple - (data)) >= sizeof(*tuple) && \ (len) - ((const u8 *)tuple - (data)) >= \ ieee80211_uhr_mode_change_tuple_size(tuple); \ tuple = (const void *)((const u8 *)tuple + \ ieee80211_uhr_mode_change_tuple_size(tuple))) #endif /* LINUX_IEEE80211_UHR_H */