| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | /* |
| 3 | * IEEE 802.11 HE definitions |
| 4 | * |
| 5 | * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen |
| 6 | * <jkmaline@cc.hut.fi> |
| 7 | * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> |
| 8 | * Copyright (c) 2005, Devicescape Software, Inc. |
| 9 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> |
| 10 | * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH |
| 11 | * Copyright (c) 2016 - 2017 Intel Deutschland GmbH |
| 12 | * Copyright (c) 2018 - 2025 Intel Corporation |
| 13 | */ |
| 14 | |
| 15 | #ifndef LINUX_IEEE80211_HE_H |
| 16 | #define LINUX_IEEE80211_HE_H |
| 17 | |
| 18 | #include <linux/types.h> |
| 19 | #include <linux/if_ether.h> |
| 20 | |
| 21 | #define IEEE80211_TWT_CONTROL_NDP BIT(0) |
| 22 | #define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1) |
| 23 | #define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) |
| 24 | #define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) |
| 25 | #define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) |
| 26 | |
| 27 | #define IEEE80211_TWT_REQTYPE_REQUEST BIT(0) |
| 28 | #define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1) |
| 29 | #define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) |
| 30 | #define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) |
| 31 | #define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) |
| 32 | #define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7) |
| 33 | #define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10) |
| 34 | #define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) |
| 35 | |
| 36 | enum ieee80211_twt_setup_cmd { |
| 37 | TWT_SETUP_CMD_REQUEST, |
| 38 | TWT_SETUP_CMD_SUGGEST, |
| 39 | TWT_SETUP_CMD_DEMAND, |
| 40 | TWT_SETUP_CMD_GROUPING, |
| 41 | TWT_SETUP_CMD_ACCEPT, |
| 42 | TWT_SETUP_CMD_ALTERNATE, |
| 43 | TWT_SETUP_CMD_DICTATE, |
| 44 | TWT_SETUP_CMD_REJECT, |
| 45 | }; |
| 46 | |
| 47 | struct ieee80211_twt_params { |
| 48 | __le16 req_type; |
| 49 | __le64 twt; |
| 50 | u8 min_twt_dur; |
| 51 | __le16 mantissa; |
| 52 | u8 channel; |
| 53 | } __packed; |
| 54 | |
| 55 | struct ieee80211_twt_setup { |
| 56 | u8 dialog_token; |
| 57 | u8 element_id; |
| 58 | u8 length; |
| 59 | u8 control; |
| 60 | u8 params[]; |
| 61 | } __packed; |
| 62 | |
| 63 | /** |
| 64 | * struct ieee80211_he_cap_elem - HE capabilities element |
| 65 | * @mac_cap_info: HE MAC Capabilities Information |
| 66 | * @phy_cap_info: HE PHY Capabilities Information |
| 67 | * |
| 68 | * This structure represents the fixed fields of the payload of the |
| 69 | * "HE capabilities element" as described in IEEE Std 802.11ax-2021 |
| 70 | * sections 9.4.2.248.2 and 9.4.2.248.3. |
| 71 | */ |
| 72 | struct ieee80211_he_cap_elem { |
| 73 | u8 mac_cap_info[6]; |
| 74 | u8 phy_cap_info[11]; |
| 75 | } __packed; |
| 76 | |
| 77 | #define IEEE80211_TX_RX_MCS_NSS_DESC_MAX_LEN 5 |
| 78 | |
| 79 | /** |
| 80 | * enum ieee80211_he_mcs_support - HE MCS support definitions |
| 81 | * @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the |
| 82 | * number of streams |
| 83 | * @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported |
| 84 | * @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported |
| 85 | * @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported |
| 86 | * |
| 87 | * These definitions are used in each 2-bit subfield of the rx_mcs_* |
| 88 | * and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are |
| 89 | * both split into 8 subfields by number of streams. These values indicate |
| 90 | * which MCSes are supported for the number of streams the value appears |
| 91 | * for. |
| 92 | */ |
| 93 | enum ieee80211_he_mcs_support { |
| 94 | IEEE80211_HE_MCS_SUPPORT_0_7 = 0, |
| 95 | IEEE80211_HE_MCS_SUPPORT_0_9 = 1, |
| 96 | IEEE80211_HE_MCS_SUPPORT_0_11 = 2, |
| 97 | IEEE80211_HE_MCS_NOT_SUPPORTED = 3, |
| 98 | }; |
| 99 | |
| 100 | /** |
| 101 | * struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field |
| 102 | * |
| 103 | * This structure holds the data required for the Tx/Rx HE MCS NSS Support Field |
| 104 | * described in P802.11ax_D2.0 section 9.4.2.237.4 |
| 105 | * |
| 106 | * @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel |
| 107 | * widths less than 80MHz. |
| 108 | * @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel |
| 109 | * widths less than 80MHz. |
| 110 | * @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel |
| 111 | * width 160MHz. |
| 112 | * @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel |
| 113 | * width 160MHz. |
| 114 | * @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for |
| 115 | * channel width 80p80MHz. |
| 116 | * @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for |
| 117 | * channel width 80p80MHz. |
| 118 | */ |
| 119 | struct ieee80211_he_mcs_nss_supp { |
| 120 | __le16 rx_mcs_80; |
| 121 | __le16 tx_mcs_80; |
| 122 | __le16 rx_mcs_160; |
| 123 | __le16 tx_mcs_160; |
| 124 | __le16 rx_mcs_80p80; |
| 125 | __le16 tx_mcs_80p80; |
| 126 | } __packed; |
| 127 | |
| 128 | /** |
| 129 | * struct ieee80211_he_operation - HE Operation element |
| 130 | * @he_oper_params: HE Operation Parameters + BSS Color Information |
| 131 | * @he_mcs_nss_set: Basic HE-MCS And NSS Set |
| 132 | * @optional: Optional fields VHT Operation Information, Max Co-Hosted |
| 133 | * BSSID Indicator, and 6 GHz Operation Information |
| 134 | * |
| 135 | * This structure represents the payload of the "HE Operation |
| 136 | * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.249. |
| 137 | */ |
| 138 | struct ieee80211_he_operation { |
| 139 | __le32 he_oper_params; |
| 140 | __le16 he_mcs_nss_set; |
| 141 | u8 optional[]; |
| 142 | } __packed; |
| 143 | |
| 144 | /** |
| 145 | * struct ieee80211_he_spr - Spatial Reuse Parameter Set element |
| 146 | * @he_sr_control: SR Control |
| 147 | * @optional: Optional fields Non-SRG OBSS PD Max Offset, SRG OBSS PD |
| 148 | * Min Offset, SRG OBSS PD Max Offset, SRG BSS Color |
| 149 | * Bitmap, and SRG Partial BSSID Bitmap |
| 150 | * |
| 151 | * This structure represents the payload of the "Spatial Reuse |
| 152 | * Parameter Set element" as described in IEEE Std 802.11ax-2021 |
| 153 | * section 9.4.2.252. |
| 154 | */ |
| 155 | struct ieee80211_he_spr { |
| 156 | u8 he_sr_control; |
| 157 | u8 optional[]; |
| 158 | } __packed; |
| 159 | |
| 160 | /** |
| 161 | * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field |
| 162 | * @aifsn: ACI/AIFSN |
| 163 | * @ecw_min_max: ECWmin/ECWmax |
| 164 | * @mu_edca_timer: MU EDCA Timer |
| 165 | * |
| 166 | * This structure represents the "MU AC Parameter Record" as described |
| 167 | * in IEEE Std 802.11ax-2021 section 9.4.2.251, Figure 9-788p. |
| 168 | */ |
| 169 | struct ieee80211_he_mu_edca_param_ac_rec { |
| 170 | u8 aifsn; |
| 171 | u8 ecw_min_max; |
| 172 | u8 mu_edca_timer; |
| 173 | } __packed; |
| 174 | |
| 175 | /** |
| 176 | * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element |
| 177 | * @mu_qos_info: QoS Info |
| 178 | * @ac_be: MU AC_BE Parameter Record |
| 179 | * @ac_bk: MU AC_BK Parameter Record |
| 180 | * @ac_vi: MU AC_VI Parameter Record |
| 181 | * @ac_vo: MU AC_VO Parameter Record |
| 182 | * |
| 183 | * This structure represents the payload of the "MU EDCA Parameter Set |
| 184 | * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.251. |
| 185 | */ |
| 186 | struct ieee80211_mu_edca_param_set { |
| 187 | u8 mu_qos_info; |
| 188 | struct ieee80211_he_mu_edca_param_ac_rec ac_be; |
| 189 | struct ieee80211_he_mu_edca_param_ac_rec ac_bk; |
| 190 | struct ieee80211_he_mu_edca_param_ac_rec ac_vi; |
| 191 | struct ieee80211_he_mu_edca_param_ac_rec ac_vo; |
| 192 | } __packed; |
| 193 | |
| 194 | /* 802.11ax HE MAC capabilities */ |
| 195 | #define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01 |
| 196 | #define IEEE80211_HE_MAC_CAP0_TWT_REQ 0x02 |
| 197 | #define IEEE80211_HE_MAC_CAP0_TWT_RES 0x04 |
| 198 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_NOT_SUPP 0x00 |
| 199 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_1 0x08 |
| 200 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_2 0x10 |
| 201 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_3 0x18 |
| 202 | #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK 0x18 |
| 203 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_1 0x00 |
| 204 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_2 0x20 |
| 205 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_4 0x40 |
| 206 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_8 0x60 |
| 207 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_16 0x80 |
| 208 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_32 0xa0 |
| 209 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_64 0xc0 |
| 210 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_UNLIMITED 0xe0 |
| 211 | #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_MASK 0xe0 |
| 212 | |
| 213 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_UNLIMITED 0x00 |
| 214 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_128 0x01 |
| 215 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_256 0x02 |
| 216 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_512 0x03 |
| 217 | #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_MASK 0x03 |
| 218 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US 0x00 |
| 219 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_8US 0x04 |
| 220 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US 0x08 |
| 221 | #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK 0x0c |
| 222 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_1 0x00 |
| 223 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_2 0x10 |
| 224 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_3 0x20 |
| 225 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_4 0x30 |
| 226 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_5 0x40 |
| 227 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_6 0x50 |
| 228 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_7 0x60 |
| 229 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8 0x70 |
| 230 | #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_MASK 0x70 |
| 231 | |
| 232 | /* Link adaptation is split between byte HE_MAC_CAP1 and |
| 233 | * HE_MAC_CAP2. It should be set only if IEEE80211_HE_MAC_CAP0_HTC_HE |
| 234 | * in which case the following values apply: |
| 235 | * 0 = No feedback. |
| 236 | * 1 = reserved. |
| 237 | * 2 = Unsolicited feedback. |
| 238 | * 3 = both |
| 239 | */ |
| 240 | #define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION 0x80 |
| 241 | |
| 242 | #define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION 0x01 |
| 243 | #define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 |
| 244 | #define IEEE80211_HE_MAC_CAP2_TRS 0x04 |
| 245 | #define IEEE80211_HE_MAC_CAP2_BSR 0x08 |
| 246 | #define IEEE80211_HE_MAC_CAP2_BCAST_TWT 0x10 |
| 247 | #define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP 0x20 |
| 248 | #define IEEE80211_HE_MAC_CAP2_MU_CASCADING 0x40 |
| 249 | #define IEEE80211_HE_MAC_CAP2_ACK_EN 0x80 |
| 250 | |
| 251 | #define IEEE80211_HE_MAC_CAP3_OMI_CONTROL 0x02 |
| 252 | #define IEEE80211_HE_MAC_CAP3_OFDMA_RA 0x04 |
| 253 | |
| 254 | /* The maximum length of an A-MDPU is defined by the combination of the Maximum |
| 255 | * A-MDPU Length Exponent field in the HT capabilities, VHT capabilities and the |
| 256 | * same field in the HE capabilities. |
| 257 | */ |
| 258 | #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_0 0x00 |
| 259 | #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1 0x08 |
| 260 | #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2 0x10 |
| 261 | #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3 0x18 |
| 262 | #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK 0x18 |
| 263 | #define IEEE80211_HE_MAC_CAP3_AMSDU_FRAG 0x20 |
| 264 | #define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED 0x40 |
| 265 | #define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS 0x80 |
| 266 | |
| 267 | #define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG 0x01 |
| 268 | #define IEEE80211_HE_MAC_CAP4_QTP 0x02 |
| 269 | #define IEEE80211_HE_MAC_CAP4_BQR 0x04 |
| 270 | #define IEEE80211_HE_MAC_CAP4_PSR_RESP 0x08 |
| 271 | #define IEEE80211_HE_MAC_CAP4_NDP_FB_REP 0x10 |
| 272 | #define IEEE80211_HE_MAC_CAP4_OPS 0x20 |
| 273 | #define IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU 0x40 |
| 274 | /* Multi TID agg TX is split between byte #4 and #5 |
| 275 | * The value is a combination of B39,B40,B41 |
| 276 | */ |
| 277 | #define IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39 0x80 |
| 278 | |
| 279 | #define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 0x01 |
| 280 | #define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 0x02 |
| 281 | #define IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION 0x04 |
| 282 | #define IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU 0x08 |
| 283 | #define IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX 0x10 |
| 284 | #define IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS 0x20 |
| 285 | #define IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING 0x40 |
| 286 | #define IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX 0x80 |
| 287 | |
| 288 | #define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR 20 |
| 289 | #define IEEE80211_HE_HT_MAX_AMPDU_FACTOR 16 |
| 290 | #define IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR 13 |
| 291 | |
| 292 | /* 802.11ax HE PHY capabilities */ |
| 293 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 |
| 294 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 |
| 295 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G 0x08 |
| 296 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G 0x10 |
| 297 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL 0x1e |
| 298 | |
| 299 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G 0x20 |
| 300 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G 0x40 |
| 301 | #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK 0xfe |
| 302 | |
| 303 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ 0x01 |
| 304 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ 0x02 |
| 305 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ 0x04 |
| 306 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ 0x08 |
| 307 | #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK 0x0f |
| 308 | #define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A 0x10 |
| 309 | #define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 |
| 310 | #define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 |
| 311 | /* Midamble RX/TX Max NSTS is split between byte #2 and byte #3 */ |
| 312 | #define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 |
| 313 | |
| 314 | #define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 |
| 315 | #define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 |
| 316 | #define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ 0x04 |
| 317 | #define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 |
| 318 | #define IEEE80211_HE_PHY_CAP2_DOPPLER_TX 0x10 |
| 319 | #define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 |
| 320 | |
| 321 | /* Note that the meaning of UL MU below is different between an AP and a non-AP |
| 322 | * sta, where in the AP case it indicates support for Rx and in the non-AP sta |
| 323 | * case it indicates support for Tx. |
| 324 | */ |
| 325 | #define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO 0x40 |
| 326 | #define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO 0x80 |
| 327 | |
| 328 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM 0x00 |
| 329 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK 0x01 |
| 330 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK 0x02 |
| 331 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM 0x03 |
| 332 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK 0x03 |
| 333 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 0x00 |
| 334 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2 0x04 |
| 335 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM 0x00 |
| 336 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK 0x08 |
| 337 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK 0x10 |
| 338 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 |
| 339 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK 0x18 |
| 340 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 |
| 341 | #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2 0x20 |
| 342 | #define IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU 0x40 |
| 343 | #define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER 0x80 |
| 344 | |
| 345 | #define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 |
| 346 | #define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER 0x02 |
| 347 | |
| 348 | /* Minimal allowed value of Max STS under 80MHz is 3 */ |
| 349 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c |
| 350 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 0x10 |
| 351 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_6 0x14 |
| 352 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_7 0x18 |
| 353 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8 0x1c |
| 354 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK 0x1c |
| 355 | |
| 356 | /* Minimal allowed value of Max STS above 80MHz is 3 */ |
| 357 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 0x60 |
| 358 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 0x80 |
| 359 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_6 0xa0 |
| 360 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_7 0xc0 |
| 361 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 0xe0 |
| 362 | #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK 0xe0 |
| 363 | |
| 364 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_1 0x00 |
| 365 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 0x01 |
| 366 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_3 0x02 |
| 367 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_4 0x03 |
| 368 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_5 0x04 |
| 369 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_6 0x05 |
| 370 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_7 0x06 |
| 371 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_8 0x07 |
| 372 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK 0x07 |
| 373 | |
| 374 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_1 0x00 |
| 375 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 0x08 |
| 376 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_3 0x10 |
| 377 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_4 0x18 |
| 378 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_5 0x20 |
| 379 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_6 0x28 |
| 380 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_7 0x30 |
| 381 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_8 0x38 |
| 382 | #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK 0x38 |
| 383 | |
| 384 | #define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 |
| 385 | #define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 |
| 386 | |
| 387 | #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 |
| 388 | #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 |
| 389 | #define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB 0x04 |
| 390 | #define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB 0x08 |
| 391 | #define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB 0x10 |
| 392 | #define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE 0x20 |
| 393 | #define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 |
| 394 | #define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 |
| 395 | |
| 396 | #define IEEE80211_HE_PHY_CAP7_PSR_BASED_SR 0x01 |
| 397 | #define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP 0x02 |
| 398 | #define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 |
| 399 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_1 0x08 |
| 400 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_2 0x10 |
| 401 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_3 0x18 |
| 402 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_4 0x20 |
| 403 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_5 0x28 |
| 404 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_6 0x30 |
| 405 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_7 0x38 |
| 406 | #define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK 0x38 |
| 407 | #define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ 0x40 |
| 408 | #define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ 0x80 |
| 409 | |
| 410 | #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI 0x01 |
| 411 | #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 |
| 412 | #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU 0x04 |
| 413 | #define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU 0x08 |
| 414 | #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI 0x10 |
| 415 | #define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_TX_2X_AND_1XLTF 0x20 |
| 416 | #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242 0x00 |
| 417 | #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484 0x40 |
| 418 | #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996 0x80 |
| 419 | #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996 0xc0 |
| 420 | #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK 0xc0 |
| 421 | |
| 422 | #define IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM 0x01 |
| 423 | #define IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK 0x02 |
| 424 | #define IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU 0x04 |
| 425 | #define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU 0x08 |
| 426 | #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 |
| 427 | #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 |
| 428 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US 0x0 |
| 429 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US 0x1 |
| 430 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US 0x2 |
| 431 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED 0x3 |
| 432 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS 6 |
| 433 | #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK 0xc0 |
| 434 | |
| 435 | #define IEEE80211_HE_PHY_CAP10_HE_MU_M1RU_MAX_LTF 0x01 |
| 436 | |
| 437 | /* 802.11ax HE TX/RX MCS NSS Support */ |
| 438 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS (3) |
| 439 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_POS (6) |
| 440 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_POS (11) |
| 441 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0 |
| 442 | #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800 |
| 443 | |
| 444 | /* TX/RX HE MCS Support field Highest MCS subfield encoding */ |
| 445 | enum ieee80211_he_highest_mcs_supported_subfield_enc { |
| 446 | HIGHEST_MCS_SUPPORTED_MCS7 = 0, |
| 447 | HIGHEST_MCS_SUPPORTED_MCS8, |
| 448 | HIGHEST_MCS_SUPPORTED_MCS9, |
| 449 | HIGHEST_MCS_SUPPORTED_MCS10, |
| 450 | HIGHEST_MCS_SUPPORTED_MCS11, |
| 451 | }; |
| 452 | |
| 453 | /* Calculate 802.11ax HE capabilities IE Tx/Rx HE MCS NSS Support Field size */ |
| 454 | static inline u8 |
| 455 | ieee80211_he_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap) |
| 456 | { |
| 457 | u8 count = 4; |
| 458 | |
| 459 | if (he_cap->phy_cap_info[0] & |
| 460 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) |
| 461 | count += 4; |
| 462 | |
| 463 | if (he_cap->phy_cap_info[0] & |
| 464 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) |
| 465 | count += 4; |
| 466 | |
| 467 | return count; |
| 468 | } |
| 469 | |
| 470 | /* 802.11ax HE PPE Thresholds */ |
| 471 | #define IEEE80211_PPE_THRES_NSS_SUPPORT_2NSS (1) |
| 472 | #define IEEE80211_PPE_THRES_NSS_POS (0) |
| 473 | #define IEEE80211_PPE_THRES_NSS_MASK (7) |
| 474 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_2x966_AND_966_RU \ |
| 475 | (BIT(5) | BIT(6)) |
| 476 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK 0x78 |
| 477 | #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS (3) |
| 478 | #define IEEE80211_PPE_THRES_INFO_PPET_SIZE (3) |
| 479 | #define (7) |
| 480 | |
| 481 | /* |
| 482 | * Calculate 802.11ax HE capabilities IE PPE field size |
| 483 | * Input: Header byte of ppe_thres (first byte), and HE capa IE's PHY cap u8* |
| 484 | */ |
| 485 | static inline u8 |
| 486 | ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) |
| 487 | { |
| 488 | u8 n; |
| 489 | |
| 490 | if ((phy_cap_info[6] & |
| 491 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) |
| 492 | return 0; |
| 493 | |
| 494 | n = hweight8(ppe_thres_hdr & |
| 495 | IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK); |
| 496 | n *= (1 + ((ppe_thres_hdr & IEEE80211_PPE_THRES_NSS_MASK) >> |
| 497 | IEEE80211_PPE_THRES_NSS_POS)); |
| 498 | |
| 499 | /* |
| 500 | * Each pair is 6 bits, and we need to add the 7 "header" bits to the |
| 501 | * total size. |
| 502 | */ |
| 503 | n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7; |
| 504 | n = DIV_ROUND_UP(n, 8); |
| 505 | |
| 506 | return n; |
| 507 | } |
| 508 | |
| 509 | static inline bool ieee80211_he_capa_size_ok(const u8 *data, u8 len) |
| 510 | { |
| 511 | const struct ieee80211_he_cap_elem *he_cap_ie_elem = (const void *)data; |
| 512 | u8 needed = sizeof(*he_cap_ie_elem); |
| 513 | |
| 514 | if (len < needed) |
| 515 | return false; |
| 516 | |
| 517 | needed += ieee80211_he_mcs_nss_size(he_cap: he_cap_ie_elem); |
| 518 | if (len < needed) |
| 519 | return false; |
| 520 | |
| 521 | if (he_cap_ie_elem->phy_cap_info[6] & |
| 522 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { |
| 523 | if (len < needed + 1) |
| 524 | return false; |
| 525 | needed += ieee80211_he_ppe_size(ppe_thres_hdr: data[needed], |
| 526 | phy_cap_info: he_cap_ie_elem->phy_cap_info); |
| 527 | } |
| 528 | |
| 529 | return len >= needed; |
| 530 | } |
| 531 | |
| 532 | /* HE Operation defines */ |
| 533 | #define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK 0x00000007 |
| 534 | #define IEEE80211_HE_OPERATION_TWT_REQUIRED 0x00000008 |
| 535 | #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK 0x00003ff0 |
| 536 | #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET 4 |
| 537 | #define IEEE80211_HE_OPERATION_VHT_OPER_INFO 0x00004000 |
| 538 | #define IEEE80211_HE_OPERATION_CO_HOSTED_BSS 0x00008000 |
| 539 | #define IEEE80211_HE_OPERATION_ER_SU_DISABLE 0x00010000 |
| 540 | #define IEEE80211_HE_OPERATION_6GHZ_OP_INFO 0x00020000 |
| 541 | #define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x3f000000 |
| 542 | #define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24 |
| 543 | #define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000 |
| 544 | #define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x80000000 |
| 545 | |
| 546 | #define IEEE80211_6GHZ_CTRL_REG_LPI_AP 0 |
| 547 | #define IEEE80211_6GHZ_CTRL_REG_SP_AP 1 |
| 548 | #define IEEE80211_6GHZ_CTRL_REG_VLP_AP 2 |
| 549 | #define IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP 3 |
| 550 | #define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD 4 |
| 551 | #define IEEE80211_6GHZ_CTRL_REG_AP_ROLE_NOT_RELEVANT 7 |
| 552 | #define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP 8 |
| 553 | |
| 554 | /** |
| 555 | * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field |
| 556 | * @primary: primary channel |
| 557 | * @control: control flags |
| 558 | * @ccfs0: channel center frequency segment 0 |
| 559 | * @ccfs1: channel center frequency segment 1 |
| 560 | * @minrate: minimum rate (in 1 Mbps units) |
| 561 | */ |
| 562 | struct ieee80211_he_6ghz_oper { |
| 563 | u8 primary; |
| 564 | #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH 0x3 |
| 565 | #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ 0 |
| 566 | #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ 1 |
| 567 | #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ 2 |
| 568 | #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3 |
| 569 | #define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4 |
| 570 | #define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x78 |
| 571 | u8 control; |
| 572 | u8 ccfs0; |
| 573 | u8 ccfs1; |
| 574 | u8 minrate; |
| 575 | } __packed; |
| 576 | |
| 577 | /** |
| 578 | * enum ieee80211_reg_conn_bits - represents Regulatory connectivity field bits. |
| 579 | * |
| 580 | * This enumeration defines bit flags used to represent regulatory connectivity |
| 581 | * field bits. |
| 582 | * |
| 583 | * @IEEE80211_REG_CONN_LPI_VALID: Indicates whether the LPI bit is valid. |
| 584 | * @IEEE80211_REG_CONN_LPI_VALUE: Represents the value of the LPI bit. |
| 585 | * @IEEE80211_REG_CONN_SP_VALID: Indicates whether the SP bit is valid. |
| 586 | * @IEEE80211_REG_CONN_SP_VALUE: Represents the value of the SP bit. |
| 587 | */ |
| 588 | enum ieee80211_reg_conn_bits { |
| 589 | IEEE80211_REG_CONN_LPI_VALID = BIT(0), |
| 590 | IEEE80211_REG_CONN_LPI_VALUE = BIT(1), |
| 591 | IEEE80211_REG_CONN_SP_VALID = BIT(2), |
| 592 | IEEE80211_REG_CONN_SP_VALUE = BIT(3), |
| 593 | }; |
| 594 | |
| 595 | /* transmit power interpretation type of transmit power envelope element */ |
| 596 | enum ieee80211_tx_power_intrpt_type { |
| 597 | IEEE80211_TPE_LOCAL_EIRP, |
| 598 | IEEE80211_TPE_LOCAL_EIRP_PSD, |
| 599 | IEEE80211_TPE_REG_CLIENT_EIRP, |
| 600 | IEEE80211_TPE_REG_CLIENT_EIRP_PSD, |
| 601 | }; |
| 602 | |
| 603 | /* category type of transmit power envelope element */ |
| 604 | enum ieee80211_tx_power_category_6ghz { |
| 605 | IEEE80211_TPE_CAT_6GHZ_DEFAULT = 0, |
| 606 | IEEE80211_TPE_CAT_6GHZ_SUBORDINATE = 1, |
| 607 | }; |
| 608 | |
| 609 | /* |
| 610 | * For IEEE80211_TPE_LOCAL_EIRP / IEEE80211_TPE_REG_CLIENT_EIRP, |
| 611 | * setting to 63.5 dBm means no constraint. |
| 612 | */ |
| 613 | #define IEEE80211_TPE_MAX_TX_PWR_NO_CONSTRAINT 127 |
| 614 | |
| 615 | /* |
| 616 | * For IEEE80211_TPE_LOCAL_EIRP_PSD / IEEE80211_TPE_REG_CLIENT_EIRP_PSD, |
| 617 | * setting to 127 indicates no PSD limit for the 20 MHz channel. |
| 618 | */ |
| 619 | #define IEEE80211_TPE_PSD_NO_LIMIT 127 |
| 620 | |
| 621 | /** |
| 622 | * struct ieee80211_tx_pwr_env - Transmit Power Envelope |
| 623 | * @info: Transmit Power Information field |
| 624 | * @variable: Maximum Transmit Power field |
| 625 | * |
| 626 | * This structure represents the payload of the "Transmit Power |
| 627 | * Envelope element" as described in IEEE Std 802.11ax-2021 section |
| 628 | * 9.4.2.161 |
| 629 | */ |
| 630 | struct ieee80211_tx_pwr_env { |
| 631 | u8 info; |
| 632 | u8 variable[]; |
| 633 | } __packed; |
| 634 | |
| 635 | #define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7 |
| 636 | #define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 |
| 637 | #define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0 |
| 638 | |
| 639 | #define IEEE80211_TX_PWR_ENV_EXT_COUNT 0xF |
| 640 | |
| 641 | static inline bool ieee80211_valid_tpe_element(const u8 *data, u8 len) |
| 642 | { |
| 643 | const struct ieee80211_tx_pwr_env *env = (const void *)data; |
| 644 | u8 count, interpret, category; |
| 645 | u8 needed = sizeof(*env); |
| 646 | u8 N; /* also called N in the spec */ |
| 647 | |
| 648 | if (len < needed) |
| 649 | return false; |
| 650 | |
| 651 | count = u8_get_bits(v: env->info, IEEE80211_TX_PWR_ENV_INFO_COUNT); |
| 652 | interpret = u8_get_bits(v: env->info, IEEE80211_TX_PWR_ENV_INFO_INTERPRET); |
| 653 | category = u8_get_bits(v: env->info, IEEE80211_TX_PWR_ENV_INFO_CATEGORY); |
| 654 | |
| 655 | switch (category) { |
| 656 | case IEEE80211_TPE_CAT_6GHZ_DEFAULT: |
| 657 | case IEEE80211_TPE_CAT_6GHZ_SUBORDINATE: |
| 658 | break; |
| 659 | default: |
| 660 | return false; |
| 661 | } |
| 662 | |
| 663 | switch (interpret) { |
| 664 | case IEEE80211_TPE_LOCAL_EIRP: |
| 665 | case IEEE80211_TPE_REG_CLIENT_EIRP: |
| 666 | if (count > 3) |
| 667 | return false; |
| 668 | |
| 669 | /* count == 0 encodes 1 value for 20 MHz, etc. */ |
| 670 | needed += count + 1; |
| 671 | |
| 672 | if (len < needed) |
| 673 | return false; |
| 674 | |
| 675 | /* there can be extension fields not accounted for in 'count' */ |
| 676 | |
| 677 | return true; |
| 678 | case IEEE80211_TPE_LOCAL_EIRP_PSD: |
| 679 | case IEEE80211_TPE_REG_CLIENT_EIRP_PSD: |
| 680 | if (count > 4) |
| 681 | return false; |
| 682 | |
| 683 | N = count ? 1 << (count - 1) : 1; |
| 684 | needed += N; |
| 685 | |
| 686 | if (len < needed) |
| 687 | return false; |
| 688 | |
| 689 | if (len > needed) { |
| 690 | u8 K = u8_get_bits(v: env->variable[N], |
| 691 | IEEE80211_TX_PWR_ENV_EXT_COUNT); |
| 692 | |
| 693 | needed += 1 + K; |
| 694 | if (len < needed) |
| 695 | return false; |
| 696 | } |
| 697 | |
| 698 | return true; |
| 699 | } |
| 700 | |
| 701 | return false; |
| 702 | } |
| 703 | |
| 704 | /* |
| 705 | * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size |
| 706 | * @he_oper_ie: byte data of the He Operations IE, stating from the byte |
| 707 | * after the ext ID byte. It is assumed that he_oper_ie has at least |
| 708 | * sizeof(struct ieee80211_he_operation) bytes, the caller must have |
| 709 | * validated this. |
| 710 | * @return the actual size of the IE data (not including header), or 0 on error |
| 711 | */ |
| 712 | static inline u8 |
| 713 | ieee80211_he_oper_size(const u8 *he_oper_ie) |
| 714 | { |
| 715 | const struct ieee80211_he_operation *he_oper = (const void *)he_oper_ie; |
| 716 | u8 oper_len = sizeof(struct ieee80211_he_operation); |
| 717 | u32 he_oper_params; |
| 718 | |
| 719 | /* Make sure the input is not NULL */ |
| 720 | if (!he_oper_ie) |
| 721 | return 0; |
| 722 | |
| 723 | /* Calc required length */ |
| 724 | he_oper_params = le32_to_cpu(he_oper->he_oper_params); |
| 725 | if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) |
| 726 | oper_len += 3; |
| 727 | if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) |
| 728 | oper_len++; |
| 729 | if (he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO) |
| 730 | oper_len += sizeof(struct ieee80211_he_6ghz_oper); |
| 731 | |
| 732 | /* Add the first byte (extension ID) to the total length */ |
| 733 | oper_len++; |
| 734 | |
| 735 | return oper_len; |
| 736 | } |
| 737 | |
| 738 | /** |
| 739 | * ieee80211_he_6ghz_oper - obtain 6 GHz operation field |
| 740 | * @he_oper: HE operation element (must be pre-validated for size) |
| 741 | * but may be %NULL |
| 742 | * |
| 743 | * Return: a pointer to the 6 GHz operation field, or %NULL |
| 744 | */ |
| 745 | static inline const struct ieee80211_he_6ghz_oper * |
| 746 | ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper) |
| 747 | { |
| 748 | const u8 *ret; |
| 749 | u32 he_oper_params; |
| 750 | |
| 751 | if (!he_oper) |
| 752 | return NULL; |
| 753 | |
| 754 | ret = (const void *)&he_oper->optional; |
| 755 | |
| 756 | he_oper_params = le32_to_cpu(he_oper->he_oper_params); |
| 757 | |
| 758 | if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)) |
| 759 | return NULL; |
| 760 | if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) |
| 761 | ret += 3; |
| 762 | if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) |
| 763 | ret++; |
| 764 | |
| 765 | return (const void *)ret; |
| 766 | } |
| 767 | |
| 768 | /* HE Spatial Reuse defines */ |
| 769 | #define IEEE80211_HE_SPR_PSR_DISALLOWED BIT(0) |
| 770 | #define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) |
| 771 | #define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT BIT(2) |
| 772 | #define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT BIT(3) |
| 773 | #define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED BIT(4) |
| 774 | |
| 775 | /* |
| 776 | * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size |
| 777 | * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the byte |
| 778 | * after the ext ID byte. It is assumed that he_spr_ie has at least |
| 779 | * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated |
| 780 | * this |
| 781 | * @return the actual size of the IE data (not including header), or 0 on error |
| 782 | */ |
| 783 | static inline u8 |
| 784 | ieee80211_he_spr_size(const u8 *he_spr_ie) |
| 785 | { |
| 786 | const struct ieee80211_he_spr *he_spr = (const void *)he_spr_ie; |
| 787 | u8 spr_len = sizeof(struct ieee80211_he_spr); |
| 788 | u8 he_spr_params; |
| 789 | |
| 790 | /* Make sure the input is not NULL */ |
| 791 | if (!he_spr_ie) |
| 792 | return 0; |
| 793 | |
| 794 | /* Calc required length */ |
| 795 | he_spr_params = he_spr->he_sr_control; |
| 796 | if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) |
| 797 | spr_len++; |
| 798 | if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) |
| 799 | spr_len += 18; |
| 800 | |
| 801 | /* Add the first byte (extension ID) to the total length */ |
| 802 | spr_len++; |
| 803 | |
| 804 | return spr_len; |
| 805 | } |
| 806 | |
| 807 | struct ieee80211_he_6ghz_capa { |
| 808 | /* uses IEEE80211_HE_6GHZ_CAP_* below */ |
| 809 | __le16 capa; |
| 810 | } __packed; |
| 811 | |
| 812 | /* HE 6 GHz band capabilities */ |
| 813 | /* uses enum ieee80211_min_mpdu_spacing values */ |
| 814 | #define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START 0x0007 |
| 815 | /* uses enum ieee80211_vht_max_ampdu_length_exp values */ |
| 816 | #define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP 0x0038 |
| 817 | /* uses IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_* values */ |
| 818 | #define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN 0x00c0 |
| 819 | /* WLAN_HT_CAP_SM_PS_* values */ |
| 820 | #define IEEE80211_HE_6GHZ_CAP_SM_PS 0x0600 |
| 821 | #define IEEE80211_HE_6GHZ_CAP_RD_RESPONDER 0x0800 |
| 822 | #define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS 0x1000 |
| 823 | #define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS 0x2000 |
| 824 | |
| 825 | #endif /* LINUX_IEEE80211_HE_H */ |
| 826 | |