Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'wireless-next-2025-11-12' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Johannes Berg says:

====================
More -next material, notably:
- split ieee80211.h file, it's way too big
- mac80211: initial chanctx work towards NAN
- mac80211: MU-MIMO sniffer improvements
- ath12k: statistics improvements

* tag 'wireless-next-2025-11-12' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (26 commits)
wifi: cw1200: Fix potential memory leak in cw1200_bh_rx_helper()
wifi: mac80211: make monitor link info check more specific
wifi: mac80211: track MU-MIMO configuration on disabled interfaces
wifi: cfg80211/mac80211: Add fallback mechanism for INDOOR_SP connection
wifi: cfg80211/mac80211: clean up duplicate ap_power handling
wifi: cfg80211: use a C99 initializer in wiphy_register
wifi: cfg80211: fix doc of struct key_params
wifi: mac80211: remove unnecessary vlan NULL check
wifi: mac80211: pass frame type to element parsing
wifi: mac80211: remove "disabling VHT" message
wifi: mac80211: add and use chanctx usage iteration
wifi: mac80211: simplify ieee80211_recalc_chanctx_min_def() API
wifi: mac80211: remove chanctx to link back-references
wifi: mac80211: make link iteration safe for 'break'
wifi: mac80211: fix EHT typo
wifi: cfg80211: fix EHT typo
wifi: ieee80211: split NAN definitions out
wifi: ieee80211: split P2P definitions out
wifi: ieee80211: split S1G definitions out
wifi: ieee80211: split EHT definitions out
...
====================

Link: https://patch.msgid.link/20251112115126.16223-4-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+4003 -3653
-2
drivers/net/wireless/ath/ath12k/core.c
··· 1 1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 4 - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. 5 4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 6 5 */ 7 6 ··· 1249 1250 spin_lock_bh(&ar->data_lock); 1250 1251 ath12k_fw_stats_free(&ar->fw_stats); 1251 1252 ar->fw_stats.num_vdev_recvd = 0; 1252 - ar->fw_stats.num_bcn_recvd = 0; 1253 1253 spin_unlock_bh(&ar->data_lock); 1254 1254 } 1255 1255
-1
drivers/net/wireless/ath/ath12k/core.h
··· 646 646 struct list_head vdevs; 647 647 struct list_head bcn; 648 648 u32 num_vdev_recvd; 649 - u32 num_bcn_recvd; 650 649 }; 651 650 652 651 struct ath12k_dbg_htt_stats {
+3 -6
drivers/net/wireless/ath/ath12k/debugfs.c
··· 1286 1286 1287 1287 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1288 1288 buf); 1289 + ath12k_fw_stats_reset(ar); 1289 1290 1290 1291 file->private_data = no_free_ptr(buf); 1291 1292 ··· 1353 1352 1354 1353 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1355 1354 buf); 1356 - /* since beacon stats request is looped for all active VDEVs, saved fw 1357 - * stats is not freed for each request until done for all active VDEVs 1358 - */ 1359 - spin_lock_bh(&ar->data_lock); 1360 - ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn); 1361 - spin_unlock_bh(&ar->data_lock); 1355 + ath12k_fw_stats_reset(ar); 1362 1356 1363 1357 file->private_data = no_free_ptr(buf); 1364 1358 ··· 1414 1418 1415 1419 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1416 1420 buf); 1421 + ath12k_fw_stats_reset(ar); 1417 1422 1418 1423 file->private_data = no_free_ptr(buf); 1419 1424
+10 -5
drivers/net/wireless/ath/ath12k/mac.c
··· 5079 5079 if (ah->state != ATH12K_HW_STATE_ON) 5080 5080 return -ENETDOWN; 5081 5081 5082 - ath12k_fw_stats_reset(ar); 5083 - 5084 5082 reinit_completion(&ar->fw_stats_complete); 5085 5083 reinit_completion(&ar->fw_stats_done); 5086 5084 ··· 5176 5178 ar->chan_tx_pwr = pdev->chan_tx_power / 2; 5177 5179 spin_unlock_bh(&ar->data_lock); 5178 5180 ar->last_tx_power_update = jiffies; 5181 + ath12k_fw_stats_reset(ar); 5179 5182 5180 5183 send_tx_power: 5181 5184 *dbm = ar->chan_tx_pwr; ··· 13207 13208 13208 13209 if (!signal && 13209 13210 ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA && 13210 - !(ath12k_mac_get_fw_stats(ar, &params))) 13211 + !(ath12k_mac_get_fw_stats(ar, &params))) { 13211 13212 signal = arsta->rssi_beacon; 13213 + ath12k_fw_stats_reset(ar); 13214 + } 13212 13215 13213 13216 params.stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT; 13214 13217 if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && 13215 13218 ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA && 13216 - !(ath12k_mac_get_fw_stats(ar, &params))) 13219 + !(ath12k_mac_get_fw_stats(ar, &params))) { 13217 13220 ath12k_mac_put_chain_rssi(sinfo, arsta); 13221 + ath12k_fw_stats_reset(ar); 13222 + } 13218 13223 13219 13224 spin_lock_bh(&ar->data_lock); 13220 13225 noise_floor = ath12k_pdev_get_noise_floor(ar); ··· 13302 13299 13303 13300 if (!signal && 13304 13301 ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA && 13305 - !(ath12k_mac_get_fw_stats(ar, &params))) 13302 + !(ath12k_mac_get_fw_stats(ar, &params))) { 13306 13303 signal = arsta->rssi_beacon; 13304 + ath12k_fw_stats_reset(ar); 13305 + } 13307 13306 13308 13307 if (signal) { 13309 13308 link_sinfo->signal =
+1 -11
drivers/net/wireless/ath/ath12k/wmi.c
··· 8089 8089 buf[len - 1] = 0; 8090 8090 else 8091 8091 buf[len] = 0; 8092 - 8093 - ath12k_fw_stats_reset(ar); 8094 8092 } 8095 8093 8096 8094 static void ··· 8485 8487 ath12k_warn(ab, "empty beacon stats"); 8486 8488 return; 8487 8489 } 8488 - /* Mark end until we reached the count of all started VDEVs 8489 - * within the PDEV 8490 - */ 8491 - if (ar->num_started_vdevs) 8492 - is_end = ((++ar->fw_stats.num_bcn_recvd) == 8493 - ar->num_started_vdevs); 8494 8490 8495 8491 list_splice_tail_init(&stats->bcn, 8496 8492 &ar->fw_stats.bcn); 8497 - 8498 - if (is_end) 8499 - complete(&ar->fw_stats_done); 8493 + complete(&ar->fw_stats_done); 8500 8494 } 8501 8495 } 8502 8496
+4 -2
drivers/net/wireless/st/cw1200/bh.c
··· 317 317 318 318 if (wsm_id & 0x0400) { 319 319 int rc = wsm_release_tx_buffer(priv, 1); 320 - if (WARN_ON(rc < 0)) 320 + if (WARN_ON(rc < 0)) { 321 + dev_kfree_skb(skb_rx); 321 322 return rc; 322 - else if (rc > 0) 323 + } else if (rc > 0) { 323 324 *tx = 1; 325 + } 324 326 } 325 327 326 328 /* cw1200_wsm_rx takes care on SKB livetime */
+1182
include/linux/ieee80211-eht.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * IEEE 802.11 EHT 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_EHT_H 16 + #define LINUX_IEEE80211_EHT_H 17 + 18 + #include <linux/types.h> 19 + #include <linux/if_ether.h> 20 + /* need HE definitions for the inlines here */ 21 + #include <linux/ieee80211-he.h> 22 + 23 + #define IEEE80211_TTLM_MAX_CNT 2 24 + #define IEEE80211_TTLM_CONTROL_DIRECTION 0x03 25 + #define IEEE80211_TTLM_CONTROL_DEF_LINK_MAP 0x04 26 + #define IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT 0x08 27 + #define IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT 0x10 28 + #define IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE 0x20 29 + 30 + #define IEEE80211_TTLM_DIRECTION_DOWN 0 31 + #define IEEE80211_TTLM_DIRECTION_UP 1 32 + #define IEEE80211_TTLM_DIRECTION_BOTH 2 33 + 34 + /** 35 + * struct ieee80211_ttlm_elem - TID-To-Link Mapping element 36 + * 37 + * Defined in section 9.4.2.314 in P802.11be_D4 38 + * 39 + * @control: the first part of control field 40 + * @optional: the second part of control field 41 + */ 42 + struct ieee80211_ttlm_elem { 43 + u8 control; 44 + u8 optional[]; 45 + } __packed; 46 + 47 + #define IEEE80211_EHT_MCS_NSS_RX 0x0f 48 + #define IEEE80211_EHT_MCS_NSS_TX 0xf0 49 + 50 + /** 51 + * struct ieee80211_eht_mcs_nss_supp_20mhz_only - EHT 20MHz only station max 52 + * supported NSS for per MCS. 53 + * 54 + * For each field below, bits 0 - 3 indicate the maximal number of spatial 55 + * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams 56 + * for Tx. 57 + * 58 + * @rx_tx_mcs7_max_nss: indicates the maximum number of spatial streams 59 + * supported for reception and the maximum number of spatial streams 60 + * supported for transmission for MCS 0 - 7. 61 + * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams 62 + * supported for reception and the maximum number of spatial streams 63 + * supported for transmission for MCS 8 - 9. 64 + * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams 65 + * supported for reception and the maximum number of spatial streams 66 + * supported for transmission for MCS 10 - 11. 67 + * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams 68 + * supported for reception and the maximum number of spatial streams 69 + * supported for transmission for MCS 12 - 13. 70 + * @rx_tx_max_nss: array of the previous fields for easier loop access 71 + */ 72 + struct ieee80211_eht_mcs_nss_supp_20mhz_only { 73 + union { 74 + struct { 75 + u8 rx_tx_mcs7_max_nss; 76 + u8 rx_tx_mcs9_max_nss; 77 + u8 rx_tx_mcs11_max_nss; 78 + u8 rx_tx_mcs13_max_nss; 79 + }; 80 + u8 rx_tx_max_nss[4]; 81 + }; 82 + }; 83 + 84 + /** 85 + * struct ieee80211_eht_mcs_nss_supp_bw - EHT max supported NSS per MCS (except 86 + * 20MHz only stations). 87 + * 88 + * For each field below, bits 0 - 3 indicate the maximal number of spatial 89 + * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams 90 + * for Tx. 91 + * 92 + * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams 93 + * supported for reception and the maximum number of spatial streams 94 + * supported for transmission for MCS 0 - 9. 95 + * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams 96 + * supported for reception and the maximum number of spatial streams 97 + * supported for transmission for MCS 10 - 11. 98 + * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams 99 + * supported for reception and the maximum number of spatial streams 100 + * supported for transmission for MCS 12 - 13. 101 + * @rx_tx_max_nss: array of the previous fields for easier loop access 102 + */ 103 + struct ieee80211_eht_mcs_nss_supp_bw { 104 + union { 105 + struct { 106 + u8 rx_tx_mcs9_max_nss; 107 + u8 rx_tx_mcs11_max_nss; 108 + u8 rx_tx_mcs13_max_nss; 109 + }; 110 + u8 rx_tx_max_nss[3]; 111 + }; 112 + }; 113 + 114 + /** 115 + * struct ieee80211_eht_cap_elem_fixed - EHT capabilities fixed data 116 + * 117 + * This structure is the "EHT Capabilities element" fixed fields as 118 + * described in P802.11be_D2.0 section 9.4.2.313. 119 + * 120 + * @mac_cap_info: MAC capabilities, see IEEE80211_EHT_MAC_CAP* 121 + * @phy_cap_info: PHY capabilities, see IEEE80211_EHT_PHY_CAP* 122 + */ 123 + struct ieee80211_eht_cap_elem_fixed { 124 + u8 mac_cap_info[2]; 125 + u8 phy_cap_info[9]; 126 + } __packed; 127 + 128 + /** 129 + * struct ieee80211_eht_cap_elem - EHT capabilities element 130 + * @fixed: fixed parts, see &ieee80211_eht_cap_elem_fixed 131 + * @optional: optional parts 132 + */ 133 + struct ieee80211_eht_cap_elem { 134 + struct ieee80211_eht_cap_elem_fixed fixed; 135 + 136 + /* 137 + * Followed by: 138 + * Supported EHT-MCS And NSS Set field: 4, 3, 6 or 9 octets. 139 + * EHT PPE Thresholds field: variable length. 140 + */ 141 + u8 optional[]; 142 + } __packed; 143 + 144 + #define IEEE80211_EHT_OPER_INFO_PRESENT 0x01 145 + #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x02 146 + #define IEEE80211_EHT_OPER_EHT_DEF_PE_DURATION 0x04 147 + #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_LIMIT 0x08 148 + #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_EXP_MASK 0x30 149 + #define IEEE80211_EHT_OPER_MCS15_DISABLE 0x40 150 + 151 + /** 152 + * struct ieee80211_eht_operation - eht operation element 153 + * 154 + * This structure is the "EHT Operation Element" fields as 155 + * described in P802.11be_D2.0 section 9.4.2.311 156 + * 157 + * @params: EHT operation element parameters. See &IEEE80211_EHT_OPER_* 158 + * @basic_mcs_nss: indicates the EHT-MCSs for each number of spatial streams in 159 + * EHT PPDUs that are supported by all EHT STAs in the BSS in transmit and 160 + * receive. 161 + * @optional: optional parts 162 + */ 163 + struct ieee80211_eht_operation { 164 + u8 params; 165 + struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss; 166 + u8 optional[]; 167 + } __packed; 168 + 169 + /** 170 + * struct ieee80211_eht_operation_info - eht operation information 171 + * 172 + * @control: EHT operation information control. 173 + * @ccfs0: defines a channel center frequency for a 20, 40, 80, 160, or 320 MHz 174 + * EHT BSS. 175 + * @ccfs1: defines a channel center frequency for a 160 or 320 MHz EHT BSS. 176 + * @optional: optional parts 177 + */ 178 + struct ieee80211_eht_operation_info { 179 + u8 control; 180 + u8 ccfs0; 181 + u8 ccfs1; 182 + u8 optional[]; 183 + } __packed; 184 + 185 + /* EHT MAC capabilities as defined in P802.11be_D2.0 section 9.4.2.313.2 */ 186 + #define IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS 0x01 187 + #define IEEE80211_EHT_MAC_CAP0_OM_CONTROL 0x02 188 + #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x04 189 + #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x08 190 + #define IEEE80211_EHT_MAC_CAP0_RESTRICTED_TWT 0x10 191 + #define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC 0x20 192 + #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK 0xc0 193 + #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_3895 0 194 + #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991 1 195 + #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454 2 196 + 197 + #define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK 0x01 198 + #define IEEE80211_EHT_MAC_CAP1_EHT_TRS 0x02 199 + #define IEEE80211_EHT_MAC_CAP1_TXOP_RET 0x04 200 + #define IEEE80211_EHT_MAC_CAP1_TWO_BQRS 0x08 201 + #define IEEE80211_EHT_MAC_CAP1_EHT_LINK_ADAPT_MASK 0x30 202 + #define IEEE80211_EHT_MAC_CAP1_UNSOL_EPCS_PRIO_ACCESS 0x40 203 + 204 + /* EHT PHY capabilities as defined in P802.11be_D2.0 section 9.4.2.313.3 */ 205 + #define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 206 + #define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x04 207 + #define IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI 0x08 208 + #define IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO 0x10 209 + #define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER 0x20 210 + #define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE 0x40 211 + 212 + /* EHT beamformee number of spatial streams <= 80MHz is split */ 213 + #define IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK 0x80 214 + #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK 0x03 215 + 216 + #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK 0x1c 217 + #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK 0xe0 218 + 219 + #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK 0x07 220 + #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK 0x38 221 + 222 + /* EHT number of sounding dimensions for 320MHz is split */ 223 + #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK 0xc0 224 + #define IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK 0x01 225 + #define IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK 0x02 226 + #define IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK 0x04 227 + #define IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK 0x08 228 + #define IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK 0x10 229 + #define IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK 0x20 230 + #define IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK 0x40 231 + #define IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK 0x80 232 + 233 + #define IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO 0x01 234 + #define IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP 0x02 235 + #define IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP 0x04 236 + #define IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI 0x08 237 + #define IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK 0xf0 238 + 239 + #define IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK 0x01 240 + #define IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP 0x02 241 + #define IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP 0x04 242 + #define IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT 0x08 243 + #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK 0x30 244 + #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_0US 0 245 + #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US 1 246 + #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US 2 247 + #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_20US 3 248 + 249 + /* Maximum number of supported EHT LTF is split */ 250 + #define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK 0xc0 251 + #define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF 0x40 252 + #define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK 0x07 253 + 254 + #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_80MHZ 0x08 255 + #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_160MHZ 0x30 256 + #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ 0x40 257 + #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK 0x78 258 + #define IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP 0x80 259 + 260 + #define IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW 0x01 261 + #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ 0x02 262 + #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ 0x04 263 + #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ 0x08 264 + #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ 0x10 265 + #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ 0x20 266 + #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ 0x40 267 + #define IEEE80211_EHT_PHY_CAP7_TB_SOUNDING_FDBK_RATE_LIMIT 0x80 268 + 269 + #define IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA 0x01 270 + #define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 271 + 272 + /* 273 + * EHT operation channel width as defined in P802.11be_D2.0 section 9.4.2.311 274 + */ 275 + #define IEEE80211_EHT_OPER_CHAN_WIDTH 0x7 276 + #define IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ 0 277 + #define IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ 1 278 + #define IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ 2 279 + #define IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ 3 280 + #define IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ 4 281 + 282 + /* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */ 283 + static inline u8 284 + ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, 285 + const struct ieee80211_eht_cap_elem_fixed *eht_cap, 286 + bool from_ap) 287 + { 288 + u8 count = 0; 289 + 290 + /* on 2.4 GHz, if it supports 40 MHz, the result is 3 */ 291 + if (he_cap->phy_cap_info[0] & 292 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) 293 + return 3; 294 + 295 + /* on 2.4 GHz, these three bits are reserved, so should be 0 */ 296 + if (he_cap->phy_cap_info[0] & 297 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) 298 + count += 3; 299 + 300 + if (he_cap->phy_cap_info[0] & 301 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) 302 + count += 3; 303 + 304 + if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) 305 + count += 3; 306 + 307 + if (count) 308 + return count; 309 + 310 + return from_ap ? 3 : 4; 311 + } 312 + 313 + /* 802.11be EHT PPE Thresholds */ 314 + #define IEEE80211_EHT_PPE_THRES_NSS_POS 0 315 + #define IEEE80211_EHT_PPE_THRES_NSS_MASK 0xf 316 + #define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK 0x1f0 317 + #define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE 3 318 + #define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE 9 319 + 320 + /* 321 + * Calculate 802.11be EHT capabilities IE EHT field size 322 + */ 323 + static inline u8 324 + ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info) 325 + { 326 + u32 n; 327 + 328 + if (!(phy_cap_info[5] & 329 + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)) 330 + return 0; 331 + 332 + n = hweight16(ppe_thres_hdr & 333 + IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); 334 + n *= 1 + u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_NSS_MASK); 335 + 336 + /* 337 + * Each pair is 6 bits, and we need to add the 9 "header" bits to the 338 + * total size. 339 + */ 340 + n = n * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2 + 341 + IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE; 342 + return DIV_ROUND_UP(n, 8); 343 + } 344 + 345 + static inline bool 346 + ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len, 347 + bool from_ap) 348 + { 349 + const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data; 350 + u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed); 351 + 352 + if (len < needed || !he_capa) 353 + return false; 354 + 355 + needed += ieee80211_eht_mcs_nss_size((const void *)he_capa, 356 + (const void *)data, 357 + from_ap); 358 + if (len < needed) 359 + return false; 360 + 361 + if (elem->phy_cap_info[5] & 362 + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) { 363 + u16 ppe_thres_hdr; 364 + 365 + if (len < needed + sizeof(ppe_thres_hdr)) 366 + return false; 367 + 368 + ppe_thres_hdr = get_unaligned_le16(data + needed); 369 + needed += ieee80211_eht_ppe_size(ppe_thres_hdr, 370 + elem->phy_cap_info); 371 + } 372 + 373 + return len >= needed; 374 + } 375 + 376 + static inline bool 377 + ieee80211_eht_oper_size_ok(const u8 *data, u8 len) 378 + { 379 + const struct ieee80211_eht_operation *elem = (const void *)data; 380 + u8 needed = sizeof(*elem); 381 + 382 + if (len < needed) 383 + return false; 384 + 385 + if (elem->params & IEEE80211_EHT_OPER_INFO_PRESENT) { 386 + needed += 3; 387 + 388 + if (elem->params & 389 + IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT) 390 + needed += 2; 391 + } 392 + 393 + return len >= needed; 394 + } 395 + 396 + /* must validate ieee80211_eht_oper_size_ok() first */ 397 + static inline u16 398 + ieee80211_eht_oper_dis_subchan_bitmap(const struct ieee80211_eht_operation *eht_oper) 399 + { 400 + const struct ieee80211_eht_operation_info *info = 401 + (const void *)eht_oper->optional; 402 + 403 + if (!(eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) 404 + return 0; 405 + 406 + if (!(eht_oper->params & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) 407 + return 0; 408 + 409 + return get_unaligned_le16(info->optional); 410 + } 411 + 412 + #define IEEE80211_BW_IND_DIS_SUBCH_PRESENT BIT(1) 413 + 414 + struct ieee80211_bandwidth_indication { 415 + u8 params; 416 + struct ieee80211_eht_operation_info info; 417 + } __packed; 418 + 419 + static inline bool 420 + ieee80211_bandwidth_indication_size_ok(const u8 *data, u8 len) 421 + { 422 + const struct ieee80211_bandwidth_indication *bwi = (const void *)data; 423 + 424 + if (len < sizeof(*bwi)) 425 + return false; 426 + 427 + if (bwi->params & IEEE80211_BW_IND_DIS_SUBCH_PRESENT && 428 + len < sizeof(*bwi) + 2) 429 + return false; 430 + 431 + return true; 432 + } 433 + 434 + /* Protected EHT action codes */ 435 + enum ieee80211_protected_eht_actioncode { 436 + WLAN_PROTECTED_EHT_ACTION_TTLM_REQ = 0, 437 + WLAN_PROTECTED_EHT_ACTION_TTLM_RES = 1, 438 + WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN = 2, 439 + WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_REQ = 3, 440 + WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_RESP = 4, 441 + WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_TEARDOWN = 5, 442 + WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF = 6, 443 + WLAN_PROTECTED_EHT_ACTION_LINK_RECOMMEND = 7, 444 + WLAN_PROTECTED_EHT_ACTION_ML_OP_UPDATE_REQ = 8, 445 + WLAN_PROTECTED_EHT_ACTION_ML_OP_UPDATE_RESP = 9, 446 + WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_NOTIF = 10, 447 + WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_REQ = 11, 448 + WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_RESP = 12, 449 + }; 450 + 451 + /* multi-link device */ 452 + #define IEEE80211_MLD_MAX_NUM_LINKS 15 453 + 454 + #define IEEE80211_ML_CONTROL_TYPE 0x0007 455 + #define IEEE80211_ML_CONTROL_TYPE_BASIC 0 456 + #define IEEE80211_ML_CONTROL_TYPE_PREQ 1 457 + #define IEEE80211_ML_CONTROL_TYPE_RECONF 2 458 + #define IEEE80211_ML_CONTROL_TYPE_TDLS 3 459 + #define IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS 4 460 + #define IEEE80211_ML_CONTROL_PRESENCE_MASK 0xfff0 461 + 462 + struct ieee80211_multi_link_elem { 463 + __le16 control; 464 + u8 variable[]; 465 + } __packed; 466 + 467 + #define IEEE80211_MLC_BASIC_PRES_LINK_ID 0x0010 468 + #define IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT 0x0020 469 + #define IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY 0x0040 470 + #define IEEE80211_MLC_BASIC_PRES_EML_CAPA 0x0080 471 + #define IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP 0x0100 472 + #define IEEE80211_MLC_BASIC_PRES_MLD_ID 0x0200 473 + #define IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP 0x0400 474 + 475 + #define IEEE80211_MED_SYNC_DELAY_DURATION 0x00ff 476 + #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH 0x0f00 477 + #define IEEE80211_MED_SYNC_DELAY_SYNC_MAX_NUM_TXOPS 0xf000 478 + 479 + /* 480 + * Described in P802.11be_D3.0 481 + * dot11MSDTimerDuration should default to 5484 (i.e. 171.375) 482 + * dot11MSDOFDMEDthreshold defaults to -72 (i.e. 0) 483 + * dot11MSDTXOPMAX defaults to 1 484 + */ 485 + #define IEEE80211_MED_SYNC_DELAY_DEFAULT 0x10ac 486 + 487 + #define IEEE80211_EML_CAP_EMLSR_SUPP 0x0001 488 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY 0x000e 489 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_0US 0 490 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US 1 491 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_64US 2 492 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_128US 3 493 + #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US 4 494 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY 0x0070 495 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_0US 0 496 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_16US 1 497 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_32US 2 498 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US 3 499 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_128US 4 500 + #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US 5 501 + #define IEEE80211_EML_CAP_EMLMR_SUPPORT 0x0080 502 + #define IEEE80211_EML_CAP_EMLMR_DELAY 0x0700 503 + #define IEEE80211_EML_CAP_EMLMR_DELAY_0US 0 504 + #define IEEE80211_EML_CAP_EMLMR_DELAY_32US 1 505 + #define IEEE80211_EML_CAP_EMLMR_DELAY_64US 2 506 + #define IEEE80211_EML_CAP_EMLMR_DELAY_128US 3 507 + #define IEEE80211_EML_CAP_EMLMR_DELAY_256US 4 508 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT 0x7800 509 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_0 0 510 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128US 1 511 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_256US 2 512 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_512US 3 513 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_1TU 4 514 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_2TU 5 515 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_4TU 6 516 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_8TU 7 517 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_16TU 8 518 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_32TU 9 519 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_64TU 10 520 + #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU 11 521 + 522 + #define IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS 0x000f 523 + #define IEEE80211_MLD_CAP_OP_SRS_SUPPORT 0x0010 524 + #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP 0x0060 525 + #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_NO_SUPP 0 526 + #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME 1 527 + #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_RESERVED 2 528 + #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_DIFF 3 529 + #define IEEE80211_MLD_CAP_OP_FREQ_SEP_TYPE_IND 0x0f80 530 + #define IEEE80211_MLD_CAP_OP_AAR_SUPPORT 0x1000 531 + #define IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT 0x2000 532 + #define IEEE80211_MLD_CAP_OP_ALIGNED_TWT_SUPPORT 0x4000 533 + 534 + struct ieee80211_mle_basic_common_info { 535 + u8 len; 536 + u8 mld_mac_addr[ETH_ALEN]; 537 + u8 variable[]; 538 + } __packed; 539 + 540 + #define IEEE80211_MLC_PREQ_PRES_MLD_ID 0x0010 541 + 542 + struct ieee80211_mle_preq_common_info { 543 + u8 len; 544 + u8 variable[]; 545 + } __packed; 546 + 547 + #define IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR 0x0010 548 + #define IEEE80211_MLC_RECONF_PRES_EML_CAPA 0x0020 549 + #define IEEE80211_MLC_RECONF_PRES_MLD_CAPA_OP 0x0040 550 + #define IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP 0x0080 551 + 552 + /* no fixed fields in RECONF */ 553 + 554 + struct ieee80211_mle_tdls_common_info { 555 + u8 len; 556 + u8 ap_mld_mac_addr[ETH_ALEN]; 557 + } __packed; 558 + 559 + #define IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR 0x0010 560 + 561 + /* no fixed fields in PRIO_ACCESS */ 562 + 563 + /** 564 + * ieee80211_mle_common_size - check multi-link element common size 565 + * @data: multi-link element, must already be checked for size using 566 + * ieee80211_mle_size_ok() 567 + * Return: the size of the multi-link element's "common" subfield 568 + */ 569 + static inline u8 ieee80211_mle_common_size(const u8 *data) 570 + { 571 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 572 + u16 control = le16_to_cpu(mle->control); 573 + 574 + switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) { 575 + case IEEE80211_ML_CONTROL_TYPE_BASIC: 576 + case IEEE80211_ML_CONTROL_TYPE_PREQ: 577 + case IEEE80211_ML_CONTROL_TYPE_TDLS: 578 + case IEEE80211_ML_CONTROL_TYPE_RECONF: 579 + case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS: 580 + /* 581 + * The length is the first octet pointed by mle->variable so no 582 + * need to add anything 583 + */ 584 + break; 585 + default: 586 + WARN_ON(1); 587 + return 0; 588 + } 589 + 590 + return sizeof(*mle) + mle->variable[0]; 591 + } 592 + 593 + /** 594 + * ieee80211_mle_get_link_id - returns the link ID 595 + * @data: the basic multi link element 596 + * Return: the link ID, or -1 if not present 597 + * 598 + * The element is assumed to be of the correct type (BASIC) and big enough, 599 + * this must be checked using ieee80211_mle_type_ok(). 600 + */ 601 + static inline int ieee80211_mle_get_link_id(const u8 *data) 602 + { 603 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 604 + u16 control = le16_to_cpu(mle->control); 605 + const u8 *common = mle->variable; 606 + 607 + /* common points now at the beginning of ieee80211_mle_basic_common_info */ 608 + common += sizeof(struct ieee80211_mle_basic_common_info); 609 + 610 + if (!(control & IEEE80211_MLC_BASIC_PRES_LINK_ID)) 611 + return -1; 612 + 613 + return *common; 614 + } 615 + 616 + /** 617 + * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count 618 + * @data: pointer to the basic multi link element 619 + * Return: the BSS Parameter Change Count field value, or -1 if not present 620 + * 621 + * The element is assumed to be of the correct type (BASIC) and big enough, 622 + * this must be checked using ieee80211_mle_type_ok(). 623 + */ 624 + static inline int 625 + ieee80211_mle_get_bss_param_ch_cnt(const u8 *data) 626 + { 627 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 628 + u16 control = le16_to_cpu(mle->control); 629 + const u8 *common = mle->variable; 630 + 631 + /* common points now at the beginning of ieee80211_mle_basic_common_info */ 632 + common += sizeof(struct ieee80211_mle_basic_common_info); 633 + 634 + if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)) 635 + return -1; 636 + 637 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 638 + common += 1; 639 + 640 + return *common; 641 + } 642 + 643 + /** 644 + * ieee80211_mle_get_eml_med_sync_delay - returns the medium sync delay 645 + * @data: pointer to the multi-link element 646 + * Return: the medium synchronization delay field value from the multi-link 647 + * element, or the default value (%IEEE80211_MED_SYNC_DELAY_DEFAULT) 648 + * if not present 649 + * 650 + * The element is assumed to be of the correct type (BASIC) and big enough, 651 + * this must be checked using ieee80211_mle_type_ok(). 652 + */ 653 + static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data) 654 + { 655 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 656 + u16 control = le16_to_cpu(mle->control); 657 + const u8 *common = mle->variable; 658 + 659 + /* common points now at the beginning of ieee80211_mle_basic_common_info */ 660 + common += sizeof(struct ieee80211_mle_basic_common_info); 661 + 662 + if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)) 663 + return IEEE80211_MED_SYNC_DELAY_DEFAULT; 664 + 665 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 666 + common += 1; 667 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 668 + common += 1; 669 + 670 + return get_unaligned_le16(common); 671 + } 672 + 673 + /** 674 + * ieee80211_mle_get_eml_cap - returns the EML capability 675 + * @data: pointer to the multi-link element 676 + * Return: the EML capability field value from the multi-link element, 677 + * or 0 if not present 678 + * 679 + * The element is assumed to be of the correct type (BASIC) and big enough, 680 + * this must be checked using ieee80211_mle_type_ok(). 681 + */ 682 + static inline u16 ieee80211_mle_get_eml_cap(const u8 *data) 683 + { 684 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 685 + u16 control = le16_to_cpu(mle->control); 686 + const u8 *common = mle->variable; 687 + 688 + /* common points now at the beginning of ieee80211_mle_basic_common_info */ 689 + common += sizeof(struct ieee80211_mle_basic_common_info); 690 + 691 + if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA)) 692 + return 0; 693 + 694 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 695 + common += 1; 696 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 697 + common += 1; 698 + if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 699 + common += 2; 700 + 701 + return get_unaligned_le16(common); 702 + } 703 + 704 + /** 705 + * ieee80211_mle_get_mld_capa_op - returns the MLD capabilities and operations. 706 + * @data: pointer to the multi-link element 707 + * Return: the MLD capabilities and operations field value from the multi-link 708 + * element, or 0 if not present 709 + * 710 + * The element is assumed to be of the correct type (BASIC) and big enough, 711 + * this must be checked using ieee80211_mle_type_ok(). 712 + */ 713 + static inline u16 ieee80211_mle_get_mld_capa_op(const u8 *data) 714 + { 715 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 716 + u16 control = le16_to_cpu(mle->control); 717 + const u8 *common = mle->variable; 718 + 719 + /* 720 + * common points now at the beginning of 721 + * ieee80211_mle_basic_common_info 722 + */ 723 + common += sizeof(struct ieee80211_mle_basic_common_info); 724 + 725 + if (!(control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP)) 726 + return 0; 727 + 728 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 729 + common += 1; 730 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 731 + common += 1; 732 + if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 733 + common += 2; 734 + if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 735 + common += 2; 736 + 737 + return get_unaligned_le16(common); 738 + } 739 + 740 + /* Defined in Figure 9-1074t in P802.11be_D7.0 */ 741 + #define IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE 0x0001 742 + #define IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_RECO_MAX_LINKS_MASK 0x001e 743 + #define IEEE80211_EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE 0x0020 744 + #define IEEE80211_EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ON_ONE_LINK 0x0040 745 + #define IEEE80211_EHT_ML_EXT_MLD_CAPA_BTM_MLD_RECO_MULTI_AP 0x0080 746 + 747 + /** 748 + * ieee80211_mle_get_ext_mld_capa_op - returns the extended MLD capabilities 749 + * and operations. 750 + * @data: pointer to the multi-link element 751 + * Return: the extended MLD capabilities and operations field value from 752 + * the multi-link element, or 0 if not present 753 + * 754 + * The element is assumed to be of the correct type (BASIC) and big enough, 755 + * this must be checked using ieee80211_mle_type_ok(). 756 + */ 757 + static inline u16 ieee80211_mle_get_ext_mld_capa_op(const u8 *data) 758 + { 759 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 760 + u16 control = le16_to_cpu(mle->control); 761 + const u8 *common = mle->variable; 762 + 763 + /* 764 + * common points now at the beginning of 765 + * ieee80211_mle_basic_common_info 766 + */ 767 + common += sizeof(struct ieee80211_mle_basic_common_info); 768 + 769 + if (!(control & IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP)) 770 + return 0; 771 + 772 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 773 + common += 1; 774 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 775 + common += 1; 776 + if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 777 + common += 2; 778 + if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 779 + common += 2; 780 + if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 781 + common += 2; 782 + if (control & IEEE80211_MLC_BASIC_PRES_MLD_ID) 783 + common += 1; 784 + 785 + return get_unaligned_le16(common); 786 + } 787 + 788 + /** 789 + * ieee80211_mle_get_mld_id - returns the MLD ID 790 + * @data: pointer to the multi-link element 791 + * Return: The MLD ID in the given multi-link element, or 0 if not present 792 + * 793 + * The element is assumed to be of the correct type (BASIC) and big enough, 794 + * this must be checked using ieee80211_mle_type_ok(). 795 + */ 796 + static inline u8 ieee80211_mle_get_mld_id(const u8 *data) 797 + { 798 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 799 + u16 control = le16_to_cpu(mle->control); 800 + const u8 *common = mle->variable; 801 + 802 + /* 803 + * common points now at the beginning of 804 + * ieee80211_mle_basic_common_info 805 + */ 806 + common += sizeof(struct ieee80211_mle_basic_common_info); 807 + 808 + if (!(control & IEEE80211_MLC_BASIC_PRES_MLD_ID)) 809 + return 0; 810 + 811 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 812 + common += 1; 813 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 814 + common += 1; 815 + if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 816 + common += 2; 817 + if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 818 + common += 2; 819 + if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 820 + common += 2; 821 + 822 + return *common; 823 + } 824 + 825 + /** 826 + * ieee80211_mle_size_ok - validate multi-link element size 827 + * @data: pointer to the element data 828 + * @len: length of the containing element 829 + * Return: whether or not the multi-link element size is OK 830 + */ 831 + static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len) 832 + { 833 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 834 + u8 fixed = sizeof(*mle); 835 + u8 common = 0; 836 + bool check_common_len = false; 837 + u16 control; 838 + 839 + if (!data || len < fixed) 840 + return false; 841 + 842 + control = le16_to_cpu(mle->control); 843 + 844 + switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) { 845 + case IEEE80211_ML_CONTROL_TYPE_BASIC: 846 + common += sizeof(struct ieee80211_mle_basic_common_info); 847 + check_common_len = true; 848 + if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 849 + common += 1; 850 + if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 851 + common += 1; 852 + if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 853 + common += 2; 854 + if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 855 + common += 2; 856 + if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 857 + common += 2; 858 + if (control & IEEE80211_MLC_BASIC_PRES_MLD_ID) 859 + common += 1; 860 + if (control & IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP) 861 + common += 2; 862 + break; 863 + case IEEE80211_ML_CONTROL_TYPE_PREQ: 864 + common += sizeof(struct ieee80211_mle_preq_common_info); 865 + if (control & IEEE80211_MLC_PREQ_PRES_MLD_ID) 866 + common += 1; 867 + check_common_len = true; 868 + break; 869 + case IEEE80211_ML_CONTROL_TYPE_RECONF: 870 + if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR) 871 + common += ETH_ALEN; 872 + if (control & IEEE80211_MLC_RECONF_PRES_EML_CAPA) 873 + common += 2; 874 + if (control & IEEE80211_MLC_RECONF_PRES_MLD_CAPA_OP) 875 + common += 2; 876 + if (control & IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP) 877 + common += 2; 878 + break; 879 + case IEEE80211_ML_CONTROL_TYPE_TDLS: 880 + common += sizeof(struct ieee80211_mle_tdls_common_info); 881 + check_common_len = true; 882 + break; 883 + case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS: 884 + common = ETH_ALEN + 1; 885 + break; 886 + default: 887 + /* we don't know this type */ 888 + return true; 889 + } 890 + 891 + if (len < fixed + common) 892 + return false; 893 + 894 + if (!check_common_len) 895 + return true; 896 + 897 + /* if present, common length is the first octet there */ 898 + return mle->variable[0] >= common; 899 + } 900 + 901 + /** 902 + * ieee80211_mle_type_ok - validate multi-link element type and size 903 + * @data: pointer to the element data 904 + * @type: expected type of the element 905 + * @len: length of the containing element 906 + * Return: whether or not the multi-link element type matches and size is OK 907 + */ 908 + static inline bool ieee80211_mle_type_ok(const u8 *data, u8 type, size_t len) 909 + { 910 + const struct ieee80211_multi_link_elem *mle = (const void *)data; 911 + u16 control; 912 + 913 + if (!ieee80211_mle_size_ok(data, len)) 914 + return false; 915 + 916 + control = le16_to_cpu(mle->control); 917 + 918 + if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) == type) 919 + return true; 920 + 921 + return false; 922 + } 923 + 924 + enum ieee80211_mle_subelems { 925 + IEEE80211_MLE_SUBELEM_PER_STA_PROFILE = 0, 926 + IEEE80211_MLE_SUBELEM_FRAGMENT = 254, 927 + }; 928 + 929 + #define IEEE80211_MLE_STA_CONTROL_LINK_ID 0x000f 930 + #define IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE 0x0010 931 + #define IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT 0x0020 932 + #define IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT 0x0040 933 + #define IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT 0x0080 934 + #define IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT 0x0100 935 + #define IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT 0x0200 936 + #define IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE 0x0400 937 + #define IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT 0x0800 938 + 939 + struct ieee80211_mle_per_sta_profile { 940 + __le16 control; 941 + u8 sta_info_len; 942 + u8 variable[]; 943 + } __packed; 944 + 945 + /** 946 + * ieee80211_mle_basic_sta_prof_size_ok - validate basic multi-link element sta 947 + * profile size 948 + * @data: pointer to the sub element data 949 + * @len: length of the containing sub element 950 + * Return: %true if the STA profile is large enough, %false otherwise 951 + */ 952 + static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data, 953 + size_t len) 954 + { 955 + const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; 956 + u16 control; 957 + u8 fixed = sizeof(*prof); 958 + u8 info_len = 1; 959 + 960 + if (len < fixed) 961 + return false; 962 + 963 + control = le16_to_cpu(prof->control); 964 + 965 + if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) 966 + info_len += 6; 967 + if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) 968 + info_len += 2; 969 + if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) 970 + info_len += 8; 971 + if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) 972 + info_len += 2; 973 + if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && 974 + control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) { 975 + if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) 976 + info_len += 2; 977 + else 978 + info_len += 1; 979 + } 980 + if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT) 981 + info_len += 1; 982 + 983 + return prof->sta_info_len >= info_len && 984 + fixed + prof->sta_info_len - 1 <= len; 985 + } 986 + 987 + /** 988 + * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS 989 + * parameter change count 990 + * @prof: the per-STA profile, having been checked with 991 + * ieee80211_mle_basic_sta_prof_size_ok() for the correct length 992 + * 993 + * Return: The BSS parameter change count value if present, 0 otherwise. 994 + */ 995 + static inline u8 996 + ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof) 997 + { 998 + u16 control = le16_to_cpu(prof->control); 999 + const u8 *pos = prof->variable; 1000 + 1001 + if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)) 1002 + return 0; 1003 + 1004 + if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) 1005 + pos += 6; 1006 + if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) 1007 + pos += 2; 1008 + if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) 1009 + pos += 8; 1010 + if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) 1011 + pos += 2; 1012 + if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && 1013 + control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) { 1014 + if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) 1015 + pos += 2; 1016 + else 1017 + pos += 1; 1018 + } 1019 + 1020 + return *pos; 1021 + } 1022 + 1023 + #define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID 0x000f 1024 + #define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE 0x0010 1025 + #define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT 0x0020 1026 + #define IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT 0x0040 1027 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE 0x0780 1028 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_AP_REM 0 1029 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_OP_PARAM_UPDATE 1 1030 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_ADD_LINK 2 1031 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_DEL_LINK 3 1032 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_NSTR_STATUS 4 1033 + #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT 0x0800 1034 + 1035 + /** 1036 + * ieee80211_mle_reconf_sta_prof_size_ok - validate reconfiguration multi-link 1037 + * element sta profile size. 1038 + * @data: pointer to the sub element data 1039 + * @len: length of the containing sub element 1040 + * Return: %true if the STA profile is large enough, %false otherwise 1041 + */ 1042 + static inline bool ieee80211_mle_reconf_sta_prof_size_ok(const u8 *data, 1043 + size_t len) 1044 + { 1045 + const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; 1046 + u16 control; 1047 + u8 fixed = sizeof(*prof); 1048 + u8 info_len = 1; 1049 + 1050 + if (len < fixed) 1051 + return false; 1052 + 1053 + control = le16_to_cpu(prof->control); 1054 + 1055 + if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT) 1056 + info_len += ETH_ALEN; 1057 + if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT) 1058 + info_len += 2; 1059 + if (control & IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT) 1060 + info_len += 2; 1061 + 1062 + return prof->sta_info_len >= info_len && 1063 + fixed + prof->sta_info_len - 1 <= len; 1064 + } 1065 + 1066 + #define IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID 0x000f 1067 + #define IEEE80211_EPCS_ENA_RESP_BODY_LEN 3 1068 + 1069 + static inline bool ieee80211_tid_to_link_map_size_ok(const u8 *data, size_t len) 1070 + { 1071 + const struct ieee80211_ttlm_elem *t2l = (const void *)data; 1072 + u8 control, fixed = sizeof(*t2l), elem_len = 0; 1073 + 1074 + if (len < fixed) 1075 + return false; 1076 + 1077 + control = t2l->control; 1078 + 1079 + if (control & IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT) 1080 + elem_len += 2; 1081 + if (control & IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT) 1082 + elem_len += 3; 1083 + 1084 + if (!(control & IEEE80211_TTLM_CONTROL_DEF_LINK_MAP)) { 1085 + u8 bm_size; 1086 + 1087 + elem_len += 1; 1088 + if (len < fixed + elem_len) 1089 + return false; 1090 + 1091 + if (control & IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE) 1092 + bm_size = 1; 1093 + else 1094 + bm_size = 2; 1095 + 1096 + elem_len += hweight8(t2l->optional[0]) * bm_size; 1097 + } 1098 + 1099 + return len >= fixed + elem_len; 1100 + } 1101 + 1102 + /** 1103 + * ieee80211_emlsr_pad_delay_in_us - Fetch the EMLSR Padding delay 1104 + * in microseconds 1105 + * @eml_cap: EML capabilities field value from common info field of 1106 + * the Multi-link element 1107 + * Return: the EMLSR Padding delay (in microseconds) encoded in the 1108 + * EML Capabilities field 1109 + */ 1110 + 1111 + static inline u32 ieee80211_emlsr_pad_delay_in_us(u16 eml_cap) 1112 + { 1113 + /* IEEE Std 802.11be-2024 Table 9-417i—Encoding of the EMLSR 1114 + * Padding Delay subfield. 1115 + */ 1116 + u32 pad_delay = u16_get_bits(eml_cap, 1117 + IEEE80211_EML_CAP_EMLSR_PADDING_DELAY); 1118 + 1119 + if (!pad_delay || 1120 + pad_delay > IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US) 1121 + return 0; 1122 + 1123 + return 32 * (1 << (pad_delay - 1)); 1124 + } 1125 + 1126 + /** 1127 + * ieee80211_emlsr_trans_delay_in_us - Fetch the EMLSR Transition 1128 + * delay in microseconds 1129 + * @eml_cap: EML capabilities field value from common info field of 1130 + * the Multi-link element 1131 + * Return: the EMLSR Transition delay (in microseconds) encoded in the 1132 + * EML Capabilities field 1133 + */ 1134 + 1135 + static inline u32 ieee80211_emlsr_trans_delay_in_us(u16 eml_cap) 1136 + { 1137 + /* IEEE Std 802.11be-2024 Table 9-417j—Encoding of the EMLSR 1138 + * Transition Delay subfield. 1139 + */ 1140 + u32 trans_delay = 1141 + u16_get_bits(eml_cap, 1142 + IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY); 1143 + 1144 + /* invalid values also just use 0 */ 1145 + if (!trans_delay || 1146 + trans_delay > IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US) 1147 + return 0; 1148 + 1149 + return 16 * (1 << (trans_delay - 1)); 1150 + } 1151 + 1152 + /** 1153 + * ieee80211_eml_trans_timeout_in_us - Fetch the EMLSR Transition 1154 + * timeout value in microseconds 1155 + * @eml_cap: EML capabilities field value from common info field of 1156 + * the Multi-link element 1157 + * Return: the EMLSR Transition timeout (in microseconds) encoded in 1158 + * the EML Capabilities field 1159 + */ 1160 + 1161 + static inline u32 ieee80211_eml_trans_timeout_in_us(u16 eml_cap) 1162 + { 1163 + /* IEEE Std 802.11be-2024 Table 9-417m—Encoding of the 1164 + * Transition Timeout subfield. 1165 + */ 1166 + u8 timeout = u16_get_bits(eml_cap, 1167 + IEEE80211_EML_CAP_TRANSITION_TIMEOUT); 1168 + 1169 + /* invalid values also just use 0 */ 1170 + if (!timeout || timeout > IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU) 1171 + return 0; 1172 + 1173 + return 128 * (1 << (timeout - 1)); 1174 + } 1175 + 1176 + #define for_each_mle_subelement(_elem, _data, _len) \ 1177 + if (ieee80211_mle_size_ok(_data, _len)) \ 1178 + for_each_element(_elem, \ 1179 + _data + ieee80211_mle_common_size(_data),\ 1180 + _len - ieee80211_mle_common_size(_data)) 1181 + 1182 + #endif /* LINUX_IEEE80211_H */
+824
include/linux/ieee80211-he.h
··· 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 IEEE80211_HE_PPE_THRES_INFO_HEADER_SIZE (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_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(data[needed], 526 + 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_INDOOR_SP_AP 8 552 + 553 + /** 554 + * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field 555 + * @primary: primary channel 556 + * @control: control flags 557 + * @ccfs0: channel center frequency segment 0 558 + * @ccfs1: channel center frequency segment 1 559 + * @minrate: minimum rate (in 1 Mbps units) 560 + */ 561 + struct ieee80211_he_6ghz_oper { 562 + u8 primary; 563 + #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH 0x3 564 + #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ 0 565 + #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ 1 566 + #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ 2 567 + #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3 568 + #define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4 569 + #define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x78 570 + u8 control; 571 + u8 ccfs0; 572 + u8 ccfs1; 573 + u8 minrate; 574 + } __packed; 575 + 576 + /** 577 + * enum ieee80211_reg_conn_bits - represents Regulatory connectivity field bits. 578 + * 579 + * This enumeration defines bit flags used to represent regulatory connectivity 580 + * field bits. 581 + * 582 + * @IEEE80211_REG_CONN_LPI_VALID: Indicates whether the LPI bit is valid. 583 + * @IEEE80211_REG_CONN_LPI_VALUE: Represents the value of the LPI bit. 584 + * @IEEE80211_REG_CONN_SP_VALID: Indicates whether the SP bit is valid. 585 + * @IEEE80211_REG_CONN_SP_VALUE: Represents the value of the SP bit. 586 + */ 587 + enum ieee80211_reg_conn_bits { 588 + IEEE80211_REG_CONN_LPI_VALID = BIT(0), 589 + IEEE80211_REG_CONN_LPI_VALUE = BIT(1), 590 + IEEE80211_REG_CONN_SP_VALID = BIT(2), 591 + IEEE80211_REG_CONN_SP_VALUE = BIT(3), 592 + }; 593 + 594 + /* transmit power interpretation type of transmit power envelope element */ 595 + enum ieee80211_tx_power_intrpt_type { 596 + IEEE80211_TPE_LOCAL_EIRP, 597 + IEEE80211_TPE_LOCAL_EIRP_PSD, 598 + IEEE80211_TPE_REG_CLIENT_EIRP, 599 + IEEE80211_TPE_REG_CLIENT_EIRP_PSD, 600 + }; 601 + 602 + /* category type of transmit power envelope element */ 603 + enum ieee80211_tx_power_category_6ghz { 604 + IEEE80211_TPE_CAT_6GHZ_DEFAULT = 0, 605 + IEEE80211_TPE_CAT_6GHZ_SUBORDINATE = 1, 606 + }; 607 + 608 + /* 609 + * For IEEE80211_TPE_LOCAL_EIRP / IEEE80211_TPE_REG_CLIENT_EIRP, 610 + * setting to 63.5 dBm means no constraint. 611 + */ 612 + #define IEEE80211_TPE_MAX_TX_PWR_NO_CONSTRAINT 127 613 + 614 + /* 615 + * For IEEE80211_TPE_LOCAL_EIRP_PSD / IEEE80211_TPE_REG_CLIENT_EIRP_PSD, 616 + * setting to 127 indicates no PSD limit for the 20 MHz channel. 617 + */ 618 + #define IEEE80211_TPE_PSD_NO_LIMIT 127 619 + 620 + /** 621 + * struct ieee80211_tx_pwr_env - Transmit Power Envelope 622 + * @info: Transmit Power Information field 623 + * @variable: Maximum Transmit Power field 624 + * 625 + * This structure represents the payload of the "Transmit Power 626 + * Envelope element" as described in IEEE Std 802.11ax-2021 section 627 + * 9.4.2.161 628 + */ 629 + struct ieee80211_tx_pwr_env { 630 + u8 info; 631 + u8 variable[]; 632 + } __packed; 633 + 634 + #define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7 635 + #define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 636 + #define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0 637 + 638 + #define IEEE80211_TX_PWR_ENV_EXT_COUNT 0xF 639 + 640 + static inline bool ieee80211_valid_tpe_element(const u8 *data, u8 len) 641 + { 642 + const struct ieee80211_tx_pwr_env *env = (const void *)data; 643 + u8 count, interpret, category; 644 + u8 needed = sizeof(*env); 645 + u8 N; /* also called N in the spec */ 646 + 647 + if (len < needed) 648 + return false; 649 + 650 + count = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_COUNT); 651 + interpret = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_INTERPRET); 652 + category = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_CATEGORY); 653 + 654 + switch (category) { 655 + case IEEE80211_TPE_CAT_6GHZ_DEFAULT: 656 + case IEEE80211_TPE_CAT_6GHZ_SUBORDINATE: 657 + break; 658 + default: 659 + return false; 660 + } 661 + 662 + switch (interpret) { 663 + case IEEE80211_TPE_LOCAL_EIRP: 664 + case IEEE80211_TPE_REG_CLIENT_EIRP: 665 + if (count > 3) 666 + return false; 667 + 668 + /* count == 0 encodes 1 value for 20 MHz, etc. */ 669 + needed += count + 1; 670 + 671 + if (len < needed) 672 + return false; 673 + 674 + /* there can be extension fields not accounted for in 'count' */ 675 + 676 + return true; 677 + case IEEE80211_TPE_LOCAL_EIRP_PSD: 678 + case IEEE80211_TPE_REG_CLIENT_EIRP_PSD: 679 + if (count > 4) 680 + return false; 681 + 682 + N = count ? 1 << (count - 1) : 1; 683 + needed += N; 684 + 685 + if (len < needed) 686 + return false; 687 + 688 + if (len > needed) { 689 + u8 K = u8_get_bits(env->variable[N], 690 + IEEE80211_TX_PWR_ENV_EXT_COUNT); 691 + 692 + needed += 1 + K; 693 + if (len < needed) 694 + return false; 695 + } 696 + 697 + return true; 698 + } 699 + 700 + return false; 701 + } 702 + 703 + /* 704 + * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size 705 + * @he_oper_ie: byte data of the He Operations IE, stating from the byte 706 + * after the ext ID byte. It is assumed that he_oper_ie has at least 707 + * sizeof(struct ieee80211_he_operation) bytes, the caller must have 708 + * validated this. 709 + * @return the actual size of the IE data (not including header), or 0 on error 710 + */ 711 + static inline u8 712 + ieee80211_he_oper_size(const u8 *he_oper_ie) 713 + { 714 + const struct ieee80211_he_operation *he_oper = (const void *)he_oper_ie; 715 + u8 oper_len = sizeof(struct ieee80211_he_operation); 716 + u32 he_oper_params; 717 + 718 + /* Make sure the input is not NULL */ 719 + if (!he_oper_ie) 720 + return 0; 721 + 722 + /* Calc required length */ 723 + he_oper_params = le32_to_cpu(he_oper->he_oper_params); 724 + if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) 725 + oper_len += 3; 726 + if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) 727 + oper_len++; 728 + if (he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO) 729 + oper_len += sizeof(struct ieee80211_he_6ghz_oper); 730 + 731 + /* Add the first byte (extension ID) to the total length */ 732 + oper_len++; 733 + 734 + return oper_len; 735 + } 736 + 737 + /** 738 + * ieee80211_he_6ghz_oper - obtain 6 GHz operation field 739 + * @he_oper: HE operation element (must be pre-validated for size) 740 + * but may be %NULL 741 + * 742 + * Return: a pointer to the 6 GHz operation field, or %NULL 743 + */ 744 + static inline const struct ieee80211_he_6ghz_oper * 745 + ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper) 746 + { 747 + const u8 *ret; 748 + u32 he_oper_params; 749 + 750 + if (!he_oper) 751 + return NULL; 752 + 753 + ret = (const void *)&he_oper->optional; 754 + 755 + he_oper_params = le32_to_cpu(he_oper->he_oper_params); 756 + 757 + if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)) 758 + return NULL; 759 + if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) 760 + ret += 3; 761 + if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) 762 + ret++; 763 + 764 + return (const void *)ret; 765 + } 766 + 767 + /* HE Spatial Reuse defines */ 768 + #define IEEE80211_HE_SPR_PSR_DISALLOWED BIT(0) 769 + #define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) 770 + #define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT BIT(2) 771 + #define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT BIT(3) 772 + #define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED BIT(4) 773 + 774 + /* 775 + * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size 776 + * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the byte 777 + * after the ext ID byte. It is assumed that he_spr_ie has at least 778 + * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated 779 + * this 780 + * @return the actual size of the IE data (not including header), or 0 on error 781 + */ 782 + static inline u8 783 + ieee80211_he_spr_size(const u8 *he_spr_ie) 784 + { 785 + const struct ieee80211_he_spr *he_spr = (const void *)he_spr_ie; 786 + u8 spr_len = sizeof(struct ieee80211_he_spr); 787 + u8 he_spr_params; 788 + 789 + /* Make sure the input is not NULL */ 790 + if (!he_spr_ie) 791 + return 0; 792 + 793 + /* Calc required length */ 794 + he_spr_params = he_spr->he_sr_control; 795 + if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) 796 + spr_len++; 797 + if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) 798 + spr_len += 18; 799 + 800 + /* Add the first byte (extension ID) to the total length */ 801 + spr_len++; 802 + 803 + return spr_len; 804 + } 805 + 806 + struct ieee80211_he_6ghz_capa { 807 + /* uses IEEE80211_HE_6GHZ_CAP_* below */ 808 + __le16 capa; 809 + } __packed; 810 + 811 + /* HE 6 GHz band capabilities */ 812 + /* uses enum ieee80211_min_mpdu_spacing values */ 813 + #define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START 0x0007 814 + /* uses enum ieee80211_vht_max_ampdu_length_exp values */ 815 + #define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP 0x0038 816 + /* uses IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_* values */ 817 + #define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN 0x00c0 818 + /* WLAN_HT_CAP_SM_PS_* values */ 819 + #define IEEE80211_HE_6GHZ_CAP_SM_PS 0x0600 820 + #define IEEE80211_HE_6GHZ_CAP_RD_RESPONDER 0x0800 821 + #define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS 0x1000 822 + #define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS 0x2000 823 + 824 + #endif /* LINUX_IEEE80211_HE_H */
+292
include/linux/ieee80211-ht.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * IEEE 802.11 HT 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_HT_H 16 + #define LINUX_IEEE80211_HT_H 17 + 18 + #include <linux/types.h> 19 + #include <linux/if_ether.h> 20 + 21 + /* Maximal size of an A-MSDU that can be transported in a HT BA session */ 22 + #define IEEE80211_MAX_MPDU_LEN_HT_BA 4095 23 + 24 + /* Maximal size of an A-MSDU */ 25 + #define IEEE80211_MAX_MPDU_LEN_HT_3839 3839 26 + #define IEEE80211_MAX_MPDU_LEN_HT_7935 7935 27 + 28 + #define IEEE80211_HT_CTL_LEN 4 29 + 30 + enum ieee80211_ht_chanwidth_values { 31 + IEEE80211_HT_CHANWIDTH_20MHZ = 0, 32 + IEEE80211_HT_CHANWIDTH_ANY = 1, 33 + }; 34 + 35 + /** 36 + * struct ieee80211_bar - Block Ack Request frame format 37 + * @frame_control: Frame Control 38 + * @duration: Duration 39 + * @ra: RA 40 + * @ta: TA 41 + * @control: BAR Control 42 + * @start_seq_num: Starting Sequence Number (see Figure 9-37) 43 + * 44 + * This structure represents the "BlockAckReq frame format" 45 + * as described in IEEE Std 802.11-2020 section 9.3.1.7. 46 + */ 47 + struct ieee80211_bar { 48 + __le16 frame_control; 49 + __le16 duration; 50 + __u8 ra[ETH_ALEN]; 51 + __u8 ta[ETH_ALEN]; 52 + __le16 control; 53 + __le16 start_seq_num; 54 + } __packed; 55 + 56 + /* 802.11 BAR control masks */ 57 + #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 58 + #define IEEE80211_BAR_CTRL_MULTI_TID 0x0002 59 + #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 60 + #define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 61 + #define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 62 + 63 + #define IEEE80211_HT_MCS_MASK_LEN 10 64 + 65 + /** 66 + * struct ieee80211_mcs_info - Supported MCS Set field 67 + * @rx_mask: RX mask 68 + * @rx_highest: highest supported RX rate. If set represents 69 + * the highest supported RX data rate in units of 1 Mbps. 70 + * If this field is 0 this value should not be used to 71 + * consider the highest RX data rate supported. 72 + * @tx_params: TX parameters 73 + * @reserved: Reserved bits 74 + * 75 + * This structure represents the "Supported MCS Set field" as 76 + * described in IEEE Std 802.11-2020 section 9.4.2.55.4. 77 + */ 78 + struct ieee80211_mcs_info { 79 + u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; 80 + __le16 rx_highest; 81 + u8 tx_params; 82 + u8 reserved[3]; 83 + } __packed; 84 + 85 + /* 802.11n HT capability MSC set */ 86 + #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff 87 + #define IEEE80211_HT_MCS_TX_DEFINED 0x01 88 + #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 89 + /* value 0 == 1 stream etc */ 90 + #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C 91 + #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 92 + #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 93 + #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 94 + 95 + #define IEEE80211_HT_MCS_CHAINS(mcs) ((mcs) == 32 ? 1 : (1 + ((mcs) >> 3))) 96 + 97 + /* 98 + * 802.11n D5.0 20.3.5 / 20.6 says: 99 + * - indices 0 to 7 and 32 are single spatial stream 100 + * - 8 to 31 are multiple spatial streams using equal modulation 101 + * [8..15 for two streams, 16..23 for three and 24..31 for four] 102 + * - remainder are multiple spatial streams using unequal modulation 103 + */ 104 + #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 105 + #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ 106 + (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) 107 + 108 + /** 109 + * struct ieee80211_ht_cap - HT capabilities element 110 + * @cap_info: HT Capability Information 111 + * @ampdu_params_info: A-MPDU Parameters 112 + * @mcs: Supported MCS Set 113 + * @extended_ht_cap_info: HT Extended Capabilities 114 + * @tx_BF_cap_info: Transmit Beamforming Capabilities 115 + * @antenna_selection_info: ASEL Capability 116 + * 117 + * This structure represents the payload of the "HT Capabilities 118 + * element" as described in IEEE Std 802.11-2020 section 9.4.2.55. 119 + */ 120 + struct ieee80211_ht_cap { 121 + __le16 cap_info; 122 + u8 ampdu_params_info; 123 + 124 + /* 16 bytes MCS information */ 125 + struct ieee80211_mcs_info mcs; 126 + 127 + __le16 extended_ht_cap_info; 128 + __le32 tx_BF_cap_info; 129 + u8 antenna_selection_info; 130 + } __packed; 131 + 132 + /* 802.11n HT capabilities masks (for cap_info) */ 133 + #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 134 + #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 135 + #define IEEE80211_HT_CAP_SM_PS 0x000C 136 + #define IEEE80211_HT_CAP_SM_PS_SHIFT 2 137 + #define IEEE80211_HT_CAP_GRN_FLD 0x0010 138 + #define IEEE80211_HT_CAP_SGI_20 0x0020 139 + #define IEEE80211_HT_CAP_SGI_40 0x0040 140 + #define IEEE80211_HT_CAP_TX_STBC 0x0080 141 + #define IEEE80211_HT_CAP_RX_STBC 0x0300 142 + #define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 143 + #define IEEE80211_HT_CAP_DELAY_BA 0x0400 144 + #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 145 + #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 146 + #define IEEE80211_HT_CAP_RESERVED 0x2000 147 + #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 148 + #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 149 + 150 + /* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ 151 + #define IEEE80211_HT_EXT_CAP_PCO 0x0001 152 + #define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 153 + #define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 154 + #define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 155 + #define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 156 + #define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 157 + #define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 158 + 159 + /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ 160 + #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 161 + #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C 162 + #define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 163 + 164 + /* 165 + * Maximum length of AMPDU that the STA can receive in high-throughput (HT). 166 + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) 167 + */ 168 + enum ieee80211_max_ampdu_length_exp { 169 + IEEE80211_HT_MAX_AMPDU_8K = 0, 170 + IEEE80211_HT_MAX_AMPDU_16K = 1, 171 + IEEE80211_HT_MAX_AMPDU_32K = 2, 172 + IEEE80211_HT_MAX_AMPDU_64K = 3 173 + }; 174 + 175 + #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 176 + 177 + /* Minimum MPDU start spacing */ 178 + enum ieee80211_min_mpdu_spacing { 179 + IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ 180 + IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ 181 + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ 182 + IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ 183 + IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ 184 + IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ 185 + IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ 186 + IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ 187 + }; 188 + 189 + /** 190 + * struct ieee80211_ht_operation - HT operation IE 191 + * @primary_chan: Primary Channel 192 + * @ht_param: HT Operation Information parameters 193 + * @operation_mode: HT Operation Information operation mode 194 + * @stbc_param: HT Operation Information STBC params 195 + * @basic_set: Basic HT-MCS Set 196 + * 197 + * This structure represents the payload of the "HT Operation 198 + * element" as described in IEEE Std 802.11-2020 section 9.4.2.56. 199 + */ 200 + struct ieee80211_ht_operation { 201 + u8 primary_chan; 202 + u8 ht_param; 203 + __le16 operation_mode; 204 + __le16 stbc_param; 205 + u8 basic_set[16]; 206 + } __packed; 207 + 208 + /* for ht_param */ 209 + #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 210 + #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 211 + #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 212 + #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 213 + #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 214 + #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 215 + 216 + /* for operation_mode */ 217 + #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 218 + #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 219 + #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 220 + #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 221 + #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 222 + #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 223 + #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 224 + #define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5 225 + #define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0 226 + 227 + /* for stbc_param */ 228 + #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 229 + #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 230 + #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 231 + #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 232 + #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 233 + #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 234 + 235 + 236 + /* block-ack parameters */ 237 + #define IEEE80211_ADDBA_PARAM_AMSDU_MASK 0x0001 238 + #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 239 + #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C 240 + #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 241 + #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 242 + #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 243 + 244 + /* 245 + * A-MPDU buffer sizes 246 + * According to HT size varies from 8 to 64 frames 247 + * HE adds the ability to have up to 256 frames. 248 + * EHT adds the ability to have up to 1K frames. 249 + */ 250 + #define IEEE80211_MIN_AMPDU_BUF 0x8 251 + #define IEEE80211_MAX_AMPDU_BUF_HT 0x40 252 + #define IEEE80211_MAX_AMPDU_BUF_HE 0x100 253 + #define IEEE80211_MAX_AMPDU_BUF_EHT 0x400 254 + 255 + 256 + /* Spatial Multiplexing Power Save Modes (for capability) */ 257 + #define WLAN_HT_CAP_SM_PS_STATIC 0 258 + #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 259 + #define WLAN_HT_CAP_SM_PS_INVALID 2 260 + #define WLAN_HT_CAP_SM_PS_DISABLED 3 261 + 262 + /* for SM power control field lower two bits */ 263 + #define WLAN_HT_SMPS_CONTROL_DISABLED 0 264 + #define WLAN_HT_SMPS_CONTROL_STATIC 1 265 + #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 266 + 267 + /* HT action codes */ 268 + enum ieee80211_ht_actioncode { 269 + WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, 270 + WLAN_HT_ACTION_SMPS = 1, 271 + WLAN_HT_ACTION_PSMP = 2, 272 + WLAN_HT_ACTION_PCO_PHASE = 3, 273 + WLAN_HT_ACTION_CSI = 4, 274 + WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, 275 + WLAN_HT_ACTION_COMPRESSED_BF = 6, 276 + WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, 277 + }; 278 + 279 + /* BACK action code */ 280 + enum ieee80211_back_actioncode { 281 + WLAN_ACTION_ADDBA_REQ = 0, 282 + WLAN_ACTION_ADDBA_RESP = 1, 283 + WLAN_ACTION_DELBA = 2, 284 + }; 285 + 286 + /* BACK (block-ack) parties */ 287 + enum ieee80211_back_parties { 288 + WLAN_BACK_RECIPIENT = 0, 289 + WLAN_BACK_INITIATOR = 1, 290 + }; 291 + 292 + #endif /* LINUX_IEEE80211_HT_H */
+230
include/linux/ieee80211-mesh.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * IEEE 802.11 mesh 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_MESH_H 16 + #define LINUX_IEEE80211_MESH_H 17 + 18 + #include <linux/types.h> 19 + #include <linux/if_ether.h> 20 + 21 + #define IEEE80211_MAX_MESH_ID_LEN 32 22 + 23 + struct ieee80211s_hdr { 24 + u8 flags; 25 + u8 ttl; 26 + __le32 seqnum; 27 + u8 eaddr1[ETH_ALEN]; 28 + u8 eaddr2[ETH_ALEN]; 29 + } __packed __aligned(2); 30 + 31 + /* Mesh flags */ 32 + #define MESH_FLAGS_AE_A4 0x1 33 + #define MESH_FLAGS_AE_A5_A6 0x2 34 + #define MESH_FLAGS_AE 0x3 35 + #define MESH_FLAGS_PS_DEEP 0x4 36 + 37 + /** 38 + * enum ieee80211_preq_flags - mesh PREQ element flags 39 + * 40 + * @IEEE80211_PREQ_PROACTIVE_PREP_FLAG: proactive PREP subfield 41 + */ 42 + enum ieee80211_preq_flags { 43 + IEEE80211_PREQ_PROACTIVE_PREP_FLAG = 1<<2, 44 + }; 45 + 46 + /** 47 + * enum ieee80211_preq_target_flags - mesh PREQ element per target flags 48 + * 49 + * @IEEE80211_PREQ_TO_FLAG: target only subfield 50 + * @IEEE80211_PREQ_USN_FLAG: unknown target HWMP sequence number subfield 51 + */ 52 + enum ieee80211_preq_target_flags { 53 + IEEE80211_PREQ_TO_FLAG = 1<<0, 54 + IEEE80211_PREQ_USN_FLAG = 1<<2, 55 + }; 56 + 57 + /** 58 + * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE 59 + * @mesh_ttl: Time To Live 60 + * @mesh_flags: Flags 61 + * @mesh_reason: Reason Code 62 + * @mesh_pre_value: Precedence Value 63 + * 64 + * This structure represents the payload of the "Mesh Channel Switch 65 + * Parameters element" as described in IEEE Std 802.11-2020 section 66 + * 9.4.2.102. 67 + */ 68 + struct ieee80211_mesh_chansw_params_ie { 69 + u8 mesh_ttl; 70 + u8 mesh_flags; 71 + __le16 mesh_reason; 72 + __le16 mesh_pre_value; 73 + } __packed; 74 + 75 + /** 76 + * struct ieee80211_meshconf_ie - Mesh Configuration element 77 + * @meshconf_psel: Active Path Selection Protocol Identifier 78 + * @meshconf_pmetric: Active Path Selection Metric Identifier 79 + * @meshconf_congest: Congestion Control Mode Identifier 80 + * @meshconf_synch: Synchronization Method Identifier 81 + * @meshconf_auth: Authentication Protocol Identifier 82 + * @meshconf_form: Mesh Formation Info 83 + * @meshconf_cap: Mesh Capability (see &enum mesh_config_capab_flags) 84 + * 85 + * This structure represents the payload of the "Mesh Configuration 86 + * element" as described in IEEE Std 802.11-2020 section 9.4.2.97. 87 + */ 88 + struct ieee80211_meshconf_ie { 89 + u8 meshconf_psel; 90 + u8 meshconf_pmetric; 91 + u8 meshconf_congest; 92 + u8 meshconf_synch; 93 + u8 meshconf_auth; 94 + u8 meshconf_form; 95 + u8 meshconf_cap; 96 + } __packed; 97 + 98 + /** 99 + * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags 100 + * 101 + * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish 102 + * additional mesh peerings with other mesh STAs 103 + * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs 104 + * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure 105 + * is ongoing 106 + * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has 107 + * neighbors in deep sleep mode 108 + * 109 + * Enumerates the "Mesh Capability" as described in IEEE Std 110 + * 802.11-2020 section 9.4.2.97.7. 111 + */ 112 + enum mesh_config_capab_flags { 113 + IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01, 114 + IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08, 115 + IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20, 116 + IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40, 117 + }; 118 + 119 + #define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1 120 + 121 + /* 122 + * mesh channel switch parameters element's flag indicator 123 + * 124 + */ 125 + #define WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT BIT(0) 126 + #define WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR BIT(1) 127 + #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2) 128 + 129 + /** 130 + * struct ieee80211_rann_ie - RANN (root announcement) element 131 + * @rann_flags: Flags 132 + * @rann_hopcount: Hop Count 133 + * @rann_ttl: Element TTL 134 + * @rann_addr: Root Mesh STA Address 135 + * @rann_seq: HWMP Sequence Number 136 + * @rann_interval: Interval 137 + * @rann_metric: Metric 138 + * 139 + * This structure represents the payload of the "RANN element" as 140 + * described in IEEE Std 802.11-2020 section 9.4.2.111. 141 + */ 142 + struct ieee80211_rann_ie { 143 + u8 rann_flags; 144 + u8 rann_hopcount; 145 + u8 rann_ttl; 146 + u8 rann_addr[ETH_ALEN]; 147 + __le32 rann_seq; 148 + __le32 rann_interval; 149 + __le32 rann_metric; 150 + } __packed; 151 + 152 + enum ieee80211_rann_flags { 153 + RANN_FLAG_IS_GATE = 1 << 0, 154 + }; 155 + 156 + /* Mesh action codes */ 157 + enum ieee80211_mesh_actioncode { 158 + WLAN_MESH_ACTION_LINK_METRIC_REPORT, 159 + WLAN_MESH_ACTION_HWMP_PATH_SELECTION, 160 + WLAN_MESH_ACTION_GATE_ANNOUNCEMENT, 161 + WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION, 162 + WLAN_MESH_ACTION_MCCA_SETUP_REQUEST, 163 + WLAN_MESH_ACTION_MCCA_SETUP_REPLY, 164 + WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST, 165 + WLAN_MESH_ACTION_MCCA_ADVERTISEMENT, 166 + WLAN_MESH_ACTION_MCCA_TEARDOWN, 167 + WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST, 168 + WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE, 169 + }; 170 + 171 + /** 172 + * enum ieee80211_mesh_sync_method - mesh synchronization method identifier 173 + * 174 + * @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method 175 + * @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method 176 + * that will be specified in a vendor specific information element 177 + */ 178 + enum ieee80211_mesh_sync_method { 179 + IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1, 180 + IEEE80211_SYNC_METHOD_VENDOR = 255, 181 + }; 182 + 183 + /** 184 + * enum ieee80211_mesh_path_protocol - mesh path selection protocol identifier 185 + * 186 + * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol 187 + * @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will 188 + * be specified in a vendor specific information element 189 + */ 190 + enum ieee80211_mesh_path_protocol { 191 + IEEE80211_PATH_PROTOCOL_HWMP = 1, 192 + IEEE80211_PATH_PROTOCOL_VENDOR = 255, 193 + }; 194 + 195 + /** 196 + * enum ieee80211_mesh_path_metric - mesh path selection metric identifier 197 + * 198 + * @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric 199 + * @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be 200 + * specified in a vendor specific information element 201 + */ 202 + enum ieee80211_mesh_path_metric { 203 + IEEE80211_PATH_METRIC_AIRTIME = 1, 204 + IEEE80211_PATH_METRIC_VENDOR = 255, 205 + }; 206 + 207 + /** 208 + * enum ieee80211_root_mode_identifier - root mesh STA mode identifier 209 + * 210 + * These attribute are used by dot11MeshHWMPRootMode to set root mesh STA mode 211 + * 212 + * @IEEE80211_ROOTMODE_NO_ROOT: the mesh STA is not a root mesh STA (default) 213 + * @IEEE80211_ROOTMODE_ROOT: the mesh STA is a root mesh STA if greater than 214 + * this value 215 + * @IEEE80211_PROACTIVE_PREQ_NO_PREP: the mesh STA is a root mesh STA supports 216 + * the proactive PREQ with proactive PREP subfield set to 0 217 + * @IEEE80211_PROACTIVE_PREQ_WITH_PREP: the mesh STA is a root mesh STA 218 + * supports the proactive PREQ with proactive PREP subfield set to 1 219 + * @IEEE80211_PROACTIVE_RANN: the mesh STA is a root mesh STA supports 220 + * the proactive RANN 221 + */ 222 + enum ieee80211_root_mode_identifier { 223 + IEEE80211_ROOTMODE_NO_ROOT = 0, 224 + IEEE80211_ROOTMODE_ROOT = 1, 225 + IEEE80211_PROACTIVE_PREQ_NO_PREP = 2, 226 + IEEE80211_PROACTIVE_PREQ_WITH_PREP = 3, 227 + IEEE80211_PROACTIVE_RANN = 4, 228 + }; 229 + 230 + #endif /* LINUX_IEEE80211_MESH_H */
+35
include/linux/ieee80211-nan.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * WFA NAN 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_NAN_H 16 + #define LINUX_IEEE80211_NAN_H 17 + 18 + /* NAN operation mode, as defined in Wi-Fi Aware (TM) specification Table 81 */ 19 + #define NAN_OP_MODE_PHY_MODE_VHT 0x01 20 + #define NAN_OP_MODE_PHY_MODE_HE 0x10 21 + #define NAN_OP_MODE_PHY_MODE_MASK 0x11 22 + #define NAN_OP_MODE_80P80MHZ 0x02 23 + #define NAN_OP_MODE_160MHZ 0x04 24 + #define NAN_OP_MODE_PNDL_SUPPRTED 0x08 25 + 26 + /* NAN Device capabilities, as defined in Wi-Fi Aware (TM) specification 27 + * Table 79 28 + */ 29 + #define NAN_DEV_CAPA_DFS_OWNER 0x01 30 + #define NAN_DEV_CAPA_EXT_KEY_ID_SUPPORTED 0x02 31 + #define NAN_DEV_CAPA_SIM_NDP_RX_SUPPORTED 0x04 32 + #define NAN_DEV_CAPA_NDPE_SUPPORTED 0x08 33 + #define NAN_DEV_CAPA_S3_SUPPORTED 0x10 34 + 35 + #endif /* LINUX_IEEE80211_NAN_H */
+71
include/linux/ieee80211-p2p.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * WFA P2P 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_P2P_H 16 + #define LINUX_IEEE80211_P2P_H 17 + 18 + #include <linux/types.h> 19 + /* 20 + * Peer-to-Peer IE attribute related definitions. 21 + */ 22 + /* 23 + * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute. 24 + */ 25 + enum ieee80211_p2p_attr_id { 26 + IEEE80211_P2P_ATTR_STATUS = 0, 27 + IEEE80211_P2P_ATTR_MINOR_REASON, 28 + IEEE80211_P2P_ATTR_CAPABILITY, 29 + IEEE80211_P2P_ATTR_DEVICE_ID, 30 + IEEE80211_P2P_ATTR_GO_INTENT, 31 + IEEE80211_P2P_ATTR_GO_CONFIG_TIMEOUT, 32 + IEEE80211_P2P_ATTR_LISTEN_CHANNEL, 33 + IEEE80211_P2P_ATTR_GROUP_BSSID, 34 + IEEE80211_P2P_ATTR_EXT_LISTEN_TIMING, 35 + IEEE80211_P2P_ATTR_INTENDED_IFACE_ADDR, 36 + IEEE80211_P2P_ATTR_MANAGABILITY, 37 + IEEE80211_P2P_ATTR_CHANNEL_LIST, 38 + IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 39 + IEEE80211_P2P_ATTR_DEVICE_INFO, 40 + IEEE80211_P2P_ATTR_GROUP_INFO, 41 + IEEE80211_P2P_ATTR_GROUP_ID, 42 + IEEE80211_P2P_ATTR_INTERFACE, 43 + IEEE80211_P2P_ATTR_OPER_CHANNEL, 44 + IEEE80211_P2P_ATTR_INVITE_FLAGS, 45 + /* 19 - 220: Reserved */ 46 + IEEE80211_P2P_ATTR_VENDOR_SPECIFIC = 221, 47 + 48 + IEEE80211_P2P_ATTR_MAX 49 + }; 50 + 51 + /* Notice of Absence attribute - described in P2P spec 4.1.14 */ 52 + /* Typical max value used here */ 53 + #define IEEE80211_P2P_NOA_DESC_MAX 4 54 + 55 + struct ieee80211_p2p_noa_desc { 56 + u8 count; 57 + __le32 duration; 58 + __le32 interval; 59 + __le32 start_time; 60 + } __packed; 61 + 62 + struct ieee80211_p2p_noa_attr { 63 + u8 index; 64 + u8 oppps_ctwindow; 65 + struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX]; 66 + } __packed; 67 + 68 + #define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7) 69 + #define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F 70 + 71 + #endif /* LINUX_IEEE80211_P2P_H */
+575
include/linux/ieee80211-s1g.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * IEEE 802.11 S1G 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_S1G_H 16 + #define LINUX_IEEE80211_S1G_H 17 + 18 + #include <linux/types.h> 19 + #include <linux/if_ether.h> 20 + 21 + /* bits unique to S1G beacon frame control */ 22 + #define IEEE80211_S1G_BCN_NEXT_TBTT 0x100 23 + #define IEEE80211_S1G_BCN_CSSID 0x200 24 + #define IEEE80211_S1G_BCN_ANO 0x400 25 + 26 + /* see 802.11ah-2016 9.9 NDP CMAC frames */ 27 + #define IEEE80211_S1G_1MHZ_NDP_BITS 25 28 + #define IEEE80211_S1G_1MHZ_NDP_BYTES 4 29 + #define IEEE80211_S1G_2MHZ_NDP_BITS 37 30 + #define IEEE80211_S1G_2MHZ_NDP_BYTES 5 31 + 32 + /** 33 + * ieee80211_is_s1g_beacon - check if IEEE80211_FTYPE_EXT && 34 + * IEEE80211_STYPE_S1G_BEACON 35 + * @fc: frame control bytes in little-endian byteorder 36 + * Return: whether or not the frame is an S1G beacon 37 + */ 38 + static inline bool ieee80211_is_s1g_beacon(__le16 fc) 39 + { 40 + return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 41 + IEEE80211_FCTL_STYPE)) == 42 + cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON); 43 + } 44 + 45 + /** 46 + * ieee80211_s1g_has_next_tbtt - check if IEEE80211_S1G_BCN_NEXT_TBTT 47 + * @fc: frame control bytes in little-endian byteorder 48 + * Return: whether or not the frame contains the variable-length 49 + * next TBTT field 50 + */ 51 + static inline bool ieee80211_s1g_has_next_tbtt(__le16 fc) 52 + { 53 + return ieee80211_is_s1g_beacon(fc) && 54 + (fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT)); 55 + } 56 + 57 + /** 58 + * ieee80211_s1g_has_ano - check if IEEE80211_S1G_BCN_ANO 59 + * @fc: frame control bytes in little-endian byteorder 60 + * Return: whether or not the frame contains the variable-length 61 + * ANO field 62 + */ 63 + static inline bool ieee80211_s1g_has_ano(__le16 fc) 64 + { 65 + return ieee80211_is_s1g_beacon(fc) && 66 + (fc & cpu_to_le16(IEEE80211_S1G_BCN_ANO)); 67 + } 68 + 69 + /** 70 + * ieee80211_s1g_has_cssid - check if IEEE80211_S1G_BCN_CSSID 71 + * @fc: frame control bytes in little-endian byteorder 72 + * Return: whether or not the frame contains the variable-length 73 + * compressed SSID field 74 + */ 75 + static inline bool ieee80211_s1g_has_cssid(__le16 fc) 76 + { 77 + return ieee80211_is_s1g_beacon(fc) && 78 + (fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID)); 79 + } 80 + 81 + /** 82 + * enum ieee80211_s1g_chanwidth - S1G channel widths 83 + * These are defined in IEEE802.11-2016ah Table 10-20 84 + * as BSS Channel Width 85 + * 86 + * @IEEE80211_S1G_CHANWIDTH_1MHZ: 1MHz operating channel 87 + * @IEEE80211_S1G_CHANWIDTH_2MHZ: 2MHz operating channel 88 + * @IEEE80211_S1G_CHANWIDTH_4MHZ: 4MHz operating channel 89 + * @IEEE80211_S1G_CHANWIDTH_8MHZ: 8MHz operating channel 90 + * @IEEE80211_S1G_CHANWIDTH_16MHZ: 16MHz operating channel 91 + */ 92 + enum ieee80211_s1g_chanwidth { 93 + IEEE80211_S1G_CHANWIDTH_1MHZ = 0, 94 + IEEE80211_S1G_CHANWIDTH_2MHZ = 1, 95 + IEEE80211_S1G_CHANWIDTH_4MHZ = 3, 96 + IEEE80211_S1G_CHANWIDTH_8MHZ = 7, 97 + IEEE80211_S1G_CHANWIDTH_16MHZ = 15, 98 + }; 99 + 100 + /** 101 + * enum ieee80211_s1g_pri_chanwidth - S1G primary channel widths 102 + * described in IEEE80211-2024 Table 10-39. 103 + * 104 + * @IEEE80211_S1G_PRI_CHANWIDTH_2MHZ: 2MHz primary channel 105 + * @IEEE80211_S1G_PRI_CHANWIDTH_1MHZ: 1MHz primary channel 106 + */ 107 + enum ieee80211_s1g_pri_chanwidth { 108 + IEEE80211_S1G_PRI_CHANWIDTH_2MHZ = 0, 109 + IEEE80211_S1G_PRI_CHANWIDTH_1MHZ = 1, 110 + }; 111 + 112 + /** 113 + * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element 114 + * @compat_info: Compatibility Information 115 + * @beacon_int: Beacon Interval 116 + * @tsf_completion: TSF Completion 117 + * 118 + * This structure represents the payload of the "S1G Beacon 119 + * Compatibility element" as described in IEEE Std 802.11-2020 section 120 + * 9.4.2.196. 121 + */ 122 + struct ieee80211_s1g_bcn_compat_ie { 123 + __le16 compat_info; 124 + __le16 beacon_int; 125 + __le32 tsf_completion; 126 + } __packed; 127 + 128 + /** 129 + * struct ieee80211_s1g_oper_ie - S1G Operation element 130 + * @ch_width: S1G Operation Information Channel Width 131 + * @oper_class: S1G Operation Information Operating Class 132 + * @primary_ch: S1G Operation Information Primary Channel Number 133 + * @oper_ch: S1G Operation Information Channel Center Frequency 134 + * @basic_mcs_nss: Basic S1G-MCS and NSS Set 135 + * 136 + * This structure represents the payload of the "S1G Operation 137 + * element" as described in IEEE Std 802.11-2020 section 9.4.2.212. 138 + */ 139 + struct ieee80211_s1g_oper_ie { 140 + u8 ch_width; 141 + u8 oper_class; 142 + u8 primary_ch; 143 + u8 oper_ch; 144 + __le16 basic_mcs_nss; 145 + } __packed; 146 + 147 + /** 148 + * struct ieee80211_aid_response_ie - AID Response element 149 + * @aid: AID/Group AID 150 + * @switch_count: AID Switch Count 151 + * @response_int: AID Response Interval 152 + * 153 + * This structure represents the payload of the "AID Response element" 154 + * as described in IEEE Std 802.11-2020 section 9.4.2.194. 155 + */ 156 + struct ieee80211_aid_response_ie { 157 + __le16 aid; 158 + u8 switch_count; 159 + __le16 response_int; 160 + } __packed; 161 + 162 + struct ieee80211_s1g_cap { 163 + u8 capab_info[10]; 164 + u8 supp_mcs_nss[5]; 165 + } __packed; 166 + 167 + /** 168 + * ieee80211_s1g_optional_len - determine length of optional S1G beacon fields 169 + * @fc: frame control bytes in little-endian byteorder 170 + * Return: total length in bytes of the optional fixed-length fields 171 + * 172 + * S1G beacons may contain up to three optional fixed-length fields that 173 + * precede the variable-length elements. Whether these fields are present 174 + * is indicated by flags in the frame control field. 175 + * 176 + * From IEEE 802.11-2024 section 9.3.4.3: 177 + * - Next TBTT field may be 0 or 3 bytes 178 + * - Short SSID field may be 0 or 4 bytes 179 + * - Access Network Options (ANO) field may be 0 or 1 byte 180 + */ 181 + static inline size_t 182 + ieee80211_s1g_optional_len(__le16 fc) 183 + { 184 + size_t len = 0; 185 + 186 + if (ieee80211_s1g_has_next_tbtt(fc)) 187 + len += 3; 188 + 189 + if (ieee80211_s1g_has_cssid(fc)) 190 + len += 4; 191 + 192 + if (ieee80211_s1g_has_ano(fc)) 193 + len += 1; 194 + 195 + return len; 196 + } 197 + 198 + /* S1G Capabilities Information field */ 199 + #define IEEE80211_S1G_CAPABILITY_LEN 15 200 + 201 + #define S1G_CAP0_S1G_LONG BIT(0) 202 + #define S1G_CAP0_SGI_1MHZ BIT(1) 203 + #define S1G_CAP0_SGI_2MHZ BIT(2) 204 + #define S1G_CAP0_SGI_4MHZ BIT(3) 205 + #define S1G_CAP0_SGI_8MHZ BIT(4) 206 + #define S1G_CAP0_SGI_16MHZ BIT(5) 207 + #define S1G_CAP0_SUPP_CH_WIDTH GENMASK(7, 6) 208 + 209 + #define S1G_SUPP_CH_WIDTH_2 0 210 + #define S1G_SUPP_CH_WIDTH_4 1 211 + #define S1G_SUPP_CH_WIDTH_8 2 212 + #define S1G_SUPP_CH_WIDTH_16 3 213 + #define S1G_SUPP_CH_WIDTH_MAX(cap) ((1 << FIELD_GET(S1G_CAP0_SUPP_CH_WIDTH, \ 214 + cap[0])) << 1) 215 + 216 + #define S1G_CAP1_RX_LDPC BIT(0) 217 + #define S1G_CAP1_TX_STBC BIT(1) 218 + #define S1G_CAP1_RX_STBC BIT(2) 219 + #define S1G_CAP1_SU_BFER BIT(3) 220 + #define S1G_CAP1_SU_BFEE BIT(4) 221 + #define S1G_CAP1_BFEE_STS GENMASK(7, 5) 222 + 223 + #define S1G_CAP2_SOUNDING_DIMENSIONS GENMASK(2, 0) 224 + #define S1G_CAP2_MU_BFER BIT(3) 225 + #define S1G_CAP2_MU_BFEE BIT(4) 226 + #define S1G_CAP2_PLUS_HTC_VHT BIT(5) 227 + #define S1G_CAP2_TRAVELING_PILOT GENMASK(7, 6) 228 + 229 + #define S1G_CAP3_RD_RESPONDER BIT(0) 230 + #define S1G_CAP3_HT_DELAYED_BA BIT(1) 231 + #define S1G_CAP3_MAX_MPDU_LEN BIT(2) 232 + #define S1G_CAP3_MAX_AMPDU_LEN_EXP GENMASK(4, 3) 233 + #define S1G_CAP3_MIN_MPDU_START GENMASK(7, 5) 234 + 235 + #define S1G_CAP4_UPLINK_SYNC BIT(0) 236 + #define S1G_CAP4_DYNAMIC_AID BIT(1) 237 + #define S1G_CAP4_BAT BIT(2) 238 + #define S1G_CAP4_TIME_ADE BIT(3) 239 + #define S1G_CAP4_NON_TIM BIT(4) 240 + #define S1G_CAP4_GROUP_AID BIT(5) 241 + #define S1G_CAP4_STA_TYPE GENMASK(7, 6) 242 + 243 + #define S1G_CAP5_CENT_AUTH_CONTROL BIT(0) 244 + #define S1G_CAP5_DIST_AUTH_CONTROL BIT(1) 245 + #define S1G_CAP5_AMSDU BIT(2) 246 + #define S1G_CAP5_AMPDU BIT(3) 247 + #define S1G_CAP5_ASYMMETRIC_BA BIT(4) 248 + #define S1G_CAP5_FLOW_CONTROL BIT(5) 249 + #define S1G_CAP5_SECTORIZED_BEAM GENMASK(7, 6) 250 + 251 + #define S1G_CAP6_OBSS_MITIGATION BIT(0) 252 + #define S1G_CAP6_FRAGMENT_BA BIT(1) 253 + #define S1G_CAP6_NDP_PS_POLL BIT(2) 254 + #define S1G_CAP6_RAW_OPERATION BIT(3) 255 + #define S1G_CAP6_PAGE_SLICING BIT(4) 256 + #define S1G_CAP6_TXOP_SHARING_IMP_ACK BIT(5) 257 + #define S1G_CAP6_VHT_LINK_ADAPT GENMASK(7, 6) 258 + 259 + #define S1G_CAP7_TACK_AS_PS_POLL BIT(0) 260 + #define S1G_CAP7_DUP_1MHZ BIT(1) 261 + #define S1G_CAP7_MCS_NEGOTIATION BIT(2) 262 + #define S1G_CAP7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3) 263 + #define S1G_CAP7_NDP_BFING_REPORT_POLL BIT(4) 264 + #define S1G_CAP7_UNSOLICITED_DYN_AID BIT(5) 265 + #define S1G_CAP7_SECTOR_TRAINING_OPERATION BIT(6) 266 + #define S1G_CAP7_TEMP_PS_MODE_SWITCH BIT(7) 267 + 268 + #define S1G_CAP8_TWT_GROUPING BIT(0) 269 + #define S1G_CAP8_BDT BIT(1) 270 + #define S1G_CAP8_COLOR GENMASK(4, 2) 271 + #define S1G_CAP8_TWT_REQUEST BIT(5) 272 + #define S1G_CAP8_TWT_RESPOND BIT(6) 273 + #define S1G_CAP8_PV1_FRAME BIT(7) 274 + 275 + #define S1G_CAP9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0) 276 + 277 + #define S1G_OPER_CH_WIDTH_PRIMARY BIT(0) 278 + #define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1) 279 + #define S1G_OPER_CH_PRIMARY_LOCATION BIT(5) 280 + 281 + #define S1G_2M_PRIMARY_LOCATION_LOWER 0 282 + #define S1G_2M_PRIMARY_LOCATION_UPPER 1 283 + 284 + #define LISTEN_INT_USF GENMASK(15, 14) 285 + #define LISTEN_INT_UI GENMASK(13, 0) 286 + 287 + #define IEEE80211_MAX_USF FIELD_MAX(LISTEN_INT_USF) 288 + #define IEEE80211_MAX_UI FIELD_MAX(LISTEN_INT_UI) 289 + 290 + /* S1G encoding types */ 291 + #define IEEE80211_S1G_TIM_ENC_MODE_BLOCK 0 292 + #define IEEE80211_S1G_TIM_ENC_MODE_SINGLE 1 293 + #define IEEE80211_S1G_TIM_ENC_MODE_OLB 2 294 + 295 + enum ieee80211_s1g_actioncode { 296 + WLAN_S1G_AID_SWITCH_REQUEST, 297 + WLAN_S1G_AID_SWITCH_RESPONSE, 298 + WLAN_S1G_SYNC_CONTROL, 299 + WLAN_S1G_STA_INFO_ANNOUNCE, 300 + WLAN_S1G_EDCA_PARAM_SET, 301 + WLAN_S1G_EL_OPERATION, 302 + WLAN_S1G_TWT_SETUP, 303 + WLAN_S1G_TWT_TEARDOWN, 304 + WLAN_S1G_SECT_GROUP_ID_LIST, 305 + WLAN_S1G_SECT_ID_FEEDBACK, 306 + WLAN_S1G_TWT_INFORMATION = 11, 307 + }; 308 + 309 + /** 310 + * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon 311 + * @fc: frame control bytes in little-endian byteorder 312 + * @variable: pointer to the beacon frame elements 313 + * @variable_len: length of the frame elements 314 + * Return: whether or not the frame is an S1G short beacon. As per 315 + * IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall 316 + * always be present as the first element in beacon frames generated at a 317 + * TBTT (Target Beacon Transmission Time), so any frame not containing 318 + * this element must have been generated at a TSBTT (Target Short Beacon 319 + * Transmission Time) that is not a TBTT. Additionally, short beacons are 320 + * prohibited from containing the S1G beacon compatibility element as per 321 + * IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with 322 + * either no elements or the first element is not the beacon compatibility 323 + * element, we have a short beacon. 324 + */ 325 + static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable, 326 + size_t variable_len) 327 + { 328 + if (!ieee80211_is_s1g_beacon(fc)) 329 + return false; 330 + 331 + /* 332 + * If the frame does not contain at least 1 element (this is perfectly 333 + * valid in a short beacon) and is an S1G beacon, we have a short 334 + * beacon. 335 + */ 336 + if (variable_len < 2) 337 + return true; 338 + 339 + return variable[0] != WLAN_EID_S1G_BCN_COMPAT; 340 + } 341 + 342 + struct s1g_tim_aid { 343 + u16 aid; 344 + u8 target_blk; /* Target block index */ 345 + u8 target_subblk; /* Target subblock index */ 346 + u8 target_subblk_bit; /* Target subblock bit */ 347 + }; 348 + 349 + struct s1g_tim_enc_block { 350 + u8 enc_mode; 351 + bool inverse; 352 + const u8 *ptr; 353 + u8 len; 354 + 355 + /* 356 + * For an OLB encoded block that spans multiple blocks, this 357 + * is the offset into the span described by that encoded block. 358 + */ 359 + u8 olb_blk_offset; 360 + }; 361 + 362 + /* 363 + * Helper routines to quickly extract the length of an encoded block. Validation 364 + * is also performed to ensure the length extracted lies within the TIM. 365 + */ 366 + 367 + static inline int ieee80211_s1g_len_bitmap(const u8 *ptr, const u8 *end) 368 + { 369 + u8 blkmap; 370 + u8 n_subblks; 371 + 372 + if (ptr >= end) 373 + return -EINVAL; 374 + 375 + blkmap = *ptr; 376 + n_subblks = hweight8(blkmap); 377 + 378 + if (ptr + 1 + n_subblks > end) 379 + return -EINVAL; 380 + 381 + return 1 + n_subblks; 382 + } 383 + 384 + static inline int ieee80211_s1g_len_single(const u8 *ptr, const u8 *end) 385 + { 386 + return (ptr + 1 > end) ? -EINVAL : 1; 387 + } 388 + 389 + static inline int ieee80211_s1g_len_olb(const u8 *ptr, const u8 *end) 390 + { 391 + if (ptr >= end) 392 + return -EINVAL; 393 + 394 + return (ptr + 1 + *ptr > end) ? -EINVAL : 1 + *ptr; 395 + } 396 + 397 + /* 398 + * Enumerate all encoded blocks until we find the encoded block that describes 399 + * our target AID. OLB is a special case as a single encoded block can describe 400 + * multiple blocks as a single encoded block. 401 + */ 402 + static inline int ieee80211_s1g_find_target_block(struct s1g_tim_enc_block *enc, 403 + const struct s1g_tim_aid *aid, 404 + const u8 *ptr, const u8 *end) 405 + { 406 + /* need at least block-control octet */ 407 + while (ptr + 1 <= end) { 408 + u8 ctrl = *ptr++; 409 + u8 mode = ctrl & 0x03; 410 + bool contains, inverse = ctrl & BIT(2); 411 + u8 span, blk_off = ctrl >> 3; 412 + int len; 413 + 414 + switch (mode) { 415 + case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 416 + len = ieee80211_s1g_len_bitmap(ptr, end); 417 + contains = blk_off == aid->target_blk; 418 + break; 419 + case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 420 + len = ieee80211_s1g_len_single(ptr, end); 421 + contains = blk_off == aid->target_blk; 422 + break; 423 + case IEEE80211_S1G_TIM_ENC_MODE_OLB: 424 + len = ieee80211_s1g_len_olb(ptr, end); 425 + /* 426 + * An OLB encoded block can describe more then one 427 + * block, meaning an encoded OLB block can span more 428 + * then a single block. 429 + */ 430 + if (len > 0) { 431 + /* Minus one for the length octet */ 432 + span = DIV_ROUND_UP(len - 1, 8); 433 + /* 434 + * Check if our target block lies within the 435 + * block span described by this encoded block. 436 + */ 437 + contains = (aid->target_blk >= blk_off) && 438 + (aid->target_blk < blk_off + span); 439 + } 440 + break; 441 + default: 442 + return -EOPNOTSUPP; 443 + } 444 + 445 + if (len < 0) 446 + return len; 447 + 448 + if (contains) { 449 + enc->enc_mode = mode; 450 + enc->inverse = inverse; 451 + enc->ptr = ptr; 452 + enc->len = (u8)len; 453 + enc->olb_blk_offset = blk_off; 454 + return 0; 455 + } 456 + 457 + ptr += len; 458 + } 459 + 460 + return -ENOENT; 461 + } 462 + 463 + static inline bool ieee80211_s1g_parse_bitmap(struct s1g_tim_enc_block *enc, 464 + struct s1g_tim_aid *aid) 465 + { 466 + const u8 *ptr = enc->ptr; 467 + u8 blkmap = *ptr++; 468 + 469 + /* 470 + * If our block bitmap does not contain a set bit that corresponds 471 + * to our AID, it could mean a variety of things depending on if 472 + * the encoding mode is inverted or not. 473 + * 474 + * 1. If inverted, it means the entire subblock is present and hence 475 + * our AID has been set. 476 + * 2. If not inverted, it means our subblock is not present and hence 477 + * it is all zero meaning our AID is not set. 478 + */ 479 + if (!(blkmap & BIT(aid->target_subblk))) 480 + return enc->inverse; 481 + 482 + /* 483 + * Increment ptr by the number of set subblocks that appear before our 484 + * target subblock. If our target subblock is 0, do nothing as ptr 485 + * already points to our target subblock. 486 + */ 487 + if (aid->target_subblk) 488 + ptr += hweight8(blkmap & GENMASK(aid->target_subblk - 1, 0)); 489 + 490 + return !!(*ptr & BIT(aid->target_subblk_bit)) ^ enc->inverse; 491 + } 492 + 493 + static inline bool ieee80211_s1g_parse_single(struct s1g_tim_enc_block *enc, 494 + struct s1g_tim_aid *aid) 495 + { 496 + /* 497 + * Single AID mode describes, as the name suggests, a single AID 498 + * within the block described by the encoded block. The octet 499 + * contains the 6 LSBs of the AID described in the block. The other 500 + * 2 bits are reserved. When inversed, every single AID described 501 + * by the current block have buffered traffic except for the AID 502 + * described in the single AID octet. 503 + */ 504 + return ((*enc->ptr & 0x3f) == (aid->aid & 0x3f)) ^ enc->inverse; 505 + } 506 + 507 + static inline bool ieee80211_s1g_parse_olb(struct s1g_tim_enc_block *enc, 508 + struct s1g_tim_aid *aid) 509 + { 510 + const u8 *ptr = enc->ptr; 511 + u8 blk_len = *ptr++; 512 + /* 513 + * Given an OLB encoded block that describes multiple blocks, 514 + * calculate the offset into the span. Then calculate the 515 + * subblock location normally. 516 + */ 517 + u16 span_offset = aid->target_blk - enc->olb_blk_offset; 518 + u16 subblk_idx = span_offset * 8 + aid->target_subblk; 519 + 520 + if (subblk_idx >= blk_len) 521 + return enc->inverse; 522 + 523 + return !!(ptr[subblk_idx] & BIT(aid->target_subblk_bit)) ^ enc->inverse; 524 + } 525 + 526 + /* 527 + * An S1G PVB has 3 non optional encoding types, each that can be inverted. 528 + * An S1G PVB is constructed with zero or more encoded block subfields. Each 529 + * encoded block represents a single "block" of AIDs (64), and each encoded 530 + * block can contain one of the 3 encoding types alongside a single bit for 531 + * whether the bits should be inverted. 532 + * 533 + * As the standard makes no guarantee about the ordering of encoded blocks, 534 + * we must parse every encoded block in the worst case scenario given an 535 + * AID that lies within the last block. 536 + */ 537 + static inline bool ieee80211_s1g_check_tim(const struct ieee80211_tim_ie *tim, 538 + u8 tim_len, u16 aid) 539 + { 540 + int err; 541 + struct s1g_tim_aid target_aid; 542 + struct s1g_tim_enc_block enc_blk; 543 + 544 + if (tim_len < 3) 545 + return false; 546 + 547 + target_aid.aid = aid; 548 + target_aid.target_blk = (aid >> 6) & 0x1f; 549 + target_aid.target_subblk = (aid >> 3) & 0x7; 550 + target_aid.target_subblk_bit = aid & 0x7; 551 + 552 + /* 553 + * Find our AIDs target encoded block and fill &enc_blk with the 554 + * encoded blocks information. If no entry is found or an error 555 + * occurs return false. 556 + */ 557 + err = ieee80211_s1g_find_target_block(&enc_blk, &target_aid, 558 + tim->virtual_map, 559 + (const u8 *)tim + tim_len + 2); 560 + if (err) 561 + return false; 562 + 563 + switch (enc_blk.enc_mode) { 564 + case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 565 + return ieee80211_s1g_parse_bitmap(&enc_blk, &target_aid); 566 + case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 567 + return ieee80211_s1g_parse_single(&enc_blk, &target_aid); 568 + case IEEE80211_S1G_TIM_ENC_MODE_OLB: 569 + return ieee80211_s1g_parse_olb(&enc_blk, &target_aid); 570 + default: 571 + return false; 572 + } 573 + } 574 + 575 + #endif /* LINUX_IEEE80211_H */
+236
include/linux/ieee80211-vht.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * IEEE 802.11 VHT 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_VHT_H 16 + #define LINUX_IEEE80211_VHT_H 17 + 18 + #include <linux/types.h> 19 + #include <linux/if_ether.h> 20 + 21 + #define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895 22 + #define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991 23 + #define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454 24 + 25 + /** 26 + * enum ieee80211_vht_opmode_bits - VHT operating mode field bits 27 + * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK: channel width mask 28 + * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: 20 MHz channel width 29 + * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width 30 + * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ: 80 MHz channel width 31 + * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ: 160 MHz or 80+80 MHz channel width 32 + * @IEEE80211_OPMODE_NOTIF_BW_160_80P80: 160 / 80+80 MHz indicator flag 33 + * @IEEE80211_OPMODE_NOTIF_RX_NSS_MASK: number of spatial streams mask 34 + * (the NSS value is the value of this field + 1) 35 + * @IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT: number of spatial streams shift 36 + * @IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF: indicates streams in SU-MIMO PPDU 37 + * using a beamforming steering matrix 38 + */ 39 + enum ieee80211_vht_opmode_bits { 40 + IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK = 0x03, 41 + IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ = 0, 42 + IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ = 1, 43 + IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ = 2, 44 + IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ = 3, 45 + IEEE80211_OPMODE_NOTIF_BW_160_80P80 = 0x04, 46 + IEEE80211_OPMODE_NOTIF_RX_NSS_MASK = 0x70, 47 + IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4, 48 + IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF = 0x80, 49 + }; 50 + 51 + /* 52 + * Maximum length of AMPDU that the STA can receive in VHT. 53 + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) 54 + */ 55 + enum ieee80211_vht_max_ampdu_length_exp { 56 + IEEE80211_VHT_MAX_AMPDU_8K = 0, 57 + IEEE80211_VHT_MAX_AMPDU_16K = 1, 58 + IEEE80211_VHT_MAX_AMPDU_32K = 2, 59 + IEEE80211_VHT_MAX_AMPDU_64K = 3, 60 + IEEE80211_VHT_MAX_AMPDU_128K = 4, 61 + IEEE80211_VHT_MAX_AMPDU_256K = 5, 62 + IEEE80211_VHT_MAX_AMPDU_512K = 6, 63 + IEEE80211_VHT_MAX_AMPDU_1024K = 7 64 + }; 65 + 66 + /** 67 + * struct ieee80211_vht_mcs_info - VHT MCS information 68 + * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams 69 + * @rx_highest: Indicates highest long GI VHT PPDU data rate 70 + * STA can receive. Rate expressed in units of 1 Mbps. 71 + * If this field is 0 this value should not be used to 72 + * consider the highest RX data rate supported. 73 + * The top 3 bits of this field indicate the Maximum NSTS,total 74 + * (a beamformee capability.) 75 + * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams 76 + * @tx_highest: Indicates highest long GI VHT PPDU data rate 77 + * STA can transmit. Rate expressed in units of 1 Mbps. 78 + * If this field is 0 this value should not be used to 79 + * consider the highest TX data rate supported. 80 + * The top 2 bits of this field are reserved, the 81 + * 3rd bit from the top indiciates VHT Extended NSS BW 82 + * Capability. 83 + */ 84 + struct ieee80211_vht_mcs_info { 85 + __le16 rx_mcs_map; 86 + __le16 rx_highest; 87 + __le16 tx_mcs_map; 88 + __le16 tx_highest; 89 + } __packed; 90 + 91 + /* for rx_highest */ 92 + #define IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT 13 93 + #define IEEE80211_VHT_MAX_NSTS_TOTAL_MASK (7 << IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT) 94 + 95 + /* for tx_highest */ 96 + #define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13) 97 + 98 + /** 99 + * enum ieee80211_vht_mcs_support - VHT MCS support definitions 100 + * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the 101 + * number of streams 102 + * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported 103 + * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported 104 + * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported 105 + * 106 + * These definitions are used in each 2-bit subfield of the @rx_mcs_map 107 + * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are 108 + * both split into 8 subfields by number of streams. These values indicate 109 + * which MCSes are supported for the number of streams the value appears 110 + * for. 111 + */ 112 + enum ieee80211_vht_mcs_support { 113 + IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, 114 + IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, 115 + IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, 116 + IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, 117 + }; 118 + 119 + /** 120 + * struct ieee80211_vht_cap - VHT capabilities 121 + * 122 + * This structure is the "VHT capabilities element" as 123 + * described in 802.11ac D3.0 8.4.2.160 124 + * @vht_cap_info: VHT capability info 125 + * @supp_mcs: VHT MCS supported rates 126 + */ 127 + struct ieee80211_vht_cap { 128 + __le32 vht_cap_info; 129 + struct ieee80211_vht_mcs_info supp_mcs; 130 + } __packed; 131 + 132 + /** 133 + * enum ieee80211_vht_chanwidth - VHT channel width 134 + * @IEEE80211_VHT_CHANWIDTH_USE_HT: use the HT operation IE to 135 + * determine the channel width (20 or 40 MHz) 136 + * @IEEE80211_VHT_CHANWIDTH_80MHZ: 80 MHz bandwidth 137 + * @IEEE80211_VHT_CHANWIDTH_160MHZ: 160 MHz bandwidth 138 + * @IEEE80211_VHT_CHANWIDTH_80P80MHZ: 80+80 MHz bandwidth 139 + */ 140 + enum ieee80211_vht_chanwidth { 141 + IEEE80211_VHT_CHANWIDTH_USE_HT = 0, 142 + IEEE80211_VHT_CHANWIDTH_80MHZ = 1, 143 + IEEE80211_VHT_CHANWIDTH_160MHZ = 2, 144 + IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, 145 + }; 146 + 147 + /** 148 + * struct ieee80211_vht_operation - VHT operation IE 149 + * 150 + * This structure is the "VHT operation element" as 151 + * described in 802.11ac D3.0 8.4.2.161 152 + * @chan_width: Operating channel width 153 + * @center_freq_seg0_idx: center freq segment 0 index 154 + * @center_freq_seg1_idx: center freq segment 1 index 155 + * @basic_mcs_set: VHT Basic MCS rate set 156 + */ 157 + struct ieee80211_vht_operation { 158 + u8 chan_width; 159 + u8 center_freq_seg0_idx; 160 + u8 center_freq_seg1_idx; 161 + __le16 basic_mcs_set; 162 + } __packed; 163 + 164 + /* 802.11ac VHT Capabilities */ 165 + #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 166 + #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 167 + #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 168 + #define IEEE80211_VHT_CAP_MAX_MPDU_MASK 0x00000003 169 + #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 170 + #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 171 + #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x0000000C 172 + #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT 2 173 + #define IEEE80211_VHT_CAP_RXLDPC 0x00000010 174 + #define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 175 + #define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 176 + #define IEEE80211_VHT_CAP_TXSTBC 0x00000080 177 + #define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 178 + #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 179 + #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 180 + #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 181 + #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 182 + #define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8 183 + #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 184 + #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 185 + #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 186 + #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK \ 187 + (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) 188 + #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 189 + #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \ 190 + (7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) 191 + #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 192 + #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 193 + #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 194 + #define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 195 + #define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 196 + #define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ 197 + (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) 198 + #define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 199 + #define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 200 + #define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 201 + #define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 202 + #define IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT 30 203 + #define IEEE80211_VHT_CAP_EXT_NSS_BW_MASK 0xc0000000 204 + 205 + /** 206 + * ieee80211_get_vht_max_nss - return max NSS for a given bandwidth/MCS 207 + * @cap: VHT capabilities of the peer 208 + * @bw: bandwidth to use 209 + * @mcs: MCS index to use 210 + * @ext_nss_bw_capable: indicates whether or not the local transmitter 211 + * (rate scaling algorithm) can deal with the new logic 212 + * (dot11VHTExtendedNSSBWCapable) 213 + * @max_vht_nss: current maximum NSS as advertised by the STA in 214 + * operating mode notification, can be 0 in which case the 215 + * capability data will be used to derive this (from MCS support) 216 + * Return: The maximum NSS that can be used for the given bandwidth/MCS 217 + * combination 218 + * 219 + * Due to the VHT Extended NSS Bandwidth Support, the maximum NSS can 220 + * vary for a given BW/MCS. This function parses the data. 221 + * 222 + * Note: This function is exported by cfg80211. 223 + */ 224 + int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, 225 + enum ieee80211_vht_chanwidth bw, 226 + int mcs, bool ext_nss_bw_capable, 227 + unsigned int max_vht_nss); 228 + 229 + /* VHT action codes */ 230 + enum ieee80211_vht_actioncode { 231 + WLAN_VHT_ACTION_COMPRESSED_BF = 0, 232 + WLAN_VHT_ACTION_GROUPID_MGMT = 1, 233 + WLAN_VHT_ACTION_OPMODE_NOTIF = 2, 234 + }; 235 + 236 + #endif /* LINUX_IEEE80211_VHT_H */
+19 -3289
include/linux/ieee80211.h
··· 43 43 #define IEEE80211_FCTL_VERS 0x0003 44 44 #define IEEE80211_FCTL_FTYPE 0x000c 45 45 #define IEEE80211_FCTL_STYPE 0x00f0 46 + #define IEEE80211_FCTL_TYPE (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE) 46 47 #define IEEE80211_FCTL_TODS 0x0100 47 48 #define IEEE80211_FCTL_FROMDS 0x0200 48 49 #define IEEE80211_FCTL_MOREFRAGS 0x0400 ··· 109 108 /* extension, added by 802.11ad */ 110 109 #define IEEE80211_STYPE_DMG_BEACON 0x0000 111 110 #define IEEE80211_STYPE_S1G_BEACON 0x0010 112 - 113 - /* bits unique to S1G beacon */ 114 - #define IEEE80211_S1G_BCN_NEXT_TBTT 0x100 115 - #define IEEE80211_S1G_BCN_CSSID 0x200 116 - #define IEEE80211_S1G_BCN_ANO 0x400 117 - 118 - /* see 802.11ah-2016 9.9 NDP CMAC frames */ 119 - #define IEEE80211_S1G_1MHZ_NDP_BITS 25 120 - #define IEEE80211_S1G_1MHZ_NDP_BYTES 4 121 - #define IEEE80211_S1G_2MHZ_NDP_BITS 37 122 - #define IEEE80211_S1G_2MHZ_NDP_BYTES 5 123 111 124 112 #define IEEE80211_NDP_FTYPE_CTS 0 125 113 #define IEEE80211_NDP_FTYPE_CF_END 0 ··· 211 221 #define IEEE80211_MAX_TIM_LEN 251 212 222 #define IEEE80211_MAX_MESH_PEERINGS 63 213 223 214 - /* S1G encoding types */ 215 - #define IEEE80211_S1G_TIM_ENC_MODE_BLOCK 0 216 - #define IEEE80211_S1G_TIM_ENC_MODE_SINGLE 1 217 - #define IEEE80211_S1G_TIM_ENC_MODE_OLB 2 218 - 219 224 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section 220 225 6.2.1.1.2. 221 226 ··· 224 239 /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ 225 240 #define IEEE80211_MAX_FRAME_LEN 2352 226 241 227 - /* Maximal size of an A-MSDU that can be transported in a HT BA session */ 228 - #define IEEE80211_MAX_MPDU_LEN_HT_BA 4095 229 - 230 - /* Maximal size of an A-MSDU */ 231 - #define IEEE80211_MAX_MPDU_LEN_HT_3839 3839 232 - #define IEEE80211_MAX_MPDU_LEN_HT_7935 7935 233 - 234 - #define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895 235 - #define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991 236 - #define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454 237 - 238 242 #define IEEE80211_MAX_SSID_LEN 32 239 - 240 - #define IEEE80211_MAX_MESH_ID_LEN 32 241 243 242 244 #define IEEE80211_FIRST_TSPEC_TSID 8 243 245 #define IEEE80211_NUM_TIDS 16 ··· 275 303 #define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 276 304 #define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 277 305 #define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 278 - 279 - #define IEEE80211_HT_CTL_LEN 4 280 306 281 307 /* trigger type within common_info of trigger frame */ 282 308 #define IEEE80211_TRIGGER_TYPE_MASK 0xf ··· 590 620 } 591 621 592 622 /** 593 - * ieee80211_is_s1g_beacon - check if IEEE80211_FTYPE_EXT && 594 - * IEEE80211_STYPE_S1G_BEACON 595 - * @fc: frame control bytes in little-endian byteorder 596 - * Return: whether or not the frame is an S1G beacon 597 - */ 598 - static inline bool ieee80211_is_s1g_beacon(__le16 fc) 599 - { 600 - return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 601 - IEEE80211_FCTL_STYPE)) == 602 - cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON); 603 - } 604 - 605 - /** 606 - * ieee80211_s1g_has_next_tbtt - check if IEEE80211_S1G_BCN_NEXT_TBTT 607 - * @fc: frame control bytes in little-endian byteorder 608 - * Return: whether or not the frame contains the variable-length 609 - * next TBTT field 610 - */ 611 - static inline bool ieee80211_s1g_has_next_tbtt(__le16 fc) 612 - { 613 - return ieee80211_is_s1g_beacon(fc) && 614 - (fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT)); 615 - } 616 - 617 - /** 618 - * ieee80211_s1g_has_ano - check if IEEE80211_S1G_BCN_ANO 619 - * @fc: frame control bytes in little-endian byteorder 620 - * Return: whether or not the frame contains the variable-length 621 - * ANO field 622 - */ 623 - static inline bool ieee80211_s1g_has_ano(__le16 fc) 624 - { 625 - return ieee80211_is_s1g_beacon(fc) && 626 - (fc & cpu_to_le16(IEEE80211_S1G_BCN_ANO)); 627 - } 628 - 629 - /** 630 - * ieee80211_s1g_has_cssid - check if IEEE80211_S1G_BCN_CSSID 631 - * @fc: frame control bytes in little-endian byteorder 632 - * Return: whether or not the frame contains the variable-length 633 - * compressed SSID field 634 - */ 635 - static inline bool ieee80211_s1g_has_cssid(__le16 fc) 636 - { 637 - return ieee80211_is_s1g_beacon(fc) && 638 - (fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID)); 639 - } 640 - 641 - /** 642 623 * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM 643 624 * @fc: frame control bytes in little-endian byteorder 644 625 * Return: whether or not the frame is an ATIM frame ··· 802 881 return le16_get_bits(hdr->seq_ctrl, IEEE80211_SCTL_SEQ); 803 882 } 804 883 805 - struct ieee80211s_hdr { 806 - u8 flags; 807 - u8 ttl; 808 - __le32 seqnum; 809 - u8 eaddr1[ETH_ALEN]; 810 - u8 eaddr2[ETH_ALEN]; 811 - } __packed __aligned(2); 812 - 813 - /* Mesh flags */ 814 - #define MESH_FLAGS_AE_A4 0x1 815 - #define MESH_FLAGS_AE_A5_A6 0x2 816 - #define MESH_FLAGS_AE 0x3 817 - #define MESH_FLAGS_PS_DEEP 0x4 818 - 819 - /** 820 - * enum ieee80211_preq_flags - mesh PREQ element flags 821 - * 822 - * @IEEE80211_PREQ_PROACTIVE_PREP_FLAG: proactive PREP subfield 823 - */ 824 - enum ieee80211_preq_flags { 825 - IEEE80211_PREQ_PROACTIVE_PREP_FLAG = 1<<2, 826 - }; 827 - 828 - /** 829 - * enum ieee80211_preq_target_flags - mesh PREQ element per target flags 830 - * 831 - * @IEEE80211_PREQ_TO_FLAG: target only subfield 832 - * @IEEE80211_PREQ_USN_FLAG: unknown target HWMP sequence number subfield 833 - */ 834 - enum ieee80211_preq_target_flags { 835 - IEEE80211_PREQ_TO_FLAG = 1<<0, 836 - IEEE80211_PREQ_USN_FLAG = 1<<2, 837 - }; 838 - 839 884 /** 840 885 * struct ieee80211_quiet_ie - Quiet element 841 886 * @count: Quiet Count ··· 881 994 } __packed; 882 995 883 996 /** 884 - * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE 885 - * @mesh_ttl: Time To Live 886 - * @mesh_flags: Flags 887 - * @mesh_reason: Reason Code 888 - * @mesh_pre_value: Precedence Value 889 - * 890 - * This structure represents the payload of the "Mesh Channel Switch 891 - * Parameters element" as described in IEEE Std 802.11-2020 section 892 - * 9.4.2.102. 893 - */ 894 - struct ieee80211_mesh_chansw_params_ie { 895 - u8 mesh_ttl; 896 - u8 mesh_flags; 897 - __le16 mesh_reason; 898 - __le16 mesh_pre_value; 899 - } __packed; 900 - 901 - /** 902 997 * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE 903 998 * @new_channel_width: New Channel Width 904 999 * @new_center_freq_seg0: New Channel Center Frequency Segment 0 ··· 920 1051 }; 921 1052 } __packed; 922 1053 923 - /** 924 - * struct ieee80211_meshconf_ie - Mesh Configuration element 925 - * @meshconf_psel: Active Path Selection Protocol Identifier 926 - * @meshconf_pmetric: Active Path Selection Metric Identifier 927 - * @meshconf_congest: Congestion Control Mode Identifier 928 - * @meshconf_synch: Synchronization Method Identifier 929 - * @meshconf_auth: Authentication Protocol Identifier 930 - * @meshconf_form: Mesh Formation Info 931 - * @meshconf_cap: Mesh Capability (see &enum mesh_config_capab_flags) 932 - * 933 - * This structure represents the payload of the "Mesh Configuration 934 - * element" as described in IEEE Std 802.11-2020 section 9.4.2.97. 935 - */ 936 - struct ieee80211_meshconf_ie { 937 - u8 meshconf_psel; 938 - u8 meshconf_pmetric; 939 - u8 meshconf_congest; 940 - u8 meshconf_synch; 941 - u8 meshconf_auth; 942 - u8 meshconf_form; 943 - u8 meshconf_cap; 944 - } __packed; 945 - 946 - /** 947 - * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags 948 - * 949 - * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish 950 - * additional mesh peerings with other mesh STAs 951 - * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs 952 - * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure 953 - * is ongoing 954 - * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has 955 - * neighbors in deep sleep mode 956 - * 957 - * Enumerates the "Mesh Capability" as described in IEEE Std 958 - * 802.11-2020 section 9.4.2.97.7. 959 - */ 960 - enum mesh_config_capab_flags { 961 - IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01, 962 - IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08, 963 - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20, 964 - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40, 965 - }; 966 - 967 - #define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1 968 - 969 - /* 970 - * mesh channel switch parameters element's flag indicator 971 - * 972 - */ 973 - #define WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT BIT(0) 974 - #define WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR BIT(1) 975 - #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2) 976 - 977 - /** 978 - * struct ieee80211_rann_ie - RANN (root announcement) element 979 - * @rann_flags: Flags 980 - * @rann_hopcount: Hop Count 981 - * @rann_ttl: Element TTL 982 - * @rann_addr: Root Mesh STA Address 983 - * @rann_seq: HWMP Sequence Number 984 - * @rann_interval: Interval 985 - * @rann_metric: Metric 986 - * 987 - * This structure represents the payload of the "RANN element" as 988 - * described in IEEE Std 802.11-2020 section 9.4.2.111. 989 - */ 990 - struct ieee80211_rann_ie { 991 - u8 rann_flags; 992 - u8 rann_hopcount; 993 - u8 rann_ttl; 994 - u8 rann_addr[ETH_ALEN]; 995 - __le32 rann_seq; 996 - __le32 rann_interval; 997 - __le32 rann_metric; 998 - } __packed; 999 - 1000 - enum ieee80211_rann_flags { 1001 - RANN_FLAG_IS_GATE = 1 << 0, 1002 - }; 1003 - 1004 - enum ieee80211_ht_chanwidth_values { 1005 - IEEE80211_HT_CHANWIDTH_20MHZ = 0, 1006 - IEEE80211_HT_CHANWIDTH_ANY = 1, 1007 - }; 1008 - 1009 - /** 1010 - * enum ieee80211_vht_opmode_bits - VHT operating mode field bits 1011 - * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK: channel width mask 1012 - * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: 20 MHz channel width 1013 - * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width 1014 - * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ: 80 MHz channel width 1015 - * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ: 160 MHz or 80+80 MHz channel width 1016 - * @IEEE80211_OPMODE_NOTIF_BW_160_80P80: 160 / 80+80 MHz indicator flag 1017 - * @IEEE80211_OPMODE_NOTIF_RX_NSS_MASK: number of spatial streams mask 1018 - * (the NSS value is the value of this field + 1) 1019 - * @IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT: number of spatial streams shift 1020 - * @IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF: indicates streams in SU-MIMO PPDU 1021 - * using a beamforming steering matrix 1022 - */ 1023 - enum ieee80211_vht_opmode_bits { 1024 - IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK = 0x03, 1025 - IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ = 0, 1026 - IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ = 1, 1027 - IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ = 2, 1028 - IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ = 3, 1029 - IEEE80211_OPMODE_NOTIF_BW_160_80P80 = 0x04, 1030 - IEEE80211_OPMODE_NOTIF_RX_NSS_MASK = 0x70, 1031 - IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4, 1032 - IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF = 0x80, 1033 - }; 1034 - 1035 - /** 1036 - * enum ieee80211_s1g_chanwidth - S1G channel widths 1037 - * These are defined in IEEE802.11-2016ah Table 10-20 1038 - * as BSS Channel Width 1039 - * 1040 - * @IEEE80211_S1G_CHANWIDTH_1MHZ: 1MHz operating channel 1041 - * @IEEE80211_S1G_CHANWIDTH_2MHZ: 2MHz operating channel 1042 - * @IEEE80211_S1G_CHANWIDTH_4MHZ: 4MHz operating channel 1043 - * @IEEE80211_S1G_CHANWIDTH_8MHZ: 8MHz operating channel 1044 - * @IEEE80211_S1G_CHANWIDTH_16MHZ: 16MHz operating channel 1045 - */ 1046 - enum ieee80211_s1g_chanwidth { 1047 - IEEE80211_S1G_CHANWIDTH_1MHZ = 0, 1048 - IEEE80211_S1G_CHANWIDTH_2MHZ = 1, 1049 - IEEE80211_S1G_CHANWIDTH_4MHZ = 3, 1050 - IEEE80211_S1G_CHANWIDTH_8MHZ = 7, 1051 - IEEE80211_S1G_CHANWIDTH_16MHZ = 15, 1052 - }; 1053 - 1054 - /** 1055 - * enum ieee80211_s1g_pri_chanwidth - S1G primary channel widths 1056 - * described in IEEE80211-2024 Table 10-39. 1057 - * 1058 - * @IEEE80211_S1G_PRI_CHANWIDTH_2MHZ: 2MHz primary channel 1059 - * @IEEE80211_S1G_PRI_CHANWIDTH_1MHZ: 1MHz primary channel 1060 - */ 1061 - enum ieee80211_s1g_pri_chanwidth { 1062 - IEEE80211_S1G_PRI_CHANWIDTH_2MHZ = 0, 1063 - IEEE80211_S1G_PRI_CHANWIDTH_1MHZ = 1, 1064 - }; 1065 - 1066 1054 #define WLAN_SA_QUERY_TR_ID_LEN 2 1067 1055 #define WLAN_MEMBERSHIP_LEN 8 1068 1056 #define WLAN_USER_POSITION_LEN 16 ··· 947 1221 u8 data; 948 1222 } __packed; 949 1223 950 - /** 951 - * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element 952 - * @compat_info: Compatibility Information 953 - * @beacon_int: Beacon Interval 954 - * @tsf_completion: TSF Completion 955 - * 956 - * This structure represents the payload of the "S1G Beacon 957 - * Compatibility element" as described in IEEE Std 802.11-2020 section 958 - * 9.4.2.196. 959 - */ 960 - struct ieee80211_s1g_bcn_compat_ie { 961 - __le16 compat_info; 962 - __le16 beacon_int; 963 - __le32 tsf_completion; 964 - } __packed; 965 - 966 - /** 967 - * struct ieee80211_s1g_oper_ie - S1G Operation element 968 - * @ch_width: S1G Operation Information Channel Width 969 - * @oper_class: S1G Operation Information Operating Class 970 - * @primary_ch: S1G Operation Information Primary Channel Number 971 - * @oper_ch: S1G Operation Information Channel Center Frequency 972 - * @basic_mcs_nss: Basic S1G-MCS and NSS Set 973 - * 974 - * This structure represents the payload of the "S1G Operation 975 - * element" as described in IEEE Std 802.11-2020 section 9.4.2.212. 976 - */ 977 - struct ieee80211_s1g_oper_ie { 978 - u8 ch_width; 979 - u8 oper_class; 980 - u8 primary_ch; 981 - u8 oper_ch; 982 - __le16 basic_mcs_nss; 983 - } __packed; 984 - 985 - /** 986 - * struct ieee80211_aid_response_ie - AID Response element 987 - * @aid: AID/Group AID 988 - * @switch_count: AID Switch Count 989 - * @response_int: AID Response Interval 990 - * 991 - * This structure represents the payload of the "AID Response element" 992 - * as described in IEEE Std 802.11-2020 section 9.4.2.194. 993 - */ 994 - struct ieee80211_aid_response_ie { 995 - __le16 aid; 996 - u8 switch_count; 997 - __le16 response_int; 998 - } __packed; 999 - 1000 - struct ieee80211_s1g_cap { 1001 - u8 capab_info[10]; 1002 - u8 supp_mcs_nss[5]; 1003 - } __packed; 1004 - 1005 1224 struct ieee80211_ext { 1006 1225 __le16 frame_control; 1007 1226 __le16 duration; ··· 959 1288 } __packed s1g_beacon; 960 1289 } u; 961 1290 } __packed __aligned(2); 962 - 963 - /** 964 - * ieee80211_s1g_optional_len - determine length of optional S1G beacon fields 965 - * @fc: frame control bytes in little-endian byteorder 966 - * Return: total length in bytes of the optional fixed-length fields 967 - * 968 - * S1G beacons may contain up to three optional fixed-length fields that 969 - * precede the variable-length elements. Whether these fields are present 970 - * is indicated by flags in the frame control field. 971 - * 972 - * From IEEE 802.11-2024 section 9.3.4.3: 973 - * - Next TBTT field may be 0 or 3 bytes 974 - * - Short SSID field may be 0 or 4 bytes 975 - * - Access Network Options (ANO) field may be 0 or 1 byte 976 - */ 977 - static inline size_t 978 - ieee80211_s1g_optional_len(__le16 fc) 979 - { 980 - size_t len = 0; 981 - 982 - if (ieee80211_s1g_has_next_tbtt(fc)) 983 - len += 3; 984 - 985 - if (ieee80211_s1g_has_cssid(fc)) 986 - len += 4; 987 - 988 - if (ieee80211_s1g_has_ano(fc)) 989 - len += 1; 990 - 991 - return len; 992 - } 993 - 994 - #define IEEE80211_TWT_CONTROL_NDP BIT(0) 995 - #define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1) 996 - #define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) 997 - #define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) 998 - #define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) 999 - 1000 - #define IEEE80211_TWT_REQTYPE_REQUEST BIT(0) 1001 - #define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1) 1002 - #define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) 1003 - #define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) 1004 - #define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) 1005 - #define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7) 1006 - #define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10) 1007 - #define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) 1008 - 1009 - enum ieee80211_twt_setup_cmd { 1010 - TWT_SETUP_CMD_REQUEST, 1011 - TWT_SETUP_CMD_SUGGEST, 1012 - TWT_SETUP_CMD_DEMAND, 1013 - TWT_SETUP_CMD_GROUPING, 1014 - TWT_SETUP_CMD_ACCEPT, 1015 - TWT_SETUP_CMD_ALTERNATE, 1016 - TWT_SETUP_CMD_DICTATE, 1017 - TWT_SETUP_CMD_REJECT, 1018 - }; 1019 - 1020 - struct ieee80211_twt_params { 1021 - __le16 req_type; 1022 - __le64 twt; 1023 - u8 min_twt_dur; 1024 - __le16 mantissa; 1025 - u8 channel; 1026 - } __packed; 1027 - 1028 - struct ieee80211_twt_setup { 1029 - u8 dialog_token; 1030 - u8 element_id; 1031 - u8 length; 1032 - u8 control; 1033 - u8 params[]; 1034 - } __packed; 1035 - 1036 - #define IEEE80211_TTLM_MAX_CNT 2 1037 - #define IEEE80211_TTLM_CONTROL_DIRECTION 0x03 1038 - #define IEEE80211_TTLM_CONTROL_DEF_LINK_MAP 0x04 1039 - #define IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT 0x08 1040 - #define IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT 0x10 1041 - #define IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE 0x20 1042 - 1043 - #define IEEE80211_TTLM_DIRECTION_DOWN 0 1044 - #define IEEE80211_TTLM_DIRECTION_UP 1 1045 - #define IEEE80211_TTLM_DIRECTION_BOTH 2 1046 - 1047 - /** 1048 - * struct ieee80211_ttlm_elem - TID-To-Link Mapping element 1049 - * 1050 - * Defined in section 9.4.2.314 in P802.11be_D4 1051 - * 1052 - * @control: the first part of control field 1053 - * @optional: the second part of control field 1054 - */ 1055 - struct ieee80211_ttlm_elem { 1056 - u8 control; 1057 - u8 optional[]; 1058 - } __packed; 1059 1291 1060 1292 /** 1061 1293 * struct ieee80211_bss_load_elem - BSS Load elemen ··· 1333 1759 } __packed chan_switch_resp; 1334 1760 } u; 1335 1761 } __packed; 1336 - 1337 - /* 1338 - * Peer-to-Peer IE attribute related definitions. 1339 - */ 1340 - /* 1341 - * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute. 1342 - */ 1343 - enum ieee80211_p2p_attr_id { 1344 - IEEE80211_P2P_ATTR_STATUS = 0, 1345 - IEEE80211_P2P_ATTR_MINOR_REASON, 1346 - IEEE80211_P2P_ATTR_CAPABILITY, 1347 - IEEE80211_P2P_ATTR_DEVICE_ID, 1348 - IEEE80211_P2P_ATTR_GO_INTENT, 1349 - IEEE80211_P2P_ATTR_GO_CONFIG_TIMEOUT, 1350 - IEEE80211_P2P_ATTR_LISTEN_CHANNEL, 1351 - IEEE80211_P2P_ATTR_GROUP_BSSID, 1352 - IEEE80211_P2P_ATTR_EXT_LISTEN_TIMING, 1353 - IEEE80211_P2P_ATTR_INTENDED_IFACE_ADDR, 1354 - IEEE80211_P2P_ATTR_MANAGABILITY, 1355 - IEEE80211_P2P_ATTR_CHANNEL_LIST, 1356 - IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 1357 - IEEE80211_P2P_ATTR_DEVICE_INFO, 1358 - IEEE80211_P2P_ATTR_GROUP_INFO, 1359 - IEEE80211_P2P_ATTR_GROUP_ID, 1360 - IEEE80211_P2P_ATTR_INTERFACE, 1361 - IEEE80211_P2P_ATTR_OPER_CHANNEL, 1362 - IEEE80211_P2P_ATTR_INVITE_FLAGS, 1363 - /* 19 - 220: Reserved */ 1364 - IEEE80211_P2P_ATTR_VENDOR_SPECIFIC = 221, 1365 - 1366 - IEEE80211_P2P_ATTR_MAX 1367 - }; 1368 - 1369 - /* Notice of Absence attribute - described in P2P spec 4.1.14 */ 1370 - /* Typical max value used here */ 1371 - #define IEEE80211_P2P_NOA_DESC_MAX 4 1372 - 1373 - struct ieee80211_p2p_noa_desc { 1374 - u8 count; 1375 - __le32 duration; 1376 - __le32 interval; 1377 - __le32 start_time; 1378 - } __packed; 1379 - 1380 - struct ieee80211_p2p_noa_attr { 1381 - u8 index; 1382 - u8 oppps_ctwindow; 1383 - struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX]; 1384 - } __packed; 1385 - 1386 - #define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7) 1387 - #define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F 1388 - 1389 - /** 1390 - * struct ieee80211_bar - Block Ack Request frame format 1391 - * @frame_control: Frame Control 1392 - * @duration: Duration 1393 - * @ra: RA 1394 - * @ta: TA 1395 - * @control: BAR Control 1396 - * @start_seq_num: Starting Sequence Number (see Figure 9-37) 1397 - * 1398 - * This structure represents the "BlockAckReq frame format" 1399 - * as described in IEEE Std 802.11-2020 section 9.3.1.7. 1400 - */ 1401 - struct ieee80211_bar { 1402 - __le16 frame_control; 1403 - __le16 duration; 1404 - __u8 ra[ETH_ALEN]; 1405 - __u8 ta[ETH_ALEN]; 1406 - __le16 control; 1407 - __le16 start_seq_num; 1408 - } __packed; 1409 - 1410 - /* 802.11 BAR control masks */ 1411 - #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 1412 - #define IEEE80211_BAR_CTRL_MULTI_TID 0x0002 1413 - #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 1414 - #define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 1415 - #define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 1416 - 1417 - #define IEEE80211_HT_MCS_MASK_LEN 10 1418 - 1419 - /** 1420 - * struct ieee80211_mcs_info - Supported MCS Set field 1421 - * @rx_mask: RX mask 1422 - * @rx_highest: highest supported RX rate. If set represents 1423 - * the highest supported RX data rate in units of 1 Mbps. 1424 - * If this field is 0 this value should not be used to 1425 - * consider the highest RX data rate supported. 1426 - * @tx_params: TX parameters 1427 - * @reserved: Reserved bits 1428 - * 1429 - * This structure represents the "Supported MCS Set field" as 1430 - * described in IEEE Std 802.11-2020 section 9.4.2.55.4. 1431 - */ 1432 - struct ieee80211_mcs_info { 1433 - u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; 1434 - __le16 rx_highest; 1435 - u8 tx_params; 1436 - u8 reserved[3]; 1437 - } __packed; 1438 - 1439 - /* 802.11n HT capability MSC set */ 1440 - #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff 1441 - #define IEEE80211_HT_MCS_TX_DEFINED 0x01 1442 - #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 1443 - /* value 0 == 1 stream etc */ 1444 - #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C 1445 - #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 1446 - #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 1447 - #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 1448 - 1449 - #define IEEE80211_HT_MCS_CHAINS(mcs) ((mcs) == 32 ? 1 : (1 + ((mcs) >> 3))) 1450 - 1451 - /* 1452 - * 802.11n D5.0 20.3.5 / 20.6 says: 1453 - * - indices 0 to 7 and 32 are single spatial stream 1454 - * - 8 to 31 are multiple spatial streams using equal modulation 1455 - * [8..15 for two streams, 16..23 for three and 24..31 for four] 1456 - * - remainder are multiple spatial streams using unequal modulation 1457 - */ 1458 - #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 1459 - #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ 1460 - (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) 1461 - 1462 - /** 1463 - * struct ieee80211_ht_cap - HT capabilities element 1464 - * @cap_info: HT Capability Information 1465 - * @ampdu_params_info: A-MPDU Parameters 1466 - * @mcs: Supported MCS Set 1467 - * @extended_ht_cap_info: HT Extended Capabilities 1468 - * @tx_BF_cap_info: Transmit Beamforming Capabilities 1469 - * @antenna_selection_info: ASEL Capability 1470 - * 1471 - * This structure represents the payload of the "HT Capabilities 1472 - * element" as described in IEEE Std 802.11-2020 section 9.4.2.55. 1473 - */ 1474 - struct ieee80211_ht_cap { 1475 - __le16 cap_info; 1476 - u8 ampdu_params_info; 1477 - 1478 - /* 16 bytes MCS information */ 1479 - struct ieee80211_mcs_info mcs; 1480 - 1481 - __le16 extended_ht_cap_info; 1482 - __le32 tx_BF_cap_info; 1483 - u8 antenna_selection_info; 1484 - } __packed; 1485 - 1486 - /* 802.11n HT capabilities masks (for cap_info) */ 1487 - #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 1488 - #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 1489 - #define IEEE80211_HT_CAP_SM_PS 0x000C 1490 - #define IEEE80211_HT_CAP_SM_PS_SHIFT 2 1491 - #define IEEE80211_HT_CAP_GRN_FLD 0x0010 1492 - #define IEEE80211_HT_CAP_SGI_20 0x0020 1493 - #define IEEE80211_HT_CAP_SGI_40 0x0040 1494 - #define IEEE80211_HT_CAP_TX_STBC 0x0080 1495 - #define IEEE80211_HT_CAP_RX_STBC 0x0300 1496 - #define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 1497 - #define IEEE80211_HT_CAP_DELAY_BA 0x0400 1498 - #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 1499 - #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 1500 - #define IEEE80211_HT_CAP_RESERVED 0x2000 1501 - #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 1502 - #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 1503 - 1504 - /* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ 1505 - #define IEEE80211_HT_EXT_CAP_PCO 0x0001 1506 - #define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 1507 - #define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 1508 - #define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 1509 - #define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 1510 - #define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 1511 - #define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 1512 - 1513 - /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ 1514 - #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 1515 - #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C 1516 - #define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 1517 - 1518 - /* 1519 - * Maximum length of AMPDU that the STA can receive in high-throughput (HT). 1520 - * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) 1521 - */ 1522 - enum ieee80211_max_ampdu_length_exp { 1523 - IEEE80211_HT_MAX_AMPDU_8K = 0, 1524 - IEEE80211_HT_MAX_AMPDU_16K = 1, 1525 - IEEE80211_HT_MAX_AMPDU_32K = 2, 1526 - IEEE80211_HT_MAX_AMPDU_64K = 3 1527 - }; 1528 - 1529 - /* 1530 - * Maximum length of AMPDU that the STA can receive in VHT. 1531 - * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) 1532 - */ 1533 - enum ieee80211_vht_max_ampdu_length_exp { 1534 - IEEE80211_VHT_MAX_AMPDU_8K = 0, 1535 - IEEE80211_VHT_MAX_AMPDU_16K = 1, 1536 - IEEE80211_VHT_MAX_AMPDU_32K = 2, 1537 - IEEE80211_VHT_MAX_AMPDU_64K = 3, 1538 - IEEE80211_VHT_MAX_AMPDU_128K = 4, 1539 - IEEE80211_VHT_MAX_AMPDU_256K = 5, 1540 - IEEE80211_VHT_MAX_AMPDU_512K = 6, 1541 - IEEE80211_VHT_MAX_AMPDU_1024K = 7 1542 - }; 1543 - 1544 - #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 1545 - 1546 - /* Minimum MPDU start spacing */ 1547 - enum ieee80211_min_mpdu_spacing { 1548 - IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ 1549 - IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ 1550 - IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ 1551 - IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ 1552 - IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ 1553 - IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ 1554 - IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ 1555 - IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ 1556 - }; 1557 - 1558 - /** 1559 - * struct ieee80211_ht_operation - HT operation IE 1560 - * @primary_chan: Primary Channel 1561 - * @ht_param: HT Operation Information parameters 1562 - * @operation_mode: HT Operation Information operation mode 1563 - * @stbc_param: HT Operation Information STBC params 1564 - * @basic_set: Basic HT-MCS Set 1565 - * 1566 - * This structure represents the payload of the "HT Operation 1567 - * element" as described in IEEE Std 802.11-2020 section 9.4.2.56. 1568 - */ 1569 - struct ieee80211_ht_operation { 1570 - u8 primary_chan; 1571 - u8 ht_param; 1572 - __le16 operation_mode; 1573 - __le16 stbc_param; 1574 - u8 basic_set[16]; 1575 - } __packed; 1576 - 1577 - /* for ht_param */ 1578 - #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 1579 - #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 1580 - #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 1581 - #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 1582 - #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 1583 - #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 1584 - 1585 - /* for operation_mode */ 1586 - #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 1587 - #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 1588 - #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 1589 - #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 1590 - #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 1591 - #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 1592 - #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 1593 - #define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5 1594 - #define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0 1595 - 1596 - /* for stbc_param */ 1597 - #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 1598 - #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 1599 - #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 1600 - #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 1601 - #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 1602 - #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 1603 - 1604 - 1605 - /* block-ack parameters */ 1606 - #define IEEE80211_ADDBA_PARAM_AMSDU_MASK 0x0001 1607 - #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 1608 - #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C 1609 - #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 1610 - #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 1611 - #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 1612 - 1613 - /* 1614 - * A-MPDU buffer sizes 1615 - * According to HT size varies from 8 to 64 frames 1616 - * HE adds the ability to have up to 256 frames. 1617 - * EHT adds the ability to have up to 1K frames. 1618 - */ 1619 - #define IEEE80211_MIN_AMPDU_BUF 0x8 1620 - #define IEEE80211_MAX_AMPDU_BUF_HT 0x40 1621 - #define IEEE80211_MAX_AMPDU_BUF_HE 0x100 1622 - #define IEEE80211_MAX_AMPDU_BUF_EHT 0x400 1623 - 1624 - 1625 - /* Spatial Multiplexing Power Save Modes (for capability) */ 1626 - #define WLAN_HT_CAP_SM_PS_STATIC 0 1627 - #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 1628 - #define WLAN_HT_CAP_SM_PS_INVALID 2 1629 - #define WLAN_HT_CAP_SM_PS_DISABLED 3 1630 - 1631 - /* for SM power control field lower two bits */ 1632 - #define WLAN_HT_SMPS_CONTROL_DISABLED 0 1633 - #define WLAN_HT_SMPS_CONTROL_STATIC 1 1634 - #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 1635 - 1636 - /** 1637 - * struct ieee80211_vht_mcs_info - VHT MCS information 1638 - * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams 1639 - * @rx_highest: Indicates highest long GI VHT PPDU data rate 1640 - * STA can receive. Rate expressed in units of 1 Mbps. 1641 - * If this field is 0 this value should not be used to 1642 - * consider the highest RX data rate supported. 1643 - * The top 3 bits of this field indicate the Maximum NSTS,total 1644 - * (a beamformee capability.) 1645 - * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams 1646 - * @tx_highest: Indicates highest long GI VHT PPDU data rate 1647 - * STA can transmit. Rate expressed in units of 1 Mbps. 1648 - * If this field is 0 this value should not be used to 1649 - * consider the highest TX data rate supported. 1650 - * The top 2 bits of this field are reserved, the 1651 - * 3rd bit from the top indiciates VHT Extended NSS BW 1652 - * Capability. 1653 - */ 1654 - struct ieee80211_vht_mcs_info { 1655 - __le16 rx_mcs_map; 1656 - __le16 rx_highest; 1657 - __le16 tx_mcs_map; 1658 - __le16 tx_highest; 1659 - } __packed; 1660 - 1661 - /* for rx_highest */ 1662 - #define IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT 13 1663 - #define IEEE80211_VHT_MAX_NSTS_TOTAL_MASK (7 << IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT) 1664 - 1665 - /* for tx_highest */ 1666 - #define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13) 1667 - 1668 - /** 1669 - * enum ieee80211_vht_mcs_support - VHT MCS support definitions 1670 - * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the 1671 - * number of streams 1672 - * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported 1673 - * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported 1674 - * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported 1675 - * 1676 - * These definitions are used in each 2-bit subfield of the @rx_mcs_map 1677 - * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are 1678 - * both split into 8 subfields by number of streams. These values indicate 1679 - * which MCSes are supported for the number of streams the value appears 1680 - * for. 1681 - */ 1682 - enum ieee80211_vht_mcs_support { 1683 - IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, 1684 - IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, 1685 - IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, 1686 - IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, 1687 - }; 1688 - 1689 - /** 1690 - * struct ieee80211_vht_cap - VHT capabilities 1691 - * 1692 - * This structure is the "VHT capabilities element" as 1693 - * described in 802.11ac D3.0 8.4.2.160 1694 - * @vht_cap_info: VHT capability info 1695 - * @supp_mcs: VHT MCS supported rates 1696 - */ 1697 - struct ieee80211_vht_cap { 1698 - __le32 vht_cap_info; 1699 - struct ieee80211_vht_mcs_info supp_mcs; 1700 - } __packed; 1701 - 1702 - /** 1703 - * enum ieee80211_vht_chanwidth - VHT channel width 1704 - * @IEEE80211_VHT_CHANWIDTH_USE_HT: use the HT operation IE to 1705 - * determine the channel width (20 or 40 MHz) 1706 - * @IEEE80211_VHT_CHANWIDTH_80MHZ: 80 MHz bandwidth 1707 - * @IEEE80211_VHT_CHANWIDTH_160MHZ: 160 MHz bandwidth 1708 - * @IEEE80211_VHT_CHANWIDTH_80P80MHZ: 80+80 MHz bandwidth 1709 - */ 1710 - enum ieee80211_vht_chanwidth { 1711 - IEEE80211_VHT_CHANWIDTH_USE_HT = 0, 1712 - IEEE80211_VHT_CHANWIDTH_80MHZ = 1, 1713 - IEEE80211_VHT_CHANWIDTH_160MHZ = 2, 1714 - IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, 1715 - }; 1716 - 1717 - /** 1718 - * struct ieee80211_vht_operation - VHT operation IE 1719 - * 1720 - * This structure is the "VHT operation element" as 1721 - * described in 802.11ac D3.0 8.4.2.161 1722 - * @chan_width: Operating channel width 1723 - * @center_freq_seg0_idx: center freq segment 0 index 1724 - * @center_freq_seg1_idx: center freq segment 1 index 1725 - * @basic_mcs_set: VHT Basic MCS rate set 1726 - */ 1727 - struct ieee80211_vht_operation { 1728 - u8 chan_width; 1729 - u8 center_freq_seg0_idx; 1730 - u8 center_freq_seg1_idx; 1731 - __le16 basic_mcs_set; 1732 - } __packed; 1733 - 1734 - /** 1735 - * struct ieee80211_he_cap_elem - HE capabilities element 1736 - * @mac_cap_info: HE MAC Capabilities Information 1737 - * @phy_cap_info: HE PHY Capabilities Information 1738 - * 1739 - * This structure represents the fixed fields of the payload of the 1740 - * "HE capabilities element" as described in IEEE Std 802.11ax-2021 1741 - * sections 9.4.2.248.2 and 9.4.2.248.3. 1742 - */ 1743 - struct ieee80211_he_cap_elem { 1744 - u8 mac_cap_info[6]; 1745 - u8 phy_cap_info[11]; 1746 - } __packed; 1747 - 1748 - #define IEEE80211_TX_RX_MCS_NSS_DESC_MAX_LEN 5 1749 - 1750 - /** 1751 - * enum ieee80211_he_mcs_support - HE MCS support definitions 1752 - * @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the 1753 - * number of streams 1754 - * @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported 1755 - * @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported 1756 - * @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported 1757 - * 1758 - * These definitions are used in each 2-bit subfield of the rx_mcs_* 1759 - * and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are 1760 - * both split into 8 subfields by number of streams. These values indicate 1761 - * which MCSes are supported for the number of streams the value appears 1762 - * for. 1763 - */ 1764 - enum ieee80211_he_mcs_support { 1765 - IEEE80211_HE_MCS_SUPPORT_0_7 = 0, 1766 - IEEE80211_HE_MCS_SUPPORT_0_9 = 1, 1767 - IEEE80211_HE_MCS_SUPPORT_0_11 = 2, 1768 - IEEE80211_HE_MCS_NOT_SUPPORTED = 3, 1769 - }; 1770 - 1771 - /** 1772 - * struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field 1773 - * 1774 - * This structure holds the data required for the Tx/Rx HE MCS NSS Support Field 1775 - * described in P802.11ax_D2.0 section 9.4.2.237.4 1776 - * 1777 - * @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel 1778 - * widths less than 80MHz. 1779 - * @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel 1780 - * widths less than 80MHz. 1781 - * @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel 1782 - * width 160MHz. 1783 - * @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel 1784 - * width 160MHz. 1785 - * @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for 1786 - * channel width 80p80MHz. 1787 - * @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for 1788 - * channel width 80p80MHz. 1789 - */ 1790 - struct ieee80211_he_mcs_nss_supp { 1791 - __le16 rx_mcs_80; 1792 - __le16 tx_mcs_80; 1793 - __le16 rx_mcs_160; 1794 - __le16 tx_mcs_160; 1795 - __le16 rx_mcs_80p80; 1796 - __le16 tx_mcs_80p80; 1797 - } __packed; 1798 - 1799 - /** 1800 - * struct ieee80211_he_operation - HE Operation element 1801 - * @he_oper_params: HE Operation Parameters + BSS Color Information 1802 - * @he_mcs_nss_set: Basic HE-MCS And NSS Set 1803 - * @optional: Optional fields VHT Operation Information, Max Co-Hosted 1804 - * BSSID Indicator, and 6 GHz Operation Information 1805 - * 1806 - * This structure represents the payload of the "HE Operation 1807 - * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.249. 1808 - */ 1809 - struct ieee80211_he_operation { 1810 - __le32 he_oper_params; 1811 - __le16 he_mcs_nss_set; 1812 - u8 optional[]; 1813 - } __packed; 1814 - 1815 - /** 1816 - * struct ieee80211_he_spr - Spatial Reuse Parameter Set element 1817 - * @he_sr_control: SR Control 1818 - * @optional: Optional fields Non-SRG OBSS PD Max Offset, SRG OBSS PD 1819 - * Min Offset, SRG OBSS PD Max Offset, SRG BSS Color 1820 - * Bitmap, and SRG Partial BSSID Bitmap 1821 - * 1822 - * This structure represents the payload of the "Spatial Reuse 1823 - * Parameter Set element" as described in IEEE Std 802.11ax-2021 1824 - * section 9.4.2.252. 1825 - */ 1826 - struct ieee80211_he_spr { 1827 - u8 he_sr_control; 1828 - u8 optional[]; 1829 - } __packed; 1830 - 1831 - /** 1832 - * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field 1833 - * @aifsn: ACI/AIFSN 1834 - * @ecw_min_max: ECWmin/ECWmax 1835 - * @mu_edca_timer: MU EDCA Timer 1836 - * 1837 - * This structure represents the "MU AC Parameter Record" as described 1838 - * in IEEE Std 802.11ax-2021 section 9.4.2.251, Figure 9-788p. 1839 - */ 1840 - struct ieee80211_he_mu_edca_param_ac_rec { 1841 - u8 aifsn; 1842 - u8 ecw_min_max; 1843 - u8 mu_edca_timer; 1844 - } __packed; 1845 - 1846 - /** 1847 - * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element 1848 - * @mu_qos_info: QoS Info 1849 - * @ac_be: MU AC_BE Parameter Record 1850 - * @ac_bk: MU AC_BK Parameter Record 1851 - * @ac_vi: MU AC_VI Parameter Record 1852 - * @ac_vo: MU AC_VO Parameter Record 1853 - * 1854 - * This structure represents the payload of the "MU EDCA Parameter Set 1855 - * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.251. 1856 - */ 1857 - struct ieee80211_mu_edca_param_set { 1858 - u8 mu_qos_info; 1859 - struct ieee80211_he_mu_edca_param_ac_rec ac_be; 1860 - struct ieee80211_he_mu_edca_param_ac_rec ac_bk; 1861 - struct ieee80211_he_mu_edca_param_ac_rec ac_vi; 1862 - struct ieee80211_he_mu_edca_param_ac_rec ac_vo; 1863 - } __packed; 1864 - 1865 - #define IEEE80211_EHT_MCS_NSS_RX 0x0f 1866 - #define IEEE80211_EHT_MCS_NSS_TX 0xf0 1867 - 1868 - /** 1869 - * struct ieee80211_eht_mcs_nss_supp_20mhz_only - EHT 20MHz only station max 1870 - * supported NSS for per MCS. 1871 - * 1872 - * For each field below, bits 0 - 3 indicate the maximal number of spatial 1873 - * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams 1874 - * for Tx. 1875 - * 1876 - * @rx_tx_mcs7_max_nss: indicates the maximum number of spatial streams 1877 - * supported for reception and the maximum number of spatial streams 1878 - * supported for transmission for MCS 0 - 7. 1879 - * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams 1880 - * supported for reception and the maximum number of spatial streams 1881 - * supported for transmission for MCS 8 - 9. 1882 - * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams 1883 - * supported for reception and the maximum number of spatial streams 1884 - * supported for transmission for MCS 10 - 11. 1885 - * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams 1886 - * supported for reception and the maximum number of spatial streams 1887 - * supported for transmission for MCS 12 - 13. 1888 - * @rx_tx_max_nss: array of the previous fields for easier loop access 1889 - */ 1890 - struct ieee80211_eht_mcs_nss_supp_20mhz_only { 1891 - union { 1892 - struct { 1893 - u8 rx_tx_mcs7_max_nss; 1894 - u8 rx_tx_mcs9_max_nss; 1895 - u8 rx_tx_mcs11_max_nss; 1896 - u8 rx_tx_mcs13_max_nss; 1897 - }; 1898 - u8 rx_tx_max_nss[4]; 1899 - }; 1900 - }; 1901 - 1902 - /** 1903 - * struct ieee80211_eht_mcs_nss_supp_bw - EHT max supported NSS per MCS (except 1904 - * 20MHz only stations). 1905 - * 1906 - * For each field below, bits 0 - 3 indicate the maximal number of spatial 1907 - * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams 1908 - * for Tx. 1909 - * 1910 - * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams 1911 - * supported for reception and the maximum number of spatial streams 1912 - * supported for transmission for MCS 0 - 9. 1913 - * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams 1914 - * supported for reception and the maximum number of spatial streams 1915 - * supported for transmission for MCS 10 - 11. 1916 - * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams 1917 - * supported for reception and the maximum number of spatial streams 1918 - * supported for transmission for MCS 12 - 13. 1919 - * @rx_tx_max_nss: array of the previous fields for easier loop access 1920 - */ 1921 - struct ieee80211_eht_mcs_nss_supp_bw { 1922 - union { 1923 - struct { 1924 - u8 rx_tx_mcs9_max_nss; 1925 - u8 rx_tx_mcs11_max_nss; 1926 - u8 rx_tx_mcs13_max_nss; 1927 - }; 1928 - u8 rx_tx_max_nss[3]; 1929 - }; 1930 - }; 1931 - 1932 - /** 1933 - * struct ieee80211_eht_cap_elem_fixed - EHT capabilities fixed data 1934 - * 1935 - * This structure is the "EHT Capabilities element" fixed fields as 1936 - * described in P802.11be_D2.0 section 9.4.2.313. 1937 - * 1938 - * @mac_cap_info: MAC capabilities, see IEEE80211_EHT_MAC_CAP* 1939 - * @phy_cap_info: PHY capabilities, see IEEE80211_EHT_PHY_CAP* 1940 - */ 1941 - struct ieee80211_eht_cap_elem_fixed { 1942 - u8 mac_cap_info[2]; 1943 - u8 phy_cap_info[9]; 1944 - } __packed; 1945 - 1946 - /** 1947 - * struct ieee80211_eht_cap_elem - EHT capabilities element 1948 - * @fixed: fixed parts, see &ieee80211_eht_cap_elem_fixed 1949 - * @optional: optional parts 1950 - */ 1951 - struct ieee80211_eht_cap_elem { 1952 - struct ieee80211_eht_cap_elem_fixed fixed; 1953 - 1954 - /* 1955 - * Followed by: 1956 - * Supported EHT-MCS And NSS Set field: 4, 3, 6 or 9 octets. 1957 - * EHT PPE Thresholds field: variable length. 1958 - */ 1959 - u8 optional[]; 1960 - } __packed; 1961 - 1962 - #define IEEE80211_EHT_OPER_INFO_PRESENT 0x01 1963 - #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x02 1964 - #define IEEE80211_EHT_OPER_EHT_DEF_PE_DURATION 0x04 1965 - #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_LIMIT 0x08 1966 - #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_EXP_MASK 0x30 1967 - #define IEEE80211_EHT_OPER_MCS15_DISABLE 0x40 1968 - 1969 - /** 1970 - * struct ieee80211_eht_operation - eht operation element 1971 - * 1972 - * This structure is the "EHT Operation Element" fields as 1973 - * described in P802.11be_D2.0 section 9.4.2.311 1974 - * 1975 - * @params: EHT operation element parameters. See &IEEE80211_EHT_OPER_* 1976 - * @basic_mcs_nss: indicates the EHT-MCSs for each number of spatial streams in 1977 - * EHT PPDUs that are supported by all EHT STAs in the BSS in transmit and 1978 - * receive. 1979 - * @optional: optional parts 1980 - */ 1981 - struct ieee80211_eht_operation { 1982 - u8 params; 1983 - struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss; 1984 - u8 optional[]; 1985 - } __packed; 1986 - 1987 - /** 1988 - * struct ieee80211_eht_operation_info - eht operation information 1989 - * 1990 - * @control: EHT operation information control. 1991 - * @ccfs0: defines a channel center frequency for a 20, 40, 80, 160, or 320 MHz 1992 - * EHT BSS. 1993 - * @ccfs1: defines a channel center frequency for a 160 or 320 MHz EHT BSS. 1994 - * @optional: optional parts 1995 - */ 1996 - struct ieee80211_eht_operation_info { 1997 - u8 control; 1998 - u8 ccfs0; 1999 - u8 ccfs1; 2000 - u8 optional[]; 2001 - } __packed; 2002 - 2003 - /* 802.11ac VHT Capabilities */ 2004 - #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 2005 - #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 2006 - #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 2007 - #define IEEE80211_VHT_CAP_MAX_MPDU_MASK 0x00000003 2008 - #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 2009 - #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 2010 - #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x0000000C 2011 - #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT 2 2012 - #define IEEE80211_VHT_CAP_RXLDPC 0x00000010 2013 - #define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 2014 - #define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 2015 - #define IEEE80211_VHT_CAP_TXSTBC 0x00000080 2016 - #define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 2017 - #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 2018 - #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 2019 - #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 2020 - #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 2021 - #define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8 2022 - #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 2023 - #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 2024 - #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 2025 - #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK \ 2026 - (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) 2027 - #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 2028 - #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \ 2029 - (7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) 2030 - #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 2031 - #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 2032 - #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 2033 - #define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 2034 - #define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 2035 - #define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ 2036 - (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) 2037 - #define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 2038 - #define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 2039 - #define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 2040 - #define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 2041 - #define IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT 30 2042 - #define IEEE80211_VHT_CAP_EXT_NSS_BW_MASK 0xc0000000 2043 - 2044 - /** 2045 - * ieee80211_get_vht_max_nss - return max NSS for a given bandwidth/MCS 2046 - * @cap: VHT capabilities of the peer 2047 - * @bw: bandwidth to use 2048 - * @mcs: MCS index to use 2049 - * @ext_nss_bw_capable: indicates whether or not the local transmitter 2050 - * (rate scaling algorithm) can deal with the new logic 2051 - * (dot11VHTExtendedNSSBWCapable) 2052 - * @max_vht_nss: current maximum NSS as advertised by the STA in 2053 - * operating mode notification, can be 0 in which case the 2054 - * capability data will be used to derive this (from MCS support) 2055 - * Return: The maximum NSS that can be used for the given bandwidth/MCS 2056 - * combination 2057 - * 2058 - * Due to the VHT Extended NSS Bandwidth Support, the maximum NSS can 2059 - * vary for a given BW/MCS. This function parses the data. 2060 - * 2061 - * Note: This function is exported by cfg80211. 2062 - */ 2063 - int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, 2064 - enum ieee80211_vht_chanwidth bw, 2065 - int mcs, bool ext_nss_bw_capable, 2066 - unsigned int max_vht_nss); 2067 - 2068 - /* 802.11ax HE MAC capabilities */ 2069 - #define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01 2070 - #define IEEE80211_HE_MAC_CAP0_TWT_REQ 0x02 2071 - #define IEEE80211_HE_MAC_CAP0_TWT_RES 0x04 2072 - #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_NOT_SUPP 0x00 2073 - #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_1 0x08 2074 - #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_2 0x10 2075 - #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_3 0x18 2076 - #define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK 0x18 2077 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_1 0x00 2078 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_2 0x20 2079 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_4 0x40 2080 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_8 0x60 2081 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_16 0x80 2082 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_32 0xa0 2083 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_64 0xc0 2084 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_UNLIMITED 0xe0 2085 - #define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_MASK 0xe0 2086 - 2087 - #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_UNLIMITED 0x00 2088 - #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_128 0x01 2089 - #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_256 0x02 2090 - #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_512 0x03 2091 - #define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_MASK 0x03 2092 - #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US 0x00 2093 - #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_8US 0x04 2094 - #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US 0x08 2095 - #define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK 0x0c 2096 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_1 0x00 2097 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_2 0x10 2098 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_3 0x20 2099 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_4 0x30 2100 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_5 0x40 2101 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_6 0x50 2102 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_7 0x60 2103 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8 0x70 2104 - #define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_MASK 0x70 2105 - 2106 - /* Link adaptation is split between byte HE_MAC_CAP1 and 2107 - * HE_MAC_CAP2. It should be set only if IEEE80211_HE_MAC_CAP0_HTC_HE 2108 - * in which case the following values apply: 2109 - * 0 = No feedback. 2110 - * 1 = reserved. 2111 - * 2 = Unsolicited feedback. 2112 - * 3 = both 2113 - */ 2114 - #define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION 0x80 2115 - 2116 - #define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION 0x01 2117 - #define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 2118 - #define IEEE80211_HE_MAC_CAP2_TRS 0x04 2119 - #define IEEE80211_HE_MAC_CAP2_BSR 0x08 2120 - #define IEEE80211_HE_MAC_CAP2_BCAST_TWT 0x10 2121 - #define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP 0x20 2122 - #define IEEE80211_HE_MAC_CAP2_MU_CASCADING 0x40 2123 - #define IEEE80211_HE_MAC_CAP2_ACK_EN 0x80 2124 - 2125 - #define IEEE80211_HE_MAC_CAP3_OMI_CONTROL 0x02 2126 - #define IEEE80211_HE_MAC_CAP3_OFDMA_RA 0x04 2127 - 2128 - /* The maximum length of an A-MDPU is defined by the combination of the Maximum 2129 - * A-MDPU Length Exponent field in the HT capabilities, VHT capabilities and the 2130 - * same field in the HE capabilities. 2131 - */ 2132 - #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_0 0x00 2133 - #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1 0x08 2134 - #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2 0x10 2135 - #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3 0x18 2136 - #define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK 0x18 2137 - #define IEEE80211_HE_MAC_CAP3_AMSDU_FRAG 0x20 2138 - #define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED 0x40 2139 - #define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS 0x80 2140 - 2141 - #define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG 0x01 2142 - #define IEEE80211_HE_MAC_CAP4_QTP 0x02 2143 - #define IEEE80211_HE_MAC_CAP4_BQR 0x04 2144 - #define IEEE80211_HE_MAC_CAP4_PSR_RESP 0x08 2145 - #define IEEE80211_HE_MAC_CAP4_NDP_FB_REP 0x10 2146 - #define IEEE80211_HE_MAC_CAP4_OPS 0x20 2147 - #define IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU 0x40 2148 - /* Multi TID agg TX is split between byte #4 and #5 2149 - * The value is a combination of B39,B40,B41 2150 - */ 2151 - #define IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39 0x80 2152 - 2153 - #define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 0x01 2154 - #define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 0x02 2155 - #define IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION 0x04 2156 - #define IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU 0x08 2157 - #define IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX 0x10 2158 - #define IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS 0x20 2159 - #define IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING 0x40 2160 - #define IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX 0x80 2161 - 2162 - #define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR 20 2163 - #define IEEE80211_HE_HT_MAX_AMPDU_FACTOR 16 2164 - #define IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR 13 2165 - 2166 - /* 802.11ax HE PHY capabilities */ 2167 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 2168 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 2169 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G 0x08 2170 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G 0x10 2171 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL 0x1e 2172 - 2173 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G 0x20 2174 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G 0x40 2175 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK 0xfe 2176 - 2177 - #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ 0x01 2178 - #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ 0x02 2179 - #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ 0x04 2180 - #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ 0x08 2181 - #define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK 0x0f 2182 - #define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A 0x10 2183 - #define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 2184 - #define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 2185 - /* Midamble RX/TX Max NSTS is split between byte #2 and byte #3 */ 2186 - #define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 2187 - 2188 - #define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 2189 - #define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 2190 - #define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ 0x04 2191 - #define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 2192 - #define IEEE80211_HE_PHY_CAP2_DOPPLER_TX 0x10 2193 - #define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 2194 - 2195 - /* Note that the meaning of UL MU below is different between an AP and a non-AP 2196 - * sta, where in the AP case it indicates support for Rx and in the non-AP sta 2197 - * case it indicates support for Tx. 2198 - */ 2199 - #define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO 0x40 2200 - #define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO 0x80 2201 - 2202 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM 0x00 2203 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK 0x01 2204 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK 0x02 2205 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM 0x03 2206 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK 0x03 2207 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 0x00 2208 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2 0x04 2209 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM 0x00 2210 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK 0x08 2211 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK 0x10 2212 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 2213 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK 0x18 2214 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 2215 - #define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2 0x20 2216 - #define IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU 0x40 2217 - #define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER 0x80 2218 - 2219 - #define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 2220 - #define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER 0x02 2221 - 2222 - /* Minimal allowed value of Max STS under 80MHz is 3 */ 2223 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c 2224 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 0x10 2225 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_6 0x14 2226 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_7 0x18 2227 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8 0x1c 2228 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK 0x1c 2229 - 2230 - /* Minimal allowed value of Max STS above 80MHz is 3 */ 2231 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 0x60 2232 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 0x80 2233 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_6 0xa0 2234 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_7 0xc0 2235 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 0xe0 2236 - #define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK 0xe0 2237 - 2238 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_1 0x00 2239 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 0x01 2240 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_3 0x02 2241 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_4 0x03 2242 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_5 0x04 2243 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_6 0x05 2244 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_7 0x06 2245 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_8 0x07 2246 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK 0x07 2247 - 2248 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_1 0x00 2249 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 0x08 2250 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_3 0x10 2251 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_4 0x18 2252 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_5 0x20 2253 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_6 0x28 2254 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_7 0x30 2255 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_8 0x38 2256 - #define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK 0x38 2257 - 2258 - #define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 2259 - #define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 2260 - 2261 - #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 2262 - #define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 2263 - #define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB 0x04 2264 - #define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB 0x08 2265 - #define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB 0x10 2266 - #define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE 0x20 2267 - #define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 2268 - #define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 2269 - 2270 - #define IEEE80211_HE_PHY_CAP7_PSR_BASED_SR 0x01 2271 - #define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP 0x02 2272 - #define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 2273 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_1 0x08 2274 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_2 0x10 2275 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_3 0x18 2276 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_4 0x20 2277 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_5 0x28 2278 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_6 0x30 2279 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_7 0x38 2280 - #define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK 0x38 2281 - #define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ 0x40 2282 - #define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ 0x80 2283 - 2284 - #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI 0x01 2285 - #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 2286 - #define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU 0x04 2287 - #define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU 0x08 2288 - #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI 0x10 2289 - #define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_TX_2X_AND_1XLTF 0x20 2290 - #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242 0x00 2291 - #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484 0x40 2292 - #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996 0x80 2293 - #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996 0xc0 2294 - #define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK 0xc0 2295 - 2296 - #define IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM 0x01 2297 - #define IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK 0x02 2298 - #define IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU 0x04 2299 - #define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU 0x08 2300 - #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 2301 - #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 2302 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US 0x0 2303 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US 0x1 2304 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US 0x2 2305 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED 0x3 2306 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS 6 2307 - #define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK 0xc0 2308 - 2309 - #define IEEE80211_HE_PHY_CAP10_HE_MU_M1RU_MAX_LTF 0x01 2310 - 2311 - /* 802.11ax HE TX/RX MCS NSS Support */ 2312 - #define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS (3) 2313 - #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_POS (6) 2314 - #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_POS (11) 2315 - #define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK 0x07c0 2316 - #define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK 0xf800 2317 - 2318 - /* TX/RX HE MCS Support field Highest MCS subfield encoding */ 2319 - enum ieee80211_he_highest_mcs_supported_subfield_enc { 2320 - HIGHEST_MCS_SUPPORTED_MCS7 = 0, 2321 - HIGHEST_MCS_SUPPORTED_MCS8, 2322 - HIGHEST_MCS_SUPPORTED_MCS9, 2323 - HIGHEST_MCS_SUPPORTED_MCS10, 2324 - HIGHEST_MCS_SUPPORTED_MCS11, 2325 - }; 2326 - 2327 - /* Calculate 802.11ax HE capabilities IE Tx/Rx HE MCS NSS Support Field size */ 2328 - static inline u8 2329 - ieee80211_he_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap) 2330 - { 2331 - u8 count = 4; 2332 - 2333 - if (he_cap->phy_cap_info[0] & 2334 - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) 2335 - count += 4; 2336 - 2337 - if (he_cap->phy_cap_info[0] & 2338 - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) 2339 - count += 4; 2340 - 2341 - return count; 2342 - } 2343 - 2344 - /* 802.11ax HE PPE Thresholds */ 2345 - #define IEEE80211_PPE_THRES_NSS_SUPPORT_2NSS (1) 2346 - #define IEEE80211_PPE_THRES_NSS_POS (0) 2347 - #define IEEE80211_PPE_THRES_NSS_MASK (7) 2348 - #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_2x966_AND_966_RU \ 2349 - (BIT(5) | BIT(6)) 2350 - #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK 0x78 2351 - #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS (3) 2352 - #define IEEE80211_PPE_THRES_INFO_PPET_SIZE (3) 2353 - #define IEEE80211_HE_PPE_THRES_INFO_HEADER_SIZE (7) 2354 - 2355 - /* 2356 - * Calculate 802.11ax HE capabilities IE PPE field size 2357 - * Input: Header byte of ppe_thres (first byte), and HE capa IE's PHY cap u8* 2358 - */ 2359 - static inline u8 2360 - ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) 2361 - { 2362 - u8 n; 2363 - 2364 - if ((phy_cap_info[6] & 2365 - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) 2366 - return 0; 2367 - 2368 - n = hweight8(ppe_thres_hdr & 2369 - IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK); 2370 - n *= (1 + ((ppe_thres_hdr & IEEE80211_PPE_THRES_NSS_MASK) >> 2371 - IEEE80211_PPE_THRES_NSS_POS)); 2372 - 2373 - /* 2374 - * Each pair is 6 bits, and we need to add the 7 "header" bits to the 2375 - * total size. 2376 - */ 2377 - n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7; 2378 - n = DIV_ROUND_UP(n, 8); 2379 - 2380 - return n; 2381 - } 2382 - 2383 - static inline bool ieee80211_he_capa_size_ok(const u8 *data, u8 len) 2384 - { 2385 - const struct ieee80211_he_cap_elem *he_cap_ie_elem = (const void *)data; 2386 - u8 needed = sizeof(*he_cap_ie_elem); 2387 - 2388 - if (len < needed) 2389 - return false; 2390 - 2391 - needed += ieee80211_he_mcs_nss_size(he_cap_ie_elem); 2392 - if (len < needed) 2393 - return false; 2394 - 2395 - if (he_cap_ie_elem->phy_cap_info[6] & 2396 - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { 2397 - if (len < needed + 1) 2398 - return false; 2399 - needed += ieee80211_he_ppe_size(data[needed], 2400 - he_cap_ie_elem->phy_cap_info); 2401 - } 2402 - 2403 - return len >= needed; 2404 - } 2405 - 2406 - /* HE Operation defines */ 2407 - #define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK 0x00000007 2408 - #define IEEE80211_HE_OPERATION_TWT_REQUIRED 0x00000008 2409 - #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK 0x00003ff0 2410 - #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET 4 2411 - #define IEEE80211_HE_OPERATION_VHT_OPER_INFO 0x00004000 2412 - #define IEEE80211_HE_OPERATION_CO_HOSTED_BSS 0x00008000 2413 - #define IEEE80211_HE_OPERATION_ER_SU_DISABLE 0x00010000 2414 - #define IEEE80211_HE_OPERATION_6GHZ_OP_INFO 0x00020000 2415 - #define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x3f000000 2416 - #define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24 2417 - #define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000 2418 - #define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x80000000 2419 - 2420 - #define IEEE80211_6GHZ_CTRL_REG_LPI_AP 0 2421 - #define IEEE80211_6GHZ_CTRL_REG_SP_AP 1 2422 - #define IEEE80211_6GHZ_CTRL_REG_VLP_AP 2 2423 - #define IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP 3 2424 - #define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD 4 2425 - #define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP 8 2426 - 2427 - /** 2428 - * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field 2429 - * @primary: primary channel 2430 - * @control: control flags 2431 - * @ccfs0: channel center frequency segment 0 2432 - * @ccfs1: channel center frequency segment 1 2433 - * @minrate: minimum rate (in 1 Mbps units) 2434 - */ 2435 - struct ieee80211_he_6ghz_oper { 2436 - u8 primary; 2437 - #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH 0x3 2438 - #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ 0 2439 - #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ 1 2440 - #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ 2 2441 - #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3 2442 - #define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4 2443 - #define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x78 2444 - u8 control; 2445 - u8 ccfs0; 2446 - u8 ccfs1; 2447 - u8 minrate; 2448 - } __packed; 2449 - 2450 - /** 2451 - * enum ieee80211_reg_conn_bits - represents Regulatory connectivity field bits. 2452 - * 2453 - * This enumeration defines bit flags used to represent regulatory connectivity 2454 - * field bits. 2455 - * 2456 - * @IEEE80211_REG_CONN_LPI_VALID: Indicates whether the LPI bit is valid. 2457 - * @IEEE80211_REG_CONN_LPI_VALUE: Represents the value of the LPI bit. 2458 - * @IEEE80211_REG_CONN_SP_VALID: Indicates whether the SP bit is valid. 2459 - * @IEEE80211_REG_CONN_SP_VALUE: Represents the value of the SP bit. 2460 - */ 2461 - enum ieee80211_reg_conn_bits { 2462 - IEEE80211_REG_CONN_LPI_VALID = BIT(0), 2463 - IEEE80211_REG_CONN_LPI_VALUE = BIT(1), 2464 - IEEE80211_REG_CONN_SP_VALID = BIT(2), 2465 - IEEE80211_REG_CONN_SP_VALUE = BIT(3), 2466 - }; 2467 - 2468 - /* transmit power interpretation type of transmit power envelope element */ 2469 - enum ieee80211_tx_power_intrpt_type { 2470 - IEEE80211_TPE_LOCAL_EIRP, 2471 - IEEE80211_TPE_LOCAL_EIRP_PSD, 2472 - IEEE80211_TPE_REG_CLIENT_EIRP, 2473 - IEEE80211_TPE_REG_CLIENT_EIRP_PSD, 2474 - }; 2475 - 2476 - /* category type of transmit power envelope element */ 2477 - enum ieee80211_tx_power_category_6ghz { 2478 - IEEE80211_TPE_CAT_6GHZ_DEFAULT = 0, 2479 - IEEE80211_TPE_CAT_6GHZ_SUBORDINATE = 1, 2480 - }; 2481 - 2482 - /* 2483 - * For IEEE80211_TPE_LOCAL_EIRP / IEEE80211_TPE_REG_CLIENT_EIRP, 2484 - * setting to 63.5 dBm means no constraint. 2485 - */ 2486 - #define IEEE80211_TPE_MAX_TX_PWR_NO_CONSTRAINT 127 2487 - 2488 - /* 2489 - * For IEEE80211_TPE_LOCAL_EIRP_PSD / IEEE80211_TPE_REG_CLIENT_EIRP_PSD, 2490 - * setting to 127 indicates no PSD limit for the 20 MHz channel. 2491 - */ 2492 - #define IEEE80211_TPE_PSD_NO_LIMIT 127 2493 - 2494 - /** 2495 - * struct ieee80211_tx_pwr_env - Transmit Power Envelope 2496 - * @info: Transmit Power Information field 2497 - * @variable: Maximum Transmit Power field 2498 - * 2499 - * This structure represents the payload of the "Transmit Power 2500 - * Envelope element" as described in IEEE Std 802.11ax-2021 section 2501 - * 9.4.2.161 2502 - */ 2503 - struct ieee80211_tx_pwr_env { 2504 - u8 info; 2505 - u8 variable[]; 2506 - } __packed; 2507 - 2508 - #define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7 2509 - #define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 2510 - #define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0 2511 - 2512 - #define IEEE80211_TX_PWR_ENV_EXT_COUNT 0xF 2513 - 2514 - static inline bool ieee80211_valid_tpe_element(const u8 *data, u8 len) 2515 - { 2516 - const struct ieee80211_tx_pwr_env *env = (const void *)data; 2517 - u8 count, interpret, category; 2518 - u8 needed = sizeof(*env); 2519 - u8 N; /* also called N in the spec */ 2520 - 2521 - if (len < needed) 2522 - return false; 2523 - 2524 - count = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_COUNT); 2525 - interpret = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_INTERPRET); 2526 - category = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_CATEGORY); 2527 - 2528 - switch (category) { 2529 - case IEEE80211_TPE_CAT_6GHZ_DEFAULT: 2530 - case IEEE80211_TPE_CAT_6GHZ_SUBORDINATE: 2531 - break; 2532 - default: 2533 - return false; 2534 - } 2535 - 2536 - switch (interpret) { 2537 - case IEEE80211_TPE_LOCAL_EIRP: 2538 - case IEEE80211_TPE_REG_CLIENT_EIRP: 2539 - if (count > 3) 2540 - return false; 2541 - 2542 - /* count == 0 encodes 1 value for 20 MHz, etc. */ 2543 - needed += count + 1; 2544 - 2545 - if (len < needed) 2546 - return false; 2547 - 2548 - /* there can be extension fields not accounted for in 'count' */ 2549 - 2550 - return true; 2551 - case IEEE80211_TPE_LOCAL_EIRP_PSD: 2552 - case IEEE80211_TPE_REG_CLIENT_EIRP_PSD: 2553 - if (count > 4) 2554 - return false; 2555 - 2556 - N = count ? 1 << (count - 1) : 1; 2557 - needed += N; 2558 - 2559 - if (len < needed) 2560 - return false; 2561 - 2562 - if (len > needed) { 2563 - u8 K = u8_get_bits(env->variable[N], 2564 - IEEE80211_TX_PWR_ENV_EXT_COUNT); 2565 - 2566 - needed += 1 + K; 2567 - if (len < needed) 2568 - return false; 2569 - } 2570 - 2571 - return true; 2572 - } 2573 - 2574 - return false; 2575 - } 2576 - 2577 - /* 2578 - * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size 2579 - * @he_oper_ie: byte data of the He Operations IE, stating from the byte 2580 - * after the ext ID byte. It is assumed that he_oper_ie has at least 2581 - * sizeof(struct ieee80211_he_operation) bytes, the caller must have 2582 - * validated this. 2583 - * @return the actual size of the IE data (not including header), or 0 on error 2584 - */ 2585 - static inline u8 2586 - ieee80211_he_oper_size(const u8 *he_oper_ie) 2587 - { 2588 - const struct ieee80211_he_operation *he_oper = (const void *)he_oper_ie; 2589 - u8 oper_len = sizeof(struct ieee80211_he_operation); 2590 - u32 he_oper_params; 2591 - 2592 - /* Make sure the input is not NULL */ 2593 - if (!he_oper_ie) 2594 - return 0; 2595 - 2596 - /* Calc required length */ 2597 - he_oper_params = le32_to_cpu(he_oper->he_oper_params); 2598 - if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) 2599 - oper_len += 3; 2600 - if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) 2601 - oper_len++; 2602 - if (he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO) 2603 - oper_len += sizeof(struct ieee80211_he_6ghz_oper); 2604 - 2605 - /* Add the first byte (extension ID) to the total length */ 2606 - oper_len++; 2607 - 2608 - return oper_len; 2609 - } 2610 - 2611 - /** 2612 - * ieee80211_he_6ghz_oper - obtain 6 GHz operation field 2613 - * @he_oper: HE operation element (must be pre-validated for size) 2614 - * but may be %NULL 2615 - * 2616 - * Return: a pointer to the 6 GHz operation field, or %NULL 2617 - */ 2618 - static inline const struct ieee80211_he_6ghz_oper * 2619 - ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper) 2620 - { 2621 - const u8 *ret; 2622 - u32 he_oper_params; 2623 - 2624 - if (!he_oper) 2625 - return NULL; 2626 - 2627 - ret = (const void *)&he_oper->optional; 2628 - 2629 - he_oper_params = le32_to_cpu(he_oper->he_oper_params); 2630 - 2631 - if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)) 2632 - return NULL; 2633 - if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) 2634 - ret += 3; 2635 - if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) 2636 - ret++; 2637 - 2638 - return (const void *)ret; 2639 - } 2640 - 2641 - /* HE Spatial Reuse defines */ 2642 - #define IEEE80211_HE_SPR_PSR_DISALLOWED BIT(0) 2643 - #define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) 2644 - #define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT BIT(2) 2645 - #define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT BIT(3) 2646 - #define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED BIT(4) 2647 - 2648 - /* 2649 - * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size 2650 - * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the byte 2651 - * after the ext ID byte. It is assumed that he_spr_ie has at least 2652 - * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated 2653 - * this 2654 - * @return the actual size of the IE data (not including header), or 0 on error 2655 - */ 2656 - static inline u8 2657 - ieee80211_he_spr_size(const u8 *he_spr_ie) 2658 - { 2659 - const struct ieee80211_he_spr *he_spr = (const void *)he_spr_ie; 2660 - u8 spr_len = sizeof(struct ieee80211_he_spr); 2661 - u8 he_spr_params; 2662 - 2663 - /* Make sure the input is not NULL */ 2664 - if (!he_spr_ie) 2665 - return 0; 2666 - 2667 - /* Calc required length */ 2668 - he_spr_params = he_spr->he_sr_control; 2669 - if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) 2670 - spr_len++; 2671 - if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) 2672 - spr_len += 18; 2673 - 2674 - /* Add the first byte (extension ID) to the total length */ 2675 - spr_len++; 2676 - 2677 - return spr_len; 2678 - } 2679 - 2680 - /* S1G Capabilities Information field */ 2681 - #define IEEE80211_S1G_CAPABILITY_LEN 15 2682 - 2683 - #define S1G_CAP0_S1G_LONG BIT(0) 2684 - #define S1G_CAP0_SGI_1MHZ BIT(1) 2685 - #define S1G_CAP0_SGI_2MHZ BIT(2) 2686 - #define S1G_CAP0_SGI_4MHZ BIT(3) 2687 - #define S1G_CAP0_SGI_8MHZ BIT(4) 2688 - #define S1G_CAP0_SGI_16MHZ BIT(5) 2689 - #define S1G_CAP0_SUPP_CH_WIDTH GENMASK(7, 6) 2690 - 2691 - #define S1G_SUPP_CH_WIDTH_2 0 2692 - #define S1G_SUPP_CH_WIDTH_4 1 2693 - #define S1G_SUPP_CH_WIDTH_8 2 2694 - #define S1G_SUPP_CH_WIDTH_16 3 2695 - #define S1G_SUPP_CH_WIDTH_MAX(cap) ((1 << FIELD_GET(S1G_CAP0_SUPP_CH_WIDTH, \ 2696 - cap[0])) << 1) 2697 - 2698 - #define S1G_CAP1_RX_LDPC BIT(0) 2699 - #define S1G_CAP1_TX_STBC BIT(1) 2700 - #define S1G_CAP1_RX_STBC BIT(2) 2701 - #define S1G_CAP1_SU_BFER BIT(3) 2702 - #define S1G_CAP1_SU_BFEE BIT(4) 2703 - #define S1G_CAP1_BFEE_STS GENMASK(7, 5) 2704 - 2705 - #define S1G_CAP2_SOUNDING_DIMENSIONS GENMASK(2, 0) 2706 - #define S1G_CAP2_MU_BFER BIT(3) 2707 - #define S1G_CAP2_MU_BFEE BIT(4) 2708 - #define S1G_CAP2_PLUS_HTC_VHT BIT(5) 2709 - #define S1G_CAP2_TRAVELING_PILOT GENMASK(7, 6) 2710 - 2711 - #define S1G_CAP3_RD_RESPONDER BIT(0) 2712 - #define S1G_CAP3_HT_DELAYED_BA BIT(1) 2713 - #define S1G_CAP3_MAX_MPDU_LEN BIT(2) 2714 - #define S1G_CAP3_MAX_AMPDU_LEN_EXP GENMASK(4, 3) 2715 - #define S1G_CAP3_MIN_MPDU_START GENMASK(7, 5) 2716 - 2717 - #define S1G_CAP4_UPLINK_SYNC BIT(0) 2718 - #define S1G_CAP4_DYNAMIC_AID BIT(1) 2719 - #define S1G_CAP4_BAT BIT(2) 2720 - #define S1G_CAP4_TIME_ADE BIT(3) 2721 - #define S1G_CAP4_NON_TIM BIT(4) 2722 - #define S1G_CAP4_GROUP_AID BIT(5) 2723 - #define S1G_CAP4_STA_TYPE GENMASK(7, 6) 2724 - 2725 - #define S1G_CAP5_CENT_AUTH_CONTROL BIT(0) 2726 - #define S1G_CAP5_DIST_AUTH_CONTROL BIT(1) 2727 - #define S1G_CAP5_AMSDU BIT(2) 2728 - #define S1G_CAP5_AMPDU BIT(3) 2729 - #define S1G_CAP5_ASYMMETRIC_BA BIT(4) 2730 - #define S1G_CAP5_FLOW_CONTROL BIT(5) 2731 - #define S1G_CAP5_SECTORIZED_BEAM GENMASK(7, 6) 2732 - 2733 - #define S1G_CAP6_OBSS_MITIGATION BIT(0) 2734 - #define S1G_CAP6_FRAGMENT_BA BIT(1) 2735 - #define S1G_CAP6_NDP_PS_POLL BIT(2) 2736 - #define S1G_CAP6_RAW_OPERATION BIT(3) 2737 - #define S1G_CAP6_PAGE_SLICING BIT(4) 2738 - #define S1G_CAP6_TXOP_SHARING_IMP_ACK BIT(5) 2739 - #define S1G_CAP6_VHT_LINK_ADAPT GENMASK(7, 6) 2740 - 2741 - #define S1G_CAP7_TACK_AS_PS_POLL BIT(0) 2742 - #define S1G_CAP7_DUP_1MHZ BIT(1) 2743 - #define S1G_CAP7_MCS_NEGOTIATION BIT(2) 2744 - #define S1G_CAP7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3) 2745 - #define S1G_CAP7_NDP_BFING_REPORT_POLL BIT(4) 2746 - #define S1G_CAP7_UNSOLICITED_DYN_AID BIT(5) 2747 - #define S1G_CAP7_SECTOR_TRAINING_OPERATION BIT(6) 2748 - #define S1G_CAP7_TEMP_PS_MODE_SWITCH BIT(7) 2749 - 2750 - #define S1G_CAP8_TWT_GROUPING BIT(0) 2751 - #define S1G_CAP8_BDT BIT(1) 2752 - #define S1G_CAP8_COLOR GENMASK(4, 2) 2753 - #define S1G_CAP8_TWT_REQUEST BIT(5) 2754 - #define S1G_CAP8_TWT_RESPOND BIT(6) 2755 - #define S1G_CAP8_PV1_FRAME BIT(7) 2756 - 2757 - #define S1G_CAP9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0) 2758 - 2759 - #define S1G_OPER_CH_WIDTH_PRIMARY BIT(0) 2760 - #define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1) 2761 - #define S1G_OPER_CH_PRIMARY_LOCATION BIT(5) 2762 - 2763 - #define S1G_2M_PRIMARY_LOCATION_LOWER 0 2764 - #define S1G_2M_PRIMARY_LOCATION_UPPER 1 2765 - 2766 - /* EHT MAC capabilities as defined in P802.11be_D2.0 section 9.4.2.313.2 */ 2767 - #define IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS 0x01 2768 - #define IEEE80211_EHT_MAC_CAP0_OM_CONTROL 0x02 2769 - #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x04 2770 - #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x08 2771 - #define IEEE80211_EHT_MAC_CAP0_RESTRICTED_TWT 0x10 2772 - #define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC 0x20 2773 - #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK 0xc0 2774 - #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_3895 0 2775 - #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991 1 2776 - #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454 2 2777 - 2778 - #define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK 0x01 2779 - #define IEEE80211_EHT_MAC_CAP1_EHT_TRS 0x02 2780 - #define IEEE80211_EHT_MAC_CAP1_TXOP_RET 0x04 2781 - #define IEEE80211_EHT_MAC_CAP1_TWO_BQRS 0x08 2782 - #define IEEE80211_EHT_MAC_CAP1_EHT_LINK_ADAPT_MASK 0x30 2783 - #define IEEE80211_EHT_MAC_CAP1_UNSOL_EPCS_PRIO_ACCESS 0x40 2784 - 2785 - /* EHT PHY capabilities as defined in P802.11be_D2.0 section 9.4.2.313.3 */ 2786 - #define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 2787 - #define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x04 2788 - #define IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI 0x08 2789 - #define IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO 0x10 2790 - #define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER 0x20 2791 - #define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE 0x40 2792 - 2793 - /* EHT beamformee number of spatial streams <= 80MHz is split */ 2794 - #define IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK 0x80 2795 - #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK 0x03 2796 - 2797 - #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK 0x1c 2798 - #define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK 0xe0 2799 - 2800 - #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK 0x07 2801 - #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK 0x38 2802 - 2803 - /* EHT number of sounding dimensions for 320MHz is split */ 2804 - #define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK 0xc0 2805 - #define IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK 0x01 2806 - #define IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK 0x02 2807 - #define IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK 0x04 2808 - #define IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK 0x08 2809 - #define IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK 0x10 2810 - #define IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK 0x20 2811 - #define IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK 0x40 2812 - #define IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK 0x80 2813 - 2814 - #define IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO 0x01 2815 - #define IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP 0x02 2816 - #define IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP 0x04 2817 - #define IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI 0x08 2818 - #define IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK 0xf0 2819 - 2820 - #define IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK 0x01 2821 - #define IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP 0x02 2822 - #define IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP 0x04 2823 - #define IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT 0x08 2824 - #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK 0x30 2825 - #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_0US 0 2826 - #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US 1 2827 - #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US 2 2828 - #define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_20US 3 2829 - 2830 - /* Maximum number of supported EHT LTF is split */ 2831 - #define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK 0xc0 2832 - #define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF 0x40 2833 - #define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK 0x07 2834 - 2835 - #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_80MHZ 0x08 2836 - #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_160MHZ 0x30 2837 - #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ 0x40 2838 - #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK 0x78 2839 - #define IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP 0x80 2840 - 2841 - #define IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW 0x01 2842 - #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ 0x02 2843 - #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ 0x04 2844 - #define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ 0x08 2845 - #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ 0x10 2846 - #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ 0x20 2847 - #define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ 0x40 2848 - #define IEEE80211_EHT_PHY_CAP7_TB_SOUNDING_FDBK_RATE_LIMIT 0x80 2849 - 2850 - #define IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA 0x01 2851 - #define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 2852 - 2853 - /* 2854 - * EHT operation channel width as defined in P802.11be_D2.0 section 9.4.2.311 2855 - */ 2856 - #define IEEE80211_EHT_OPER_CHAN_WIDTH 0x7 2857 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ 0 2858 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ 1 2859 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ 2 2860 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ 3 2861 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ 4 2862 - 2863 - /* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */ 2864 - static inline u8 2865 - ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, 2866 - const struct ieee80211_eht_cap_elem_fixed *eht_cap, 2867 - bool from_ap) 2868 - { 2869 - u8 count = 0; 2870 - 2871 - /* on 2.4 GHz, if it supports 40 MHz, the result is 3 */ 2872 - if (he_cap->phy_cap_info[0] & 2873 - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) 2874 - return 3; 2875 - 2876 - /* on 2.4 GHz, these three bits are reserved, so should be 0 */ 2877 - if (he_cap->phy_cap_info[0] & 2878 - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) 2879 - count += 3; 2880 - 2881 - if (he_cap->phy_cap_info[0] & 2882 - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) 2883 - count += 3; 2884 - 2885 - if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) 2886 - count += 3; 2887 - 2888 - if (count) 2889 - return count; 2890 - 2891 - return from_ap ? 3 : 4; 2892 - } 2893 - 2894 - /* 802.11be EHT PPE Thresholds */ 2895 - #define IEEE80211_EHT_PPE_THRES_NSS_POS 0 2896 - #define IEEE80211_EHT_PPE_THRES_NSS_MASK 0xf 2897 - #define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK 0x1f0 2898 - #define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE 3 2899 - #define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE 9 2900 - 2901 - /* 2902 - * Calculate 802.11be EHT capabilities IE EHT field size 2903 - */ 2904 - static inline u8 2905 - ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info) 2906 - { 2907 - u32 n; 2908 - 2909 - if (!(phy_cap_info[5] & 2910 - IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)) 2911 - return 0; 2912 - 2913 - n = hweight16(ppe_thres_hdr & 2914 - IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); 2915 - n *= 1 + u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_NSS_MASK); 2916 - 2917 - /* 2918 - * Each pair is 6 bits, and we need to add the 9 "header" bits to the 2919 - * total size. 2920 - */ 2921 - n = n * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2 + 2922 - IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE; 2923 - return DIV_ROUND_UP(n, 8); 2924 - } 2925 - 2926 - static inline bool 2927 - ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len, 2928 - bool from_ap) 2929 - { 2930 - const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data; 2931 - u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed); 2932 - 2933 - if (len < needed || !he_capa) 2934 - return false; 2935 - 2936 - needed += ieee80211_eht_mcs_nss_size((const void *)he_capa, 2937 - (const void *)data, 2938 - from_ap); 2939 - if (len < needed) 2940 - return false; 2941 - 2942 - if (elem->phy_cap_info[5] & 2943 - IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) { 2944 - u16 ppe_thres_hdr; 2945 - 2946 - if (len < needed + sizeof(ppe_thres_hdr)) 2947 - return false; 2948 - 2949 - ppe_thres_hdr = get_unaligned_le16(data + needed); 2950 - needed += ieee80211_eht_ppe_size(ppe_thres_hdr, 2951 - elem->phy_cap_info); 2952 - } 2953 - 2954 - return len >= needed; 2955 - } 2956 - 2957 - static inline bool 2958 - ieee80211_eht_oper_size_ok(const u8 *data, u8 len) 2959 - { 2960 - const struct ieee80211_eht_operation *elem = (const void *)data; 2961 - u8 needed = sizeof(*elem); 2962 - 2963 - if (len < needed) 2964 - return false; 2965 - 2966 - if (elem->params & IEEE80211_EHT_OPER_INFO_PRESENT) { 2967 - needed += 3; 2968 - 2969 - if (elem->params & 2970 - IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT) 2971 - needed += 2; 2972 - } 2973 - 2974 - return len >= needed; 2975 - } 2976 - 2977 - /* must validate ieee80211_eht_oper_size_ok() first */ 2978 - static inline u16 2979 - ieee80211_eht_oper_dis_subchan_bitmap(const struct ieee80211_eht_operation *eht_oper) 2980 - { 2981 - const struct ieee80211_eht_operation_info *info = 2982 - (const void *)eht_oper->optional; 2983 - 2984 - if (!(eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) 2985 - return 0; 2986 - 2987 - if (!(eht_oper->params & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) 2988 - return 0; 2989 - 2990 - return get_unaligned_le16(info->optional); 2991 - } 2992 - 2993 - #define IEEE80211_BW_IND_DIS_SUBCH_PRESENT BIT(1) 2994 - 2995 - struct ieee80211_bandwidth_indication { 2996 - u8 params; 2997 - struct ieee80211_eht_operation_info info; 2998 - } __packed; 2999 - 3000 - static inline bool 3001 - ieee80211_bandwidth_indication_size_ok(const u8 *data, u8 len) 3002 - { 3003 - const struct ieee80211_bandwidth_indication *bwi = (const void *)data; 3004 - 3005 - if (len < sizeof(*bwi)) 3006 - return false; 3007 - 3008 - if (bwi->params & IEEE80211_BW_IND_DIS_SUBCH_PRESENT && 3009 - len < sizeof(*bwi) + 2) 3010 - return false; 3011 - 3012 - return true; 3013 - } 3014 - 3015 - #define LISTEN_INT_USF GENMASK(15, 14) 3016 - #define LISTEN_INT_UI GENMASK(13, 0) 3017 - 3018 - #define IEEE80211_MAX_USF FIELD_MAX(LISTEN_INT_USF) 3019 - #define IEEE80211_MAX_UI FIELD_MAX(LISTEN_INT_UI) 3020 1762 3021 1763 /* Authentication algorithms */ 3022 1764 #define WLAN_AUTH_OPEN 0 ··· 1832 3942 WLAN_ACTION_SPCT_CHL_SWITCH = 4, 1833 3943 }; 1834 3944 1835 - /* HT action codes */ 1836 - enum ieee80211_ht_actioncode { 1837 - WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, 1838 - WLAN_HT_ACTION_SMPS = 1, 1839 - WLAN_HT_ACTION_PSMP = 2, 1840 - WLAN_HT_ACTION_PCO_PHASE = 3, 1841 - WLAN_HT_ACTION_CSI = 4, 1842 - WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, 1843 - WLAN_HT_ACTION_COMPRESSED_BF = 6, 1844 - WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, 1845 - }; 1846 - 1847 - /* VHT action codes */ 1848 - enum ieee80211_vht_actioncode { 1849 - WLAN_VHT_ACTION_COMPRESSED_BF = 0, 1850 - WLAN_VHT_ACTION_GROUPID_MGMT = 1, 1851 - WLAN_VHT_ACTION_OPMODE_NOTIF = 2, 1852 - }; 1853 - 1854 3945 /* Self Protected Action codes */ 1855 3946 enum ieee80211_self_protected_actioncode { 1856 3947 WLAN_SP_RESERVED = 0, ··· 1842 3971 WLAN_SP_MGK_ACK = 5, 1843 3972 }; 1844 3973 1845 - /* Mesh action codes */ 1846 - enum ieee80211_mesh_actioncode { 1847 - WLAN_MESH_ACTION_LINK_METRIC_REPORT, 1848 - WLAN_MESH_ACTION_HWMP_PATH_SELECTION, 1849 - WLAN_MESH_ACTION_GATE_ANNOUNCEMENT, 1850 - WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION, 1851 - WLAN_MESH_ACTION_MCCA_SETUP_REQUEST, 1852 - WLAN_MESH_ACTION_MCCA_SETUP_REPLY, 1853 - WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST, 1854 - WLAN_MESH_ACTION_MCCA_ADVERTISEMENT, 1855 - WLAN_MESH_ACTION_MCCA_TEARDOWN, 1856 - WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST, 1857 - WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE, 1858 - }; 1859 - 1860 3974 /* Unprotected WNM action codes */ 1861 3975 enum ieee80211_unprotected_wnm_actioncode { 1862 3976 WLAN_UNPROTECTED_WNM_ACTION_TIM = 0, 1863 3977 WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE = 1, 1864 - }; 1865 - 1866 - /* Protected EHT action codes */ 1867 - enum ieee80211_protected_eht_actioncode { 1868 - WLAN_PROTECTED_EHT_ACTION_TTLM_REQ = 0, 1869 - WLAN_PROTECTED_EHT_ACTION_TTLM_RES = 1, 1870 - WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN = 2, 1871 - WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_REQ = 3, 1872 - WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_RESP = 4, 1873 - WLAN_PROTECTED_EHT_ACTION_EPCS_ENABLE_TEARDOWN = 5, 1874 - WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF = 6, 1875 - WLAN_PROTECTED_EHT_ACTION_LINK_RECOMMEND = 7, 1876 - WLAN_PROTECTED_EHT_ACTION_ML_OP_UPDATE_REQ = 8, 1877 - WLAN_PROTECTED_EHT_ACTION_ML_OP_UPDATE_RESP = 9, 1878 - WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_NOTIF = 10, 1879 - WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_REQ = 11, 1880 - WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_RESP = 12, 1881 3978 }; 1882 3979 1883 3980 /* Security key length */ ··· 1862 4023 WLAN_KEY_LEN_BIP_CMAC_256 = 32, 1863 4024 WLAN_KEY_LEN_BIP_GMAC_128 = 16, 1864 4025 WLAN_KEY_LEN_BIP_GMAC_256 = 32, 1865 - }; 1866 - 1867 - enum ieee80211_s1g_actioncode { 1868 - WLAN_S1G_AID_SWITCH_REQUEST, 1869 - WLAN_S1G_AID_SWITCH_RESPONSE, 1870 - WLAN_S1G_SYNC_CONTROL, 1871 - WLAN_S1G_STA_INFO_ANNOUNCE, 1872 - WLAN_S1G_EDCA_PARAM_SET, 1873 - WLAN_S1G_EL_OPERATION, 1874 - WLAN_S1G_TWT_SETUP, 1875 - WLAN_S1G_TWT_TEARDOWN, 1876 - WLAN_S1G_SECT_GROUP_ID_LIST, 1877 - WLAN_S1G_SECT_ID_FEEDBACK, 1878 - WLAN_S1G_TWT_INFORMATION = 11, 1879 4026 }; 1880 4027 1881 4028 /* Radio measurement action codes as defined in IEEE 802.11-2024 - Table 9-470 */ ··· 2023 4198 /* BSS Coex IE information field bits */ 2024 4199 #define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0) 2025 4200 2026 - /** 2027 - * enum ieee80211_mesh_sync_method - mesh synchronization method identifier 2028 - * 2029 - * @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method 2030 - * @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method 2031 - * that will be specified in a vendor specific information element 2032 - */ 2033 - enum ieee80211_mesh_sync_method { 2034 - IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1, 2035 - IEEE80211_SYNC_METHOD_VENDOR = 255, 2036 - }; 2037 - 2038 - /** 2039 - * enum ieee80211_mesh_path_protocol - mesh path selection protocol identifier 2040 - * 2041 - * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol 2042 - * @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will 2043 - * be specified in a vendor specific information element 2044 - */ 2045 - enum ieee80211_mesh_path_protocol { 2046 - IEEE80211_PATH_PROTOCOL_HWMP = 1, 2047 - IEEE80211_PATH_PROTOCOL_VENDOR = 255, 2048 - }; 2049 - 2050 - /** 2051 - * enum ieee80211_mesh_path_metric - mesh path selection metric identifier 2052 - * 2053 - * @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric 2054 - * @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be 2055 - * specified in a vendor specific information element 2056 - */ 2057 - enum ieee80211_mesh_path_metric { 2058 - IEEE80211_PATH_METRIC_AIRTIME = 1, 2059 - IEEE80211_PATH_METRIC_VENDOR = 255, 2060 - }; 2061 - 2062 - /** 2063 - * enum ieee80211_root_mode_identifier - root mesh STA mode identifier 2064 - * 2065 - * These attribute are used by dot11MeshHWMPRootMode to set root mesh STA mode 2066 - * 2067 - * @IEEE80211_ROOTMODE_NO_ROOT: the mesh STA is not a root mesh STA (default) 2068 - * @IEEE80211_ROOTMODE_ROOT: the mesh STA is a root mesh STA if greater than 2069 - * this value 2070 - * @IEEE80211_PROACTIVE_PREQ_NO_PREP: the mesh STA is a root mesh STA supports 2071 - * the proactive PREQ with proactive PREP subfield set to 0 2072 - * @IEEE80211_PROACTIVE_PREQ_WITH_PREP: the mesh STA is a root mesh STA 2073 - * supports the proactive PREQ with proactive PREP subfield set to 1 2074 - * @IEEE80211_PROACTIVE_RANN: the mesh STA is a root mesh STA supports 2075 - * the proactive RANN 2076 - */ 2077 - enum ieee80211_root_mode_identifier { 2078 - IEEE80211_ROOTMODE_NO_ROOT = 0, 2079 - IEEE80211_ROOTMODE_ROOT = 1, 2080 - IEEE80211_PROACTIVE_PREQ_NO_PREP = 2, 2081 - IEEE80211_PROACTIVE_PREQ_WITH_PREP = 3, 2082 - IEEE80211_PROACTIVE_RANN = 4, 2083 - }; 2084 - 2085 4201 /* 2086 4202 * IEEE 802.11-2007 7.3.2.9 Country information element 2087 4203 * ··· 2129 4363 __le16 max_idle_period; 2130 4364 u8 idle_options; 2131 4365 } __packed; 2132 - 2133 - /* BACK action code */ 2134 - enum ieee80211_back_actioncode { 2135 - WLAN_ACTION_ADDBA_REQ = 0, 2136 - WLAN_ACTION_ADDBA_RESP = 1, 2137 - WLAN_ACTION_DELBA = 2, 2138 - }; 2139 - 2140 - /* BACK (block-ack) parties */ 2141 - enum ieee80211_back_parties { 2142 - WLAN_BACK_RECIPIENT = 0, 2143 - WLAN_BACK_INITIATOR = 1, 2144 - }; 2145 4366 2146 4367 /* SA Query action */ 2147 4368 enum ieee80211_sa_query_action { ··· 2262 4509 __le16 sba; 2263 4510 __le16 medium_time; 2264 4511 } __packed; 2265 - 2266 - struct ieee80211_he_6ghz_capa { 2267 - /* uses IEEE80211_HE_6GHZ_CAP_* below */ 2268 - __le16 capa; 2269 - } __packed; 2270 - 2271 - /* HE 6 GHz band capabilities */ 2272 - /* uses enum ieee80211_min_mpdu_spacing values */ 2273 - #define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START 0x0007 2274 - /* uses enum ieee80211_vht_max_ampdu_length_exp values */ 2275 - #define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP 0x0038 2276 - /* uses IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_* values */ 2277 - #define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN 0x00c0 2278 - /* WLAN_HT_CAP_SM_PS_* values */ 2279 - #define IEEE80211_HE_6GHZ_CAP_SM_PS 0x0600 2280 - #define IEEE80211_HE_6GHZ_CAP_RD_RESPONDER 0x0800 2281 - #define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS 0x1000 2282 - #define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS 0x2000 2283 4512 2284 4513 /** 2285 4514 * ieee80211_get_qos_ctl - get pointer to qos control bytes ··· 2538 4803 return !!(tim->virtual_map[index] & mask); 2539 4804 } 2540 4805 2541 - struct s1g_tim_aid { 2542 - u16 aid; 2543 - u8 target_blk; /* Target block index */ 2544 - u8 target_subblk; /* Target subblock index */ 2545 - u8 target_subblk_bit; /* Target subblock bit */ 2546 - }; 2547 - 2548 - struct s1g_tim_enc_block { 2549 - u8 enc_mode; 2550 - bool inverse; 2551 - const u8 *ptr; 2552 - u8 len; 2553 - 2554 - /* 2555 - * For an OLB encoded block that spans multiple blocks, this 2556 - * is the offset into the span described by that encoded block. 2557 - */ 2558 - u8 olb_blk_offset; 2559 - }; 2560 - 2561 - /* 2562 - * Helper routines to quickly extract the length of an encoded block. Validation 2563 - * is also performed to ensure the length extracted lies within the TIM. 2564 - */ 2565 - 2566 - static inline int ieee80211_s1g_len_bitmap(const u8 *ptr, const u8 *end) 2567 - { 2568 - u8 blkmap; 2569 - u8 n_subblks; 2570 - 2571 - if (ptr >= end) 2572 - return -EINVAL; 2573 - 2574 - blkmap = *ptr; 2575 - n_subblks = hweight8(blkmap); 2576 - 2577 - if (ptr + 1 + n_subblks > end) 2578 - return -EINVAL; 2579 - 2580 - return 1 + n_subblks; 2581 - } 2582 - 2583 - static inline int ieee80211_s1g_len_single(const u8 *ptr, const u8 *end) 2584 - { 2585 - return (ptr + 1 > end) ? -EINVAL : 1; 2586 - } 2587 - 2588 - static inline int ieee80211_s1g_len_olb(const u8 *ptr, const u8 *end) 2589 - { 2590 - if (ptr >= end) 2591 - return -EINVAL; 2592 - 2593 - return (ptr + 1 + *ptr > end) ? -EINVAL : 1 + *ptr; 2594 - } 2595 - 2596 - /* 2597 - * Enumerate all encoded blocks until we find the encoded block that describes 2598 - * our target AID. OLB is a special case as a single encoded block can describe 2599 - * multiple blocks as a single encoded block. 2600 - */ 2601 - static inline int ieee80211_s1g_find_target_block(struct s1g_tim_enc_block *enc, 2602 - const struct s1g_tim_aid *aid, 2603 - const u8 *ptr, const u8 *end) 2604 - { 2605 - /* need at least block-control octet */ 2606 - while (ptr + 1 <= end) { 2607 - u8 ctrl = *ptr++; 2608 - u8 mode = ctrl & 0x03; 2609 - bool contains, inverse = ctrl & BIT(2); 2610 - u8 span, blk_off = ctrl >> 3; 2611 - int len; 2612 - 2613 - switch (mode) { 2614 - case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 2615 - len = ieee80211_s1g_len_bitmap(ptr, end); 2616 - contains = blk_off == aid->target_blk; 2617 - break; 2618 - case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 2619 - len = ieee80211_s1g_len_single(ptr, end); 2620 - contains = blk_off == aid->target_blk; 2621 - break; 2622 - case IEEE80211_S1G_TIM_ENC_MODE_OLB: 2623 - len = ieee80211_s1g_len_olb(ptr, end); 2624 - /* 2625 - * An OLB encoded block can describe more then one 2626 - * block, meaning an encoded OLB block can span more 2627 - * then a single block. 2628 - */ 2629 - if (len > 0) { 2630 - /* Minus one for the length octet */ 2631 - span = DIV_ROUND_UP(len - 1, 8); 2632 - /* 2633 - * Check if our target block lies within the 2634 - * block span described by this encoded block. 2635 - */ 2636 - contains = (aid->target_blk >= blk_off) && 2637 - (aid->target_blk < blk_off + span); 2638 - } 2639 - break; 2640 - default: 2641 - return -EOPNOTSUPP; 2642 - } 2643 - 2644 - if (len < 0) 2645 - return len; 2646 - 2647 - if (contains) { 2648 - enc->enc_mode = mode; 2649 - enc->inverse = inverse; 2650 - enc->ptr = ptr; 2651 - enc->len = (u8)len; 2652 - enc->olb_blk_offset = blk_off; 2653 - return 0; 2654 - } 2655 - 2656 - ptr += len; 2657 - } 2658 - 2659 - return -ENOENT; 2660 - } 2661 - 2662 - static inline bool ieee80211_s1g_parse_bitmap(struct s1g_tim_enc_block *enc, 2663 - struct s1g_tim_aid *aid) 2664 - { 2665 - const u8 *ptr = enc->ptr; 2666 - u8 blkmap = *ptr++; 2667 - 2668 - /* 2669 - * If our block bitmap does not contain a set bit that corresponds 2670 - * to our AID, it could mean a variety of things depending on if 2671 - * the encoding mode is inverted or not. 2672 - * 2673 - * 1. If inverted, it means the entire subblock is present and hence 2674 - * our AID has been set. 2675 - * 2. If not inverted, it means our subblock is not present and hence 2676 - * it is all zero meaning our AID is not set. 2677 - */ 2678 - if (!(blkmap & BIT(aid->target_subblk))) 2679 - return enc->inverse; 2680 - 2681 - /* 2682 - * Increment ptr by the number of set subblocks that appear before our 2683 - * target subblock. If our target subblock is 0, do nothing as ptr 2684 - * already points to our target subblock. 2685 - */ 2686 - if (aid->target_subblk) 2687 - ptr += hweight8(blkmap & GENMASK(aid->target_subblk - 1, 0)); 2688 - 2689 - return !!(*ptr & BIT(aid->target_subblk_bit)) ^ enc->inverse; 2690 - } 2691 - 2692 - static inline bool ieee80211_s1g_parse_single(struct s1g_tim_enc_block *enc, 2693 - struct s1g_tim_aid *aid) 2694 - { 2695 - /* 2696 - * Single AID mode describes, as the name suggests, a single AID 2697 - * within the block described by the encoded block. The octet 2698 - * contains the 6 LSBs of the AID described in the block. The other 2699 - * 2 bits are reserved. When inversed, every single AID described 2700 - * by the current block have buffered traffic except for the AID 2701 - * described in the single AID octet. 2702 - */ 2703 - return ((*enc->ptr & 0x3f) == (aid->aid & 0x3f)) ^ enc->inverse; 2704 - } 2705 - 2706 - static inline bool ieee80211_s1g_parse_olb(struct s1g_tim_enc_block *enc, 2707 - struct s1g_tim_aid *aid) 2708 - { 2709 - const u8 *ptr = enc->ptr; 2710 - u8 blk_len = *ptr++; 2711 - /* 2712 - * Given an OLB encoded block that describes multiple blocks, 2713 - * calculate the offset into the span. Then calculate the 2714 - * subblock location normally. 2715 - */ 2716 - u16 span_offset = aid->target_blk - enc->olb_blk_offset; 2717 - u16 subblk_idx = span_offset * 8 + aid->target_subblk; 2718 - 2719 - if (subblk_idx >= blk_len) 2720 - return enc->inverse; 2721 - 2722 - return !!(ptr[subblk_idx] & BIT(aid->target_subblk_bit)) ^ enc->inverse; 2723 - } 2724 - 2725 - /* 2726 - * An S1G PVB has 3 non optional encoding types, each that can be inverted. 2727 - * An S1G PVB is constructed with zero or more encoded block subfields. Each 2728 - * encoded block represents a single "block" of AIDs (64), and each encoded 2729 - * block can contain one of the 3 encoding types alongside a single bit for 2730 - * whether the bits should be inverted. 2731 - * 2732 - * As the standard makes no guarantee about the ordering of encoded blocks, 2733 - * we must parse every encoded block in the worst case scenario given an 2734 - * AID that lies within the last block. 2735 - */ 2736 - static inline bool ieee80211_s1g_check_tim(const struct ieee80211_tim_ie *tim, 2737 - u8 tim_len, u16 aid) 2738 - { 2739 - int err; 2740 - struct s1g_tim_aid target_aid; 2741 - struct s1g_tim_enc_block enc_blk; 2742 - 2743 - if (tim_len < 3) 2744 - return false; 2745 - 2746 - target_aid.aid = aid; 2747 - target_aid.target_blk = (aid >> 6) & 0x1f; 2748 - target_aid.target_subblk = (aid >> 3) & 0x7; 2749 - target_aid.target_subblk_bit = aid & 0x7; 2750 - 2751 - /* 2752 - * Find our AIDs target encoded block and fill &enc_blk with the 2753 - * encoded blocks information. If no entry is found or an error 2754 - * occurs return false. 2755 - */ 2756 - err = ieee80211_s1g_find_target_block(&enc_blk, &target_aid, 2757 - tim->virtual_map, 2758 - (const u8 *)tim + tim_len + 2); 2759 - if (err) 2760 - return false; 2761 - 2762 - switch (enc_blk.enc_mode) { 2763 - case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 2764 - return ieee80211_s1g_parse_bitmap(&enc_blk, &target_aid); 2765 - case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 2766 - return ieee80211_s1g_parse_single(&enc_blk, &target_aid); 2767 - case IEEE80211_S1G_TIM_ENC_MODE_OLB: 2768 - return ieee80211_s1g_parse_olb(&enc_blk, &target_aid); 2769 - default: 2770 - return false; 2771 - } 2772 - } 2773 - 2774 - /** 2775 - * ieee80211_check_tim - check if AID bit is set in TIM 2776 - * @tim: the TIM IE 2777 - * @tim_len: length of the TIM IE 2778 - * @aid: the AID to look for 2779 - * @s1g: whether the TIM is from an S1G PPDU 2780 - * Return: whether or not traffic is indicated in the TIM for the given AID 2781 - */ 2782 - static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim, 2783 - u8 tim_len, u16 aid, bool s1g) 2784 - { 2785 - return s1g ? ieee80211_s1g_check_tim(tim, tim_len, aid) : 2786 - __ieee80211_check_tim(tim, tim_len, aid); 2787 - } 2788 - 2789 4806 /** 2790 4807 * ieee80211_get_tdls_action - get TDLS action code 2791 4808 * @skb: the skb containing the frame, length will not be checked ··· 2669 5182 return true; 2670 5183 2671 5184 return false; 2672 - } 2673 - 2674 - /** 2675 - * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon 2676 - * @fc: frame control bytes in little-endian byteorder 2677 - * @variable: pointer to the beacon frame elements 2678 - * @variable_len: length of the frame elements 2679 - * Return: whether or not the frame is an S1G short beacon. As per 2680 - * IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall 2681 - * always be present as the first element in beacon frames generated at a 2682 - * TBTT (Target Beacon Transmission Time), so any frame not containing 2683 - * this element must have been generated at a TSBTT (Target Short Beacon 2684 - * Transmission Time) that is not a TBTT. Additionally, short beacons are 2685 - * prohibited from containing the S1G beacon compatibility element as per 2686 - * IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with 2687 - * either no elements or the first element is not the beacon compatibility 2688 - * element, we have a short beacon. 2689 - */ 2690 - static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable, 2691 - size_t variable_len) 2692 - { 2693 - if (!ieee80211_is_s1g_beacon(fc)) 2694 - return false; 2695 - 2696 - /* 2697 - * If the frame does not contain at least 1 element (this is perfectly 2698 - * valid in a short beacon) and is an S1G beacon, we have a short 2699 - * beacon. 2700 - */ 2701 - if (variable_len < 2) 2702 - return true; 2703 - 2704 - return variable[0] != WLAN_EID_S1G_BCN_COMPAT; 2705 5185 } 2706 5186 2707 5187 struct element { ··· 2804 5350 struct ieee80211_rnr_mld_params mld_params; 2805 5351 } __packed; 2806 5352 2807 - /* multi-link device */ 2808 - #define IEEE80211_MLD_MAX_NUM_LINKS 15 2809 - 2810 - #define IEEE80211_ML_CONTROL_TYPE 0x0007 2811 - #define IEEE80211_ML_CONTROL_TYPE_BASIC 0 2812 - #define IEEE80211_ML_CONTROL_TYPE_PREQ 1 2813 - #define IEEE80211_ML_CONTROL_TYPE_RECONF 2 2814 - #define IEEE80211_ML_CONTROL_TYPE_TDLS 3 2815 - #define IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS 4 2816 - #define IEEE80211_ML_CONTROL_PRESENCE_MASK 0xfff0 2817 - 2818 - struct ieee80211_multi_link_elem { 2819 - __le16 control; 2820 - u8 variable[]; 2821 - } __packed; 2822 - 2823 - #define IEEE80211_MLC_BASIC_PRES_LINK_ID 0x0010 2824 - #define IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT 0x0020 2825 - #define IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY 0x0040 2826 - #define IEEE80211_MLC_BASIC_PRES_EML_CAPA 0x0080 2827 - #define IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP 0x0100 2828 - #define IEEE80211_MLC_BASIC_PRES_MLD_ID 0x0200 2829 - #define IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP 0x0400 2830 - 2831 - #define IEEE80211_MED_SYNC_DELAY_DURATION 0x00ff 2832 - #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH 0x0f00 2833 - #define IEEE80211_MED_SYNC_DELAY_SYNC_MAX_NUM_TXOPS 0xf000 2834 - 2835 - /* 2836 - * Described in P802.11be_D3.0 2837 - * dot11MSDTimerDuration should default to 5484 (i.e. 171.375) 2838 - * dot11MSDOFDMEDthreshold defaults to -72 (i.e. 0) 2839 - * dot11MSDTXOPMAX defaults to 1 2840 - */ 2841 - #define IEEE80211_MED_SYNC_DELAY_DEFAULT 0x10ac 2842 - 2843 - #define IEEE80211_EML_CAP_EMLSR_SUPP 0x0001 2844 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY 0x000e 2845 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_0US 0 2846 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US 1 2847 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_64US 2 2848 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_128US 3 2849 - #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US 4 2850 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY 0x0070 2851 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_0US 0 2852 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_16US 1 2853 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_32US 2 2854 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US 3 2855 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_128US 4 2856 - #define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US 5 2857 - #define IEEE80211_EML_CAP_EMLMR_SUPPORT 0x0080 2858 - #define IEEE80211_EML_CAP_EMLMR_DELAY 0x0700 2859 - #define IEEE80211_EML_CAP_EMLMR_DELAY_0US 0 2860 - #define IEEE80211_EML_CAP_EMLMR_DELAY_32US 1 2861 - #define IEEE80211_EML_CAP_EMLMR_DELAY_64US 2 2862 - #define IEEE80211_EML_CAP_EMLMR_DELAY_128US 3 2863 - #define IEEE80211_EML_CAP_EMLMR_DELAY_256US 4 2864 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT 0x7800 2865 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_0 0 2866 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128US 1 2867 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_256US 2 2868 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_512US 3 2869 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_1TU 4 2870 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_2TU 5 2871 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_4TU 6 2872 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_8TU 7 2873 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_16TU 8 2874 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_32TU 9 2875 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_64TU 10 2876 - #define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU 11 2877 - 2878 - #define IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS 0x000f 2879 - #define IEEE80211_MLD_CAP_OP_SRS_SUPPORT 0x0010 2880 - #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP 0x0060 2881 - #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_NO_SUPP 0 2882 - #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME 1 2883 - #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_RESERVED 2 2884 - #define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_DIFF 3 2885 - #define IEEE80211_MLD_CAP_OP_FREQ_SEP_TYPE_IND 0x0f80 2886 - #define IEEE80211_MLD_CAP_OP_AAR_SUPPORT 0x1000 2887 - #define IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT 0x2000 2888 - #define IEEE80211_MLD_CAP_OP_ALIGNED_TWT_SUPPORT 0x4000 2889 - 2890 - struct ieee80211_mle_basic_common_info { 2891 - u8 len; 2892 - u8 mld_mac_addr[ETH_ALEN]; 2893 - u8 variable[]; 2894 - } __packed; 2895 - 2896 - #define IEEE80211_MLC_PREQ_PRES_MLD_ID 0x0010 2897 - 2898 - struct ieee80211_mle_preq_common_info { 2899 - u8 len; 2900 - u8 variable[]; 2901 - } __packed; 2902 - 2903 - #define IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR 0x0010 2904 - #define IEEE80211_MLC_RECONF_PRES_EML_CAPA 0x0020 2905 - #define IEEE80211_MLC_RECONF_PRES_MLD_CAPA_OP 0x0040 2906 - #define IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP 0x0080 2907 - 2908 - /* no fixed fields in RECONF */ 2909 - 2910 - struct ieee80211_mle_tdls_common_info { 2911 - u8 len; 2912 - u8 ap_mld_mac_addr[ETH_ALEN]; 2913 - } __packed; 2914 - 2915 - #define IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR 0x0010 2916 - 2917 - /* no fixed fields in PRIO_ACCESS */ 5353 + #include "ieee80211-ht.h" 5354 + #include "ieee80211-vht.h" 5355 + #include "ieee80211-he.h" 5356 + #include "ieee80211-eht.h" 5357 + #include "ieee80211-mesh.h" 5358 + #include "ieee80211-s1g.h" 5359 + #include "ieee80211-p2p.h" 5360 + #include "ieee80211-nan.h" 2918 5361 2919 5362 /** 2920 - * ieee80211_mle_common_size - check multi-link element common size 2921 - * @data: multi-link element, must already be checked for size using 2922 - * ieee80211_mle_size_ok() 2923 - * Return: the size of the multi-link element's "common" subfield 5363 + * ieee80211_check_tim - check if AID bit is set in TIM 5364 + * @tim: the TIM IE 5365 + * @tim_len: length of the TIM IE 5366 + * @aid: the AID to look for 5367 + * @s1g: whether the TIM is from an S1G PPDU 5368 + * Return: whether or not traffic is indicated in the TIM for the given AID 2924 5369 */ 2925 - static inline u8 ieee80211_mle_common_size(const u8 *data) 5370 + static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim, 5371 + u8 tim_len, u16 aid, bool s1g) 2926 5372 { 2927 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 2928 - u16 control = le16_to_cpu(mle->control); 2929 - 2930 - switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) { 2931 - case IEEE80211_ML_CONTROL_TYPE_BASIC: 2932 - case IEEE80211_ML_CONTROL_TYPE_PREQ: 2933 - case IEEE80211_ML_CONTROL_TYPE_TDLS: 2934 - case IEEE80211_ML_CONTROL_TYPE_RECONF: 2935 - case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS: 2936 - /* 2937 - * The length is the first octet pointed by mle->variable so no 2938 - * need to add anything 2939 - */ 2940 - break; 2941 - default: 2942 - WARN_ON(1); 2943 - return 0; 2944 - } 2945 - 2946 - return sizeof(*mle) + mle->variable[0]; 5373 + return s1g ? ieee80211_s1g_check_tim(tim, tim_len, aid) : 5374 + __ieee80211_check_tim(tim, tim_len, aid); 2947 5375 } 2948 - 2949 - /** 2950 - * ieee80211_mle_get_link_id - returns the link ID 2951 - * @data: the basic multi link element 2952 - * Return: the link ID, or -1 if not present 2953 - * 2954 - * The element is assumed to be of the correct type (BASIC) and big enough, 2955 - * this must be checked using ieee80211_mle_type_ok(). 2956 - */ 2957 - static inline int ieee80211_mle_get_link_id(const u8 *data) 2958 - { 2959 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 2960 - u16 control = le16_to_cpu(mle->control); 2961 - const u8 *common = mle->variable; 2962 - 2963 - /* common points now at the beginning of ieee80211_mle_basic_common_info */ 2964 - common += sizeof(struct ieee80211_mle_basic_common_info); 2965 - 2966 - if (!(control & IEEE80211_MLC_BASIC_PRES_LINK_ID)) 2967 - return -1; 2968 - 2969 - return *common; 2970 - } 2971 - 2972 - /** 2973 - * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count 2974 - * @data: pointer to the basic multi link element 2975 - * Return: the BSS Parameter Change Count field value, or -1 if not present 2976 - * 2977 - * The element is assumed to be of the correct type (BASIC) and big enough, 2978 - * this must be checked using ieee80211_mle_type_ok(). 2979 - */ 2980 - static inline int 2981 - ieee80211_mle_get_bss_param_ch_cnt(const u8 *data) 2982 - { 2983 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 2984 - u16 control = le16_to_cpu(mle->control); 2985 - const u8 *common = mle->variable; 2986 - 2987 - /* common points now at the beginning of ieee80211_mle_basic_common_info */ 2988 - common += sizeof(struct ieee80211_mle_basic_common_info); 2989 - 2990 - if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)) 2991 - return -1; 2992 - 2993 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 2994 - common += 1; 2995 - 2996 - return *common; 2997 - } 2998 - 2999 - /** 3000 - * ieee80211_mle_get_eml_med_sync_delay - returns the medium sync delay 3001 - * @data: pointer to the multi-link element 3002 - * Return: the medium synchronization delay field value from the multi-link 3003 - * element, or the default value (%IEEE80211_MED_SYNC_DELAY_DEFAULT) 3004 - * if not present 3005 - * 3006 - * The element is assumed to be of the correct type (BASIC) and big enough, 3007 - * this must be checked using ieee80211_mle_type_ok(). 3008 - */ 3009 - static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data) 3010 - { 3011 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3012 - u16 control = le16_to_cpu(mle->control); 3013 - const u8 *common = mle->variable; 3014 - 3015 - /* common points now at the beginning of ieee80211_mle_basic_common_info */ 3016 - common += sizeof(struct ieee80211_mle_basic_common_info); 3017 - 3018 - if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)) 3019 - return IEEE80211_MED_SYNC_DELAY_DEFAULT; 3020 - 3021 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3022 - common += 1; 3023 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3024 - common += 1; 3025 - 3026 - return get_unaligned_le16(common); 3027 - } 3028 - 3029 - /** 3030 - * ieee80211_mle_get_eml_cap - returns the EML capability 3031 - * @data: pointer to the multi-link element 3032 - * Return: the EML capability field value from the multi-link element, 3033 - * or 0 if not present 3034 - * 3035 - * The element is assumed to be of the correct type (BASIC) and big enough, 3036 - * this must be checked using ieee80211_mle_type_ok(). 3037 - */ 3038 - static inline u16 ieee80211_mle_get_eml_cap(const u8 *data) 3039 - { 3040 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3041 - u16 control = le16_to_cpu(mle->control); 3042 - const u8 *common = mle->variable; 3043 - 3044 - /* common points now at the beginning of ieee80211_mle_basic_common_info */ 3045 - common += sizeof(struct ieee80211_mle_basic_common_info); 3046 - 3047 - if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA)) 3048 - return 0; 3049 - 3050 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3051 - common += 1; 3052 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3053 - common += 1; 3054 - if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 3055 - common += 2; 3056 - 3057 - return get_unaligned_le16(common); 3058 - } 3059 - 3060 - /** 3061 - * ieee80211_mle_get_mld_capa_op - returns the MLD capabilities and operations. 3062 - * @data: pointer to the multi-link element 3063 - * Return: the MLD capabilities and operations field value from the multi-link 3064 - * element, or 0 if not present 3065 - * 3066 - * The element is assumed to be of the correct type (BASIC) and big enough, 3067 - * this must be checked using ieee80211_mle_type_ok(). 3068 - */ 3069 - static inline u16 ieee80211_mle_get_mld_capa_op(const u8 *data) 3070 - { 3071 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3072 - u16 control = le16_to_cpu(mle->control); 3073 - const u8 *common = mle->variable; 3074 - 3075 - /* 3076 - * common points now at the beginning of 3077 - * ieee80211_mle_basic_common_info 3078 - */ 3079 - common += sizeof(struct ieee80211_mle_basic_common_info); 3080 - 3081 - if (!(control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP)) 3082 - return 0; 3083 - 3084 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3085 - common += 1; 3086 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3087 - common += 1; 3088 - if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 3089 - common += 2; 3090 - if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 3091 - common += 2; 3092 - 3093 - return get_unaligned_le16(common); 3094 - } 3095 - 3096 - /* Defined in Figure 9-1074t in P802.11be_D7.0 */ 3097 - #define IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE 0x0001 3098 - #define IEEE80211_EHT_ML_EXT_MLD_CAPA_OP_RECO_MAX_LINKS_MASK 0x001e 3099 - #define IEEE80211_EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE 0x0020 3100 - #define IEEE80211_EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ON_ONE_LINK 0x0040 3101 - #define IEEE80211_EHT_ML_EXT_MLD_CAPA_BTM_MLD_RECO_MULTI_AP 0x0080 3102 - 3103 - /** 3104 - * ieee80211_mle_get_ext_mld_capa_op - returns the extended MLD capabilities 3105 - * and operations. 3106 - * @data: pointer to the multi-link element 3107 - * Return: the extended MLD capabilities and operations field value from 3108 - * the multi-link element, or 0 if not present 3109 - * 3110 - * The element is assumed to be of the correct type (BASIC) and big enough, 3111 - * this must be checked using ieee80211_mle_type_ok(). 3112 - */ 3113 - static inline u16 ieee80211_mle_get_ext_mld_capa_op(const u8 *data) 3114 - { 3115 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3116 - u16 control = le16_to_cpu(mle->control); 3117 - const u8 *common = mle->variable; 3118 - 3119 - /* 3120 - * common points now at the beginning of 3121 - * ieee80211_mle_basic_common_info 3122 - */ 3123 - common += sizeof(struct ieee80211_mle_basic_common_info); 3124 - 3125 - if (!(control & IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP)) 3126 - return 0; 3127 - 3128 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3129 - common += 1; 3130 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3131 - common += 1; 3132 - if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 3133 - common += 2; 3134 - if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 3135 - common += 2; 3136 - if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 3137 - common += 2; 3138 - if (control & IEEE80211_MLC_BASIC_PRES_MLD_ID) 3139 - common += 1; 3140 - 3141 - return get_unaligned_le16(common); 3142 - } 3143 - 3144 - /** 3145 - * ieee80211_mle_get_mld_id - returns the MLD ID 3146 - * @data: pointer to the multi-link element 3147 - * Return: The MLD ID in the given multi-link element, or 0 if not present 3148 - * 3149 - * The element is assumed to be of the correct type (BASIC) and big enough, 3150 - * this must be checked using ieee80211_mle_type_ok(). 3151 - */ 3152 - static inline u8 ieee80211_mle_get_mld_id(const u8 *data) 3153 - { 3154 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3155 - u16 control = le16_to_cpu(mle->control); 3156 - const u8 *common = mle->variable; 3157 - 3158 - /* 3159 - * common points now at the beginning of 3160 - * ieee80211_mle_basic_common_info 3161 - */ 3162 - common += sizeof(struct ieee80211_mle_basic_common_info); 3163 - 3164 - if (!(control & IEEE80211_MLC_BASIC_PRES_MLD_ID)) 3165 - return 0; 3166 - 3167 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3168 - common += 1; 3169 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3170 - common += 1; 3171 - if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 3172 - common += 2; 3173 - if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 3174 - common += 2; 3175 - if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 3176 - common += 2; 3177 - 3178 - return *common; 3179 - } 3180 - 3181 - /** 3182 - * ieee80211_mle_size_ok - validate multi-link element size 3183 - * @data: pointer to the element data 3184 - * @len: length of the containing element 3185 - * Return: whether or not the multi-link element size is OK 3186 - */ 3187 - static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len) 3188 - { 3189 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3190 - u8 fixed = sizeof(*mle); 3191 - u8 common = 0; 3192 - bool check_common_len = false; 3193 - u16 control; 3194 - 3195 - if (!data || len < fixed) 3196 - return false; 3197 - 3198 - control = le16_to_cpu(mle->control); 3199 - 3200 - switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) { 3201 - case IEEE80211_ML_CONTROL_TYPE_BASIC: 3202 - common += sizeof(struct ieee80211_mle_basic_common_info); 3203 - check_common_len = true; 3204 - if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID) 3205 - common += 1; 3206 - if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT) 3207 - common += 1; 3208 - if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY) 3209 - common += 2; 3210 - if (control & IEEE80211_MLC_BASIC_PRES_EML_CAPA) 3211 - common += 2; 3212 - if (control & IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP) 3213 - common += 2; 3214 - if (control & IEEE80211_MLC_BASIC_PRES_MLD_ID) 3215 - common += 1; 3216 - if (control & IEEE80211_MLC_BASIC_PRES_EXT_MLD_CAPA_OP) 3217 - common += 2; 3218 - break; 3219 - case IEEE80211_ML_CONTROL_TYPE_PREQ: 3220 - common += sizeof(struct ieee80211_mle_preq_common_info); 3221 - if (control & IEEE80211_MLC_PREQ_PRES_MLD_ID) 3222 - common += 1; 3223 - check_common_len = true; 3224 - break; 3225 - case IEEE80211_ML_CONTROL_TYPE_RECONF: 3226 - if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR) 3227 - common += ETH_ALEN; 3228 - if (control & IEEE80211_MLC_RECONF_PRES_EML_CAPA) 3229 - common += 2; 3230 - if (control & IEEE80211_MLC_RECONF_PRES_MLD_CAPA_OP) 3231 - common += 2; 3232 - if (control & IEEE80211_MLC_RECONF_PRES_EXT_MLD_CAPA_OP) 3233 - common += 2; 3234 - break; 3235 - case IEEE80211_ML_CONTROL_TYPE_TDLS: 3236 - common += sizeof(struct ieee80211_mle_tdls_common_info); 3237 - check_common_len = true; 3238 - break; 3239 - case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS: 3240 - common = ETH_ALEN + 1; 3241 - break; 3242 - default: 3243 - /* we don't know this type */ 3244 - return true; 3245 - } 3246 - 3247 - if (len < fixed + common) 3248 - return false; 3249 - 3250 - if (!check_common_len) 3251 - return true; 3252 - 3253 - /* if present, common length is the first octet there */ 3254 - return mle->variable[0] >= common; 3255 - } 3256 - 3257 - /** 3258 - * ieee80211_mle_type_ok - validate multi-link element type and size 3259 - * @data: pointer to the element data 3260 - * @type: expected type of the element 3261 - * @len: length of the containing element 3262 - * Return: whether or not the multi-link element type matches and size is OK 3263 - */ 3264 - static inline bool ieee80211_mle_type_ok(const u8 *data, u8 type, size_t len) 3265 - { 3266 - const struct ieee80211_multi_link_elem *mle = (const void *)data; 3267 - u16 control; 3268 - 3269 - if (!ieee80211_mle_size_ok(data, len)) 3270 - return false; 3271 - 3272 - control = le16_to_cpu(mle->control); 3273 - 3274 - if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) == type) 3275 - return true; 3276 - 3277 - return false; 3278 - } 3279 - 3280 - enum ieee80211_mle_subelems { 3281 - IEEE80211_MLE_SUBELEM_PER_STA_PROFILE = 0, 3282 - IEEE80211_MLE_SUBELEM_FRAGMENT = 254, 3283 - }; 3284 - 3285 - #define IEEE80211_MLE_STA_CONTROL_LINK_ID 0x000f 3286 - #define IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE 0x0010 3287 - #define IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT 0x0020 3288 - #define IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT 0x0040 3289 - #define IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT 0x0080 3290 - #define IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT 0x0100 3291 - #define IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT 0x0200 3292 - #define IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE 0x0400 3293 - #define IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT 0x0800 3294 - 3295 - struct ieee80211_mle_per_sta_profile { 3296 - __le16 control; 3297 - u8 sta_info_len; 3298 - u8 variable[]; 3299 - } __packed; 3300 - 3301 - /** 3302 - * ieee80211_mle_basic_sta_prof_size_ok - validate basic multi-link element sta 3303 - * profile size 3304 - * @data: pointer to the sub element data 3305 - * @len: length of the containing sub element 3306 - * Return: %true if the STA profile is large enough, %false otherwise 3307 - */ 3308 - static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data, 3309 - size_t len) 3310 - { 3311 - const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; 3312 - u16 control; 3313 - u8 fixed = sizeof(*prof); 3314 - u8 info_len = 1; 3315 - 3316 - if (len < fixed) 3317 - return false; 3318 - 3319 - control = le16_to_cpu(prof->control); 3320 - 3321 - if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) 3322 - info_len += 6; 3323 - if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) 3324 - info_len += 2; 3325 - if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) 3326 - info_len += 8; 3327 - if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) 3328 - info_len += 2; 3329 - if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && 3330 - control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) { 3331 - if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) 3332 - info_len += 2; 3333 - else 3334 - info_len += 1; 3335 - } 3336 - if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT) 3337 - info_len += 1; 3338 - 3339 - return prof->sta_info_len >= info_len && 3340 - fixed + prof->sta_info_len - 1 <= len; 3341 - } 3342 - 3343 - /** 3344 - * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS 3345 - * parameter change count 3346 - * @prof: the per-STA profile, having been checked with 3347 - * ieee80211_mle_basic_sta_prof_size_ok() for the correct length 3348 - * 3349 - * Return: The BSS parameter change count value if present, 0 otherwise. 3350 - */ 3351 - static inline u8 3352 - ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof) 3353 - { 3354 - u16 control = le16_to_cpu(prof->control); 3355 - const u8 *pos = prof->variable; 3356 - 3357 - if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)) 3358 - return 0; 3359 - 3360 - if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) 3361 - pos += 6; 3362 - if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) 3363 - pos += 2; 3364 - if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) 3365 - pos += 8; 3366 - if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) 3367 - pos += 2; 3368 - if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && 3369 - control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) { 3370 - if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) 3371 - pos += 2; 3372 - else 3373 - pos += 1; 3374 - } 3375 - 3376 - return *pos; 3377 - } 3378 - 3379 - #define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID 0x000f 3380 - #define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE 0x0010 3381 - #define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT 0x0020 3382 - #define IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT 0x0040 3383 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE 0x0780 3384 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_AP_REM 0 3385 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_OP_PARAM_UPDATE 1 3386 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_ADD_LINK 2 3387 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_DEL_LINK 3 3388 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_TYPE_NSTR_STATUS 4 3389 - #define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT 0x0800 3390 - 3391 - /** 3392 - * ieee80211_mle_reconf_sta_prof_size_ok - validate reconfiguration multi-link 3393 - * element sta profile size. 3394 - * @data: pointer to the sub element data 3395 - * @len: length of the containing sub element 3396 - * Return: %true if the STA profile is large enough, %false otherwise 3397 - */ 3398 - static inline bool ieee80211_mle_reconf_sta_prof_size_ok(const u8 *data, 3399 - size_t len) 3400 - { 3401 - const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; 3402 - u16 control; 3403 - u8 fixed = sizeof(*prof); 3404 - u8 info_len = 1; 3405 - 3406 - if (len < fixed) 3407 - return false; 3408 - 3409 - control = le16_to_cpu(prof->control); 3410 - 3411 - if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT) 3412 - info_len += ETH_ALEN; 3413 - if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT) 3414 - info_len += 2; 3415 - if (control & IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT) 3416 - info_len += 2; 3417 - 3418 - return prof->sta_info_len >= info_len && 3419 - fixed + prof->sta_info_len - 1 <= len; 3420 - } 3421 - 3422 - #define IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID 0x000f 3423 - #define IEEE80211_EPCS_ENA_RESP_BODY_LEN 3 3424 - 3425 - static inline bool ieee80211_tid_to_link_map_size_ok(const u8 *data, size_t len) 3426 - { 3427 - const struct ieee80211_ttlm_elem *t2l = (const void *)data; 3428 - u8 control, fixed = sizeof(*t2l), elem_len = 0; 3429 - 3430 - if (len < fixed) 3431 - return false; 3432 - 3433 - control = t2l->control; 3434 - 3435 - if (control & IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT) 3436 - elem_len += 2; 3437 - if (control & IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT) 3438 - elem_len += 3; 3439 - 3440 - if (!(control & IEEE80211_TTLM_CONTROL_DEF_LINK_MAP)) { 3441 - u8 bm_size; 3442 - 3443 - elem_len += 1; 3444 - if (len < fixed + elem_len) 3445 - return false; 3446 - 3447 - if (control & IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE) 3448 - bm_size = 1; 3449 - else 3450 - bm_size = 2; 3451 - 3452 - elem_len += hweight8(t2l->optional[0]) * bm_size; 3453 - } 3454 - 3455 - return len >= fixed + elem_len; 3456 - } 3457 - 3458 - /** 3459 - * ieee80211_emlsr_pad_delay_in_us - Fetch the EMLSR Padding delay 3460 - * in microseconds 3461 - * @eml_cap: EML capabilities field value from common info field of 3462 - * the Multi-link element 3463 - * Return: the EMLSR Padding delay (in microseconds) encoded in the 3464 - * EML Capabilities field 3465 - */ 3466 - 3467 - static inline u32 ieee80211_emlsr_pad_delay_in_us(u16 eml_cap) 3468 - { 3469 - /* IEEE Std 802.11be-2024 Table 9-417i—Encoding of the EMLSR 3470 - * Padding Delay subfield. 3471 - */ 3472 - u32 pad_delay = u16_get_bits(eml_cap, 3473 - IEEE80211_EML_CAP_EMLSR_PADDING_DELAY); 3474 - 3475 - if (!pad_delay || 3476 - pad_delay > IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US) 3477 - return 0; 3478 - 3479 - return 32 * (1 << (pad_delay - 1)); 3480 - } 3481 - 3482 - /** 3483 - * ieee80211_emlsr_trans_delay_in_us - Fetch the EMLSR Transition 3484 - * delay in microseconds 3485 - * @eml_cap: EML capabilities field value from common info field of 3486 - * the Multi-link element 3487 - * Return: the EMLSR Transition delay (in microseconds) encoded in the 3488 - * EML Capabilities field 3489 - */ 3490 - 3491 - static inline u32 ieee80211_emlsr_trans_delay_in_us(u16 eml_cap) 3492 - { 3493 - /* IEEE Std 802.11be-2024 Table 9-417j—Encoding of the EMLSR 3494 - * Transition Delay subfield. 3495 - */ 3496 - u32 trans_delay = 3497 - u16_get_bits(eml_cap, 3498 - IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY); 3499 - 3500 - /* invalid values also just use 0 */ 3501 - if (!trans_delay || 3502 - trans_delay > IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US) 3503 - return 0; 3504 - 3505 - return 16 * (1 << (trans_delay - 1)); 3506 - } 3507 - 3508 - /** 3509 - * ieee80211_eml_trans_timeout_in_us - Fetch the EMLSR Transition 3510 - * timeout value in microseconds 3511 - * @eml_cap: EML capabilities field value from common info field of 3512 - * the Multi-link element 3513 - * Return: the EMLSR Transition timeout (in microseconds) encoded in 3514 - * the EML Capabilities field 3515 - */ 3516 - 3517 - static inline u32 ieee80211_eml_trans_timeout_in_us(u16 eml_cap) 3518 - { 3519 - /* IEEE Std 802.11be-2024 Table 9-417m—Encoding of the 3520 - * Transition Timeout subfield. 3521 - */ 3522 - u8 timeout = u16_get_bits(eml_cap, 3523 - IEEE80211_EML_CAP_TRANSITION_TIMEOUT); 3524 - 3525 - /* invalid values also just use 0 */ 3526 - if (!timeout || timeout > IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU) 3527 - return 0; 3528 - 3529 - return 128 * (1 << (timeout - 1)); 3530 - } 3531 - 3532 - #define for_each_mle_subelement(_elem, _data, _len) \ 3533 - if (ieee80211_mle_size_ok(_data, _len)) \ 3534 - for_each_element(_elem, \ 3535 - _data + ieee80211_mle_common_size(_data),\ 3536 - _len - ieee80211_mle_common_size(_data)) 3537 - 3538 - /* NAN operation mode, as defined in Wi-Fi Aware (TM) specification Table 81 */ 3539 - #define NAN_OP_MODE_PHY_MODE_VHT 0x01 3540 - #define NAN_OP_MODE_PHY_MODE_HE 0x10 3541 - #define NAN_OP_MODE_PHY_MODE_MASK 0x11 3542 - #define NAN_OP_MODE_80P80MHZ 0x02 3543 - #define NAN_OP_MODE_160MHZ 0x04 3544 - #define NAN_OP_MODE_PNDL_SUPPRTED 0x08 3545 - 3546 - /* NAN Device capabilities, as defined in Wi-Fi Aware (TM) specification 3547 - * Table 79 3548 - */ 3549 - #define NAN_DEV_CAPA_DFS_OWNER 0x01 3550 - #define NAN_DEV_CAPA_EXT_KEY_ID_SUPPORTED 0x02 3551 - #define NAN_DEV_CAPA_SIM_NDP_RX_SUPPORTED 0x04 3552 - #define NAN_DEV_CAPA_NDPE_SUPPORTED 0x08 3553 - #define NAN_DEV_CAPA_S3_SUPPORTED 0x10 3554 5376 3555 5377 #endif /* LINUX_IEEE80211_H */
+31 -3
include/net/cfg80211.h
··· 685 685 } 686 686 687 687 /** 688 - * ieee80211_get_eht_iftype_cap - return ETH capabilities for an sband's iftype 688 + * ieee80211_get_eht_iftype_cap - return EHT capabilities for an sband's iftype 689 689 * @sband: the sband to search for the iftype on 690 690 * @iftype: enum nl80211_iftype 691 691 * ··· 786 786 * @key: key material 787 787 * @key_len: length of key material 788 788 * @cipher: cipher suite selector 789 - * @seq: sequence counter (IV/PN) for TKIP and CCMP keys, only used 790 - * with the get_key() callback, must be in little endian, 789 + * @seq: sequence counter (IV/PN), must be in little endian, 791 790 * length given by @seq_len. 792 791 * @seq_len: length of @seq. 793 792 * @vlan_id: vlan_id for VLAN group key (if nonzero) ··· 10132 10133 return cfg80211_bss_color_notify(dev, 10133 10134 NL80211_CMD_COLOR_CHANGE_COMPLETED, 10134 10135 0, 0, link_id); 10136 + } 10137 + 10138 + /** 10139 + * cfg80211_6ghz_power_type - determine AP regulatory power type 10140 + * @control: control flags 10141 + * @client_flags: &enum ieee80211_channel_flags for station mode to enable 10142 + * SP to LPI fallback, zero otherwise. 10143 + * 10144 + * Return: regulatory power type from &enum ieee80211_ap_reg_power 10145 + */ 10146 + static inline enum ieee80211_ap_reg_power 10147 + cfg80211_6ghz_power_type(u8 control, u32 client_flags) 10148 + { 10149 + switch (u8_get_bits(control, IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) { 10150 + case IEEE80211_6GHZ_CTRL_REG_LPI_AP: 10151 + case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP: 10152 + return IEEE80211_REG_LPI_AP; 10153 + case IEEE80211_6GHZ_CTRL_REG_SP_AP: 10154 + case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD: 10155 + return IEEE80211_REG_SP_AP; 10156 + case IEEE80211_6GHZ_CTRL_REG_VLP_AP: 10157 + return IEEE80211_REG_VLP_AP; 10158 + case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP: 10159 + if (client_flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT) 10160 + return IEEE80211_REG_LPI_AP; 10161 + return IEEE80211_REG_SP_AP; 10162 + default: 10163 + return IEEE80211_REG_UNSET_AP; 10164 + } 10135 10165 } 10136 10166 10137 10167 /**
+1 -1
include/net/mac80211.h
··· 7223 7223 } 7224 7224 7225 7225 /** 7226 - * ieee80211_get_eht_iftype_cap_vif - return ETH capabilities for sband/vif 7226 + * ieee80211_get_eht_iftype_cap_vif - return EHT capabilities for sband/vif 7227 7227 * @sband: the sband to search for the iftype on 7228 7228 * @vif: the vif to get the iftype from 7229 7229 *
+5 -2
net/mac80211/agg-rx.c
··· 9 9 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 10 10 * Copyright 2007-2010, Intel Corporation 11 11 * Copyright(c) 2015-2017 Intel Deutschland GmbH 12 - * Copyright (C) 2018-2024 Intel Corporation 12 + * Copyright (C) 2018-2025 Intel Corporation 13 13 */ 14 14 15 15 /** ··· 206 206 if (elem_len <= 0) 207 207 return 0; 208 208 209 - elems = ieee802_11_parse_elems(elem_data, elem_len, true, NULL); 209 + elems = ieee802_11_parse_elems(elem_data, elem_len, 210 + IEEE80211_FTYPE_MGMT | 211 + IEEE80211_STYPE_ACTION, 212 + NULL); 210 213 211 214 if (!elems || elems->parse_error || !elems->addba_ext_ie) 212 215 goto free;
+32 -15
net/mac80211/cfg.c
··· 63 63 memcpy(sdata->vif.bss_conf.mu_group.position, 64 64 params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN, 65 65 WLAN_USER_POSITION_LEN); 66 - ieee80211_link_info_change_notify(sdata, &sdata->deflink, 67 - BSS_CHANGED_MU_GROUPS); 66 + 68 67 /* don't care about endianness - just check for 0 */ 69 68 memcpy(&membership, params->vht_mumimo_groups, 70 69 WLAN_MEMBERSHIP_LEN); 71 70 mu_mimo_groups = membership != 0; 71 + 72 + /* Unset following if configured explicitly */ 73 + eth_broadcast_addr(sdata->u.mntr.mu_follow_addr); 72 74 } 73 75 74 76 if (params->vht_mumimo_follow_addr) { ··· 78 76 is_valid_ether_addr(params->vht_mumimo_follow_addr); 79 77 ether_addr_copy(sdata->u.mntr.mu_follow_addr, 80 78 params->vht_mumimo_follow_addr); 79 + 80 + /* Unset current membership until a management frame is RXed */ 81 + memset(sdata->vif.bss_conf.mu_group.membership, 0, 82 + WLAN_MEMBERSHIP_LEN); 81 83 } 82 84 83 85 sdata->vif.bss_conf.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow; 86 + 87 + /* Notify only after setting mu_mimo_owner */ 88 + if (sdata->vif.bss_conf.mu_mimo_owner && 89 + sdata->flags & IEEE80211_SDATA_IN_DRIVER) 90 + ieee80211_link_info_change_notify(sdata, &sdata->deflink, 91 + BSS_CHANGED_MU_GROUPS); 84 92 } 85 93 86 94 static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, 87 95 struct vif_params *params) 88 96 { 89 97 struct ieee80211_local *local = sdata->local; 90 - struct ieee80211_sub_if_data *monitor_sdata; 98 + struct ieee80211_sub_if_data *monitor_sdata = NULL; 91 99 92 100 /* check flags first */ 93 101 if (params->flags && ieee80211_sdata_running(sdata)) { ··· 115 103 return -EBUSY; 116 104 } 117 105 118 - /* also validate MU-MIMO change */ 119 - if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) 120 - monitor_sdata = sdata; 121 - else 122 - monitor_sdata = wiphy_dereference(local->hw.wiphy, 123 - local->monitor_sdata); 124 - 125 - if (!monitor_sdata && 106 + /* validate whether MU-MIMO can be configured */ 107 + if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && 108 + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && 126 109 (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) 127 110 return -EOPNOTSUPP; 128 111 112 + /* Also update dependent monitor_sdata if required */ 113 + if (test_bit(SDATA_STATE_RUNNING, &sdata->state) && 114 + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) 115 + monitor_sdata = wiphy_dereference(local->hw.wiphy, 116 + local->monitor_sdata); 117 + 129 118 /* apply all changes now - no failures allowed */ 130 119 131 - if (monitor_sdata && 132 - (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) || 133 - ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))) 134 - ieee80211_set_mu_mimo_follow(monitor_sdata, params); 120 + if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) || 121 + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { 122 + /* This is copied in when the VIF is activated */ 123 + ieee80211_set_mu_mimo_follow(sdata, params); 124 + 125 + if (monitor_sdata) 126 + ieee80211_set_mu_mimo_follow(monitor_sdata, params); 127 + } 135 128 136 129 if (params->flags) { 137 130 if (ieee80211_sdata_running(sdata)) {
+235 -162
net/mac80211/chan.c
··· 12 12 #include "driver-ops.h" 13 13 #include "rate.h" 14 14 15 + struct ieee80211_chanctx_user_iter { 16 + struct ieee80211_chan_req *chanreq; 17 + struct ieee80211_sub_if_data *sdata; 18 + struct ieee80211_link_data *link; 19 + enum nl80211_iftype iftype; 20 + bool reserved, radar_required, done; 21 + enum { 22 + CHANCTX_ITER_POS_ASSIGNED, 23 + CHANCTX_ITER_POS_RESERVED, 24 + CHANCTX_ITER_POS_DONE, 25 + } per_link; 26 + }; 27 + 28 + enum ieee80211_chanctx_iter_type { 29 + CHANCTX_ITER_ALL, 30 + CHANCTX_ITER_RESERVED, 31 + CHANCTX_ITER_ASSIGNED, 32 + }; 33 + 34 + static void ieee80211_chanctx_user_iter_next(struct ieee80211_local *local, 35 + struct ieee80211_chanctx *ctx, 36 + struct ieee80211_chanctx_user_iter *iter, 37 + enum ieee80211_chanctx_iter_type type, 38 + bool start) 39 + { 40 + lockdep_assert_wiphy(local->hw.wiphy); 41 + 42 + if (start) { 43 + memset(iter, 0, sizeof(*iter)); 44 + goto next_interface; 45 + } 46 + 47 + next_link: 48 + for (int link_id = iter->link ? iter->link->link_id : 0; 49 + link_id < ARRAY_SIZE(iter->sdata->link); 50 + link_id++) { 51 + struct ieee80211_link_data *link; 52 + 53 + link = sdata_dereference(iter->sdata->link[link_id], 54 + iter->sdata); 55 + if (!link) 56 + continue; 57 + 58 + switch (iter->per_link) { 59 + case CHANCTX_ITER_POS_ASSIGNED: 60 + iter->per_link = CHANCTX_ITER_POS_RESERVED; 61 + if (type != CHANCTX_ITER_RESERVED && 62 + rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) { 63 + iter->link = link; 64 + iter->reserved = false; 65 + iter->radar_required = link->radar_required; 66 + iter->chanreq = &link->conf->chanreq; 67 + return; 68 + } 69 + fallthrough; 70 + case CHANCTX_ITER_POS_RESERVED: 71 + iter->per_link = CHANCTX_ITER_POS_DONE; 72 + if (type != CHANCTX_ITER_ASSIGNED && 73 + link->reserved_chanctx == ctx) { 74 + iter->link = link; 75 + iter->reserved = true; 76 + iter->radar_required = 77 + link->reserved_radar_required; 78 + 79 + iter->chanreq = &link->reserved; 80 + return; 81 + } 82 + fallthrough; 83 + case CHANCTX_ITER_POS_DONE: 84 + iter->per_link = CHANCTX_ITER_POS_ASSIGNED; 85 + continue; 86 + } 87 + } 88 + 89 + next_interface: 90 + /* next (or first) interface */ 91 + iter->sdata = list_prepare_entry(iter->sdata, &local->interfaces, list); 92 + list_for_each_entry_continue(iter->sdata, &local->interfaces, list) { 93 + /* AP_VLAN has a chanctx pointer but follows AP */ 94 + if (iter->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 95 + continue; 96 + 97 + iter->link = NULL; 98 + iter->per_link = CHANCTX_ITER_POS_ASSIGNED; 99 + iter->iftype = iter->sdata->vif.type; 100 + goto next_link; 101 + } 102 + 103 + iter->done = true; 104 + } 105 + 106 + #define for_each_chanctx_user_assigned(local, ctx, iter) \ 107 + for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 108 + CHANCTX_ITER_ASSIGNED, \ 109 + true); \ 110 + !((iter)->done); \ 111 + ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 112 + CHANCTX_ITER_ASSIGNED, \ 113 + false)) 114 + 115 + #define for_each_chanctx_user_reserved(local, ctx, iter) \ 116 + for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 117 + CHANCTX_ITER_RESERVED, \ 118 + true); \ 119 + !((iter)->done); \ 120 + ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 121 + CHANCTX_ITER_RESERVED, \ 122 + false)) 123 + 124 + #define for_each_chanctx_user_all(local, ctx, iter) \ 125 + for (ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 126 + CHANCTX_ITER_ALL, \ 127 + true); \ 128 + !((iter)->done); \ 129 + ieee80211_chanctx_user_iter_next(local, ctx, iter, \ 130 + CHANCTX_ITER_ALL, \ 131 + false)) 132 + 15 133 static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local, 16 134 struct ieee80211_chanctx *ctx) 17 135 { 18 - struct ieee80211_link_data *link; 136 + struct ieee80211_chanctx_user_iter iter; 19 137 int num = 0; 20 138 21 - lockdep_assert_wiphy(local->hw.wiphy); 22 - 23 - list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) 139 + for_each_chanctx_user_assigned(local, ctx, &iter) 24 140 num++; 25 141 26 142 return num; ··· 145 29 static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local, 146 30 struct ieee80211_chanctx *ctx) 147 31 { 148 - struct ieee80211_link_data *link; 32 + struct ieee80211_chanctx_user_iter iter; 149 33 int num = 0; 150 34 151 - lockdep_assert_wiphy(local->hw.wiphy); 152 - 153 - list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) 35 + for_each_chanctx_user_reserved(local, ctx, &iter) 154 36 num++; 155 37 156 38 return num; ··· 157 43 int ieee80211_chanctx_refcount(struct ieee80211_local *local, 158 44 struct ieee80211_chanctx *ctx) 159 45 { 160 - return ieee80211_chanctx_num_assigned(local, ctx) + 161 - ieee80211_chanctx_num_reserved(local, ctx); 46 + struct ieee80211_chanctx_user_iter iter; 47 + int num = 0; 48 + 49 + for_each_chanctx_user_all(local, ctx, &iter) 50 + num++; 51 + 52 + return num; 162 53 } 163 54 164 55 static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx) ··· 262 143 const struct ieee80211_chan_req *req, 263 144 struct ieee80211_chan_req *tmp) 264 145 { 265 - struct ieee80211_link_data *link; 146 + struct ieee80211_chanctx_user_iter iter; 266 147 267 148 lockdep_assert_wiphy(local->hw.wiphy); 268 149 269 150 if (WARN_ON(!req)) 270 151 return NULL; 271 152 272 - list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) { 273 - req = ieee80211_chanreq_compatible(&link->reserved, req, tmp); 153 + for_each_chanctx_user_reserved(local, ctx, &iter) { 154 + req = ieee80211_chanreq_compatible(iter.chanreq, req, tmp); 274 155 if (!req) 275 156 break; 276 157 } ··· 284 165 const struct ieee80211_chan_req *compat, 285 166 struct ieee80211_chan_req *tmp) 286 167 { 287 - struct ieee80211_link_data *link; 288 168 const struct ieee80211_chan_req *comp_def = compat; 169 + struct ieee80211_chanctx_user_iter iter; 289 170 290 171 lockdep_assert_wiphy(local->hw.wiphy); 291 172 292 - list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) { 293 - struct ieee80211_bss_conf *link_conf = link->conf; 294 - 295 - if (link->reserved_chanctx) 173 + for_each_chanctx_user_assigned(local, ctx, &iter) { 174 + if (iter.link->reserved_chanctx) 296 175 continue; 297 176 298 - comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq, 177 + comp_def = ieee80211_chanreq_compatible(iter.chanreq, 299 178 comp_def, tmp); 300 179 if (!comp_def) 301 180 break; ··· 317 200 if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp)) 318 201 return false; 319 202 320 - if (!list_empty(&ctx->reserved_links) && 203 + if (ieee80211_chanctx_num_reserved(local, ctx) != 0 && 321 204 ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp)) 322 205 return true; 323 206 ··· 506 389 * channel context. 507 390 */ 508 391 static u32 509 - _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 510 - struct ieee80211_chanctx *ctx, 511 - struct ieee80211_link_data *rsvd_for, 512 - bool check_reserved) 392 + __ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 393 + struct ieee80211_chanctx *ctx, 394 + struct ieee80211_link_data *rsvd_for, 395 + bool check_reserved) 513 396 { 514 397 enum nl80211_chan_width max_bw; 515 398 struct cfg80211_chan_def min_def; ··· 614 497 * the max of min required widths of all the interfaces bound to this 615 498 * channel context. 616 499 */ 617 - void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 618 - struct ieee80211_chanctx *ctx, 619 - struct ieee80211_link_data *rsvd_for, 620 - bool check_reserved) 500 + static void 501 + _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 502 + struct ieee80211_chanctx *ctx, 503 + struct ieee80211_link_data *rsvd_for, 504 + bool check_reserved) 621 505 { 622 - u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, 623 - check_reserved); 506 + u32 changed = __ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, 507 + check_reserved); 624 508 625 509 if (!changed) 626 510 return; ··· 633 515 634 516 /* check is BW wider */ 635 517 ieee80211_chan_bw_change(local, ctx, false, false); 518 + } 519 + 520 + void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 521 + struct ieee80211_chanctx *ctx) 522 + { 523 + _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false); 636 524 } 637 525 638 526 static void _ieee80211_change_chanctx(struct ieee80211_local *local, ··· 675 551 ieee80211_chan_bw_change(local, old_ctx, false, true); 676 552 677 553 if (ieee80211_chanreq_identical(&ctx_req, chanreq)) { 678 - ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false); 554 + _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false); 679 555 return; 680 556 } 681 557 ··· 696 572 ctx->conf.ap = chanreq->ap; 697 573 698 574 /* check if min chanctx also changed */ 699 - changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false); 575 + changed |= __ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, 576 + false); 700 577 701 578 ieee80211_add_wbrf(local, &ctx->conf.def); 702 579 ··· 758 633 * context to actually be removed. 759 634 */ 760 635 link->reserved_chanctx = ctx; 761 - list_add(&link->reserved_chanctx_list, 762 - &ctx->reserved_links); 763 636 764 637 ieee80211_change_chanctx(local, ctx, ctx, compat); 765 638 ··· 798 675 ieee80211_chanctx_radar_required(struct ieee80211_local *local, 799 676 struct ieee80211_chanctx *ctx) 800 677 { 801 - struct ieee80211_chanctx_conf *conf = &ctx->conf; 802 - struct ieee80211_link_data *link; 678 + struct ieee80211_chanctx_user_iter iter; 803 679 804 680 lockdep_assert_wiphy(local->hw.wiphy); 805 681 806 - for_each_sdata_link(local, link) { 807 - if (rcu_access_pointer(link->conf->chanctx_conf) != conf) 808 - continue; 809 - if (!link->radar_required) 810 - continue; 811 - return true; 682 + for_each_chanctx_user_assigned(local, ctx, &iter) { 683 + if (iter.radar_required) 684 + return true; 812 685 } 813 686 814 687 return false; ··· 824 705 if (!ctx) 825 706 return NULL; 826 707 827 - INIT_LIST_HEAD(&ctx->assigned_links); 828 - INIT_LIST_HEAD(&ctx->reserved_links); 829 708 ctx->conf.def = chanreq->oper; 830 709 ctx->conf.ap = chanreq->ap; 831 710 ctx->conf.rx_chains_static = 1; ··· 832 715 ctx->conf.radar_enabled = false; 833 716 ctx->conf.radio_idx = radio_idx; 834 717 ctx->radar_detected = false; 835 - _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false); 718 + __ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false); 836 719 837 720 return ctx; 838 721 } ··· 921 804 { 922 805 struct ieee80211_chanctx_conf *conf = &ctx->conf; 923 806 const struct ieee80211_chan_req *compat = NULL; 924 - struct ieee80211_link_data *link; 807 + struct ieee80211_chanctx_user_iter iter; 925 808 struct ieee80211_chan_req tmp; 926 809 struct sta_info *sta; 927 810 928 811 lockdep_assert_wiphy(local->hw.wiphy); 929 812 930 - for_each_sdata_link(local, link) { 931 - struct ieee80211_bss_conf *link_conf; 932 - 933 - if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 934 - continue; 935 - 936 - link_conf = link->conf; 937 - 938 - if (rcu_access_pointer(link_conf->chanctx_conf) != conf) 939 - continue; 940 - 813 + for_each_chanctx_user_assigned(local, ctx, &iter) { 941 814 if (!compat) 942 - compat = &link_conf->chanreq; 815 + compat = iter.chanreq; 943 816 944 - compat = ieee80211_chanreq_compatible(&link_conf->chanreq, 817 + compat = ieee80211_chanreq_compatible(iter.chanreq, 945 818 compat, &tmp); 946 819 if (WARN_ON_ONCE(!compat)) 947 820 return; ··· 944 837 list_for_each_entry(sta, &local->sta_list, list) { 945 838 struct ieee80211_sub_if_data *sdata = sta->sdata; 946 839 struct ieee80211_chan_req tdls_chanreq = {}; 840 + struct ieee80211_link_data *link; 947 841 int tdls_link_id; 948 842 949 843 if (!sta->uploaded || ··· 1012 904 1013 905 drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx); 1014 906 conf = NULL; 1015 - list_del(&link->assigned_chanctx_list); 1016 907 } 1017 908 1018 909 if (new_ctx) { 1019 910 /* recalc considering the link we'll use it for now */ 1020 - ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false); 911 + _ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false); 1021 912 1022 913 ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx); 1023 914 if (assign_on_failure || !ret) { ··· 1026 919 1027 920 /* succeeded, so commit it to the data structures */ 1028 921 conf = &new_ctx->conf; 1029 - if (!local->in_reconfig) 1030 - list_add(&link->assigned_chanctx_list, 1031 - &new_ctx->assigned_links); 1032 922 } 1033 923 } else { 1034 924 ret = 0; ··· 1037 933 ieee80211_recalc_chanctx_chantype(local, curr_ctx); 1038 934 ieee80211_recalc_smps_chanctx(local, curr_ctx); 1039 935 ieee80211_recalc_radar_chanctx(local, curr_ctx); 1040 - ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL, false); 936 + ieee80211_recalc_chanctx_min_def(local, curr_ctx); 1041 937 } 1042 938 1043 939 if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { 1044 940 ieee80211_recalc_txpower(link, false); 1045 - ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false); 941 + ieee80211_recalc_chanctx_min_def(local, new_ctx); 1046 942 } 1047 943 1048 944 if (conf) { ··· 1075 971 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 1076 972 struct ieee80211_chanctx *chanctx) 1077 973 { 974 + struct ieee80211_chanctx_user_iter iter; 1078 975 struct ieee80211_sub_if_data *sdata; 1079 976 u8 rx_chains_static, rx_chains_dynamic; 1080 - struct ieee80211_link_data *link; 1081 977 1082 978 lockdep_assert_wiphy(local->hw.wiphy); 1083 979 1084 980 rx_chains_static = 1; 1085 981 rx_chains_dynamic = 1; 1086 982 1087 - for_each_sdata_link(local, link) { 983 + for_each_chanctx_user_assigned(local, chanctx, &iter) { 1088 984 u8 needed_static, needed_dynamic; 1089 985 1090 - switch (link->sdata->vif.type) { 986 + switch (iter.iftype) { 1091 987 case NL80211_IFTYPE_STATION: 1092 - if (!link->sdata->u.mgd.associated) 988 + if (!iter.sdata->u.mgd.associated) 1093 989 continue; 1094 990 break; 1095 991 case NL80211_IFTYPE_MONITOR: ··· 1105 1001 continue; 1106 1002 } 1107 1003 1108 - if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf) 1109 - continue; 1110 - 1111 - if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) { 1004 + if (iter.iftype == NL80211_IFTYPE_MONITOR) { 1112 1005 rx_chains_dynamic = rx_chains_static = local->rx_chains; 1113 1006 break; 1114 1007 } 1115 1008 1116 - switch (link->smps_mode) { 1009 + switch (iter.link->smps_mode) { 1117 1010 default: 1118 1011 WARN_ONCE(1, "Invalid SMPS mode %d\n", 1119 - link->smps_mode); 1012 + iter.link->smps_mode); 1120 1013 fallthrough; 1121 1014 case IEEE80211_SMPS_OFF: 1122 - needed_static = link->needed_rx_chains; 1123 - needed_dynamic = link->needed_rx_chains; 1015 + needed_static = iter.link->needed_rx_chains; 1016 + needed_dynamic = iter.link->needed_rx_chains; 1124 1017 break; 1125 1018 case IEEE80211_SMPS_DYNAMIC: 1126 1019 needed_static = 1; 1127 - needed_dynamic = link->needed_rx_chains; 1020 + needed_dynamic = iter.link->needed_rx_chains; 1128 1021 break; 1129 1022 case IEEE80211_SMPS_STATIC: 1130 1023 needed_static = 1; ··· 1209 1108 if (WARN_ON(!ctx)) 1210 1109 return; 1211 1110 1212 - list_del(&link->reserved_chanctx_list); 1213 1111 link->reserved_chanctx = NULL; 1214 1112 1215 1113 if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) { ··· 1242 1142 struct wiphy *wiphy = local->hw.wiphy; 1243 1143 const struct wiphy_radio *radio; 1244 1144 1245 - if (!curr_ctx || (curr_ctx->replace_state == 1246 - IEEE80211_CHANCTX_WILL_BE_REPLACED) || 1247 - !list_empty(&curr_ctx->reserved_links)) { 1145 + if (!curr_ctx || 1146 + curr_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED || 1147 + ieee80211_chanctx_num_reserved(local, curr_ctx) != 0) { 1248 1148 /* 1249 1149 * Another link already requested this context for a 1250 1150 * reservation. Find another one hoping all links assigned ··· 1267 1167 IEEE80211_CHANCTX_REPLACE_NONE) 1268 1168 continue; 1269 1169 1270 - if (!list_empty(&ctx->reserved_links)) 1170 + if (ieee80211_chanctx_num_reserved(local, ctx) != 0) 1271 1171 continue; 1272 1172 1273 1173 if (ctx->conf.radio_idx >= 0) { ··· 1285 1185 * If that's true then all available contexts already have reservations 1286 1186 * and cannot be used. 1287 1187 */ 1288 - if (!curr_ctx || (curr_ctx->replace_state == 1289 - IEEE80211_CHANCTX_WILL_BE_REPLACED) || 1290 - !list_empty(&curr_ctx->reserved_links)) 1188 + if (!curr_ctx || 1189 + curr_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED || 1190 + ieee80211_chanctx_num_reserved(local, curr_ctx) != 0) 1291 1191 return ERR_PTR(-EBUSY); 1292 1192 1293 1193 new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); ··· 1367 1267 return PTR_ERR(new_ctx); 1368 1268 } 1369 1269 1370 - list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links); 1371 1270 link->reserved_chanctx = new_ctx; 1372 1271 link->reserved = *chanreq; 1373 1272 link->reserved_radar_required = radar_required; ··· 1480 1381 vif_chsw[0].new_ctx = &new_ctx->conf; 1481 1382 vif_chsw[0].link_conf = link->conf; 1482 1383 1483 - list_del(&link->reserved_chanctx_list); 1484 1384 link->reserved_chanctx = NULL; 1485 1385 1486 1386 err = drv_switch_vif_chanctx(local, vif_chsw, 1, ··· 1492 1394 } 1493 1395 1494 1396 link->radar_required = link->reserved_radar_required; 1495 - list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links); 1496 1397 rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf); 1497 1398 1498 1399 if (sdata->vif.type == NL80211_IFTYPE_AP) ··· 1502 1405 if (ieee80211_chanctx_refcount(local, old_ctx) == 0) 1503 1406 ieee80211_free_chanctx(local, old_ctx, false); 1504 1407 1505 - ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false); 1408 + ieee80211_recalc_chanctx_min_def(local, new_ctx); 1506 1409 ieee80211_recalc_smps_chanctx(local, new_ctx); 1507 1410 ieee80211_recalc_radar_chanctx(local, new_ctx); 1508 1411 ··· 1548 1451 1549 1452 ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq); 1550 1453 1551 - list_del(&link->reserved_chanctx_list); 1552 1454 link->reserved_chanctx = NULL; 1553 1455 1554 1456 err = ieee80211_assign_link_chanctx(link, new_ctx, false); ··· 1593 1497 int n_vifs) 1594 1498 { 1595 1499 struct ieee80211_vif_chanctx_switch *vif_chsw; 1596 - struct ieee80211_link_data *link; 1597 1500 struct ieee80211_chanctx *ctx, *old_ctx; 1598 1501 int i, err; 1599 1502 ··· 1604 1509 1605 1510 i = 0; 1606 1511 list_for_each_entry(ctx, &local->chanctx_list, list) { 1512 + struct ieee80211_chanctx_user_iter iter; 1513 + 1607 1514 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1608 1515 continue; 1609 1516 ··· 1614 1517 goto out; 1615 1518 } 1616 1519 1617 - list_for_each_entry(link, &ctx->reserved_links, 1618 - reserved_chanctx_list) { 1619 - if (!ieee80211_link_has_in_place_reservation(link)) 1520 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1521 + if (!ieee80211_link_has_in_place_reservation(iter.link)) 1620 1522 continue; 1621 1523 1622 - old_ctx = ieee80211_link_get_chanctx(link); 1623 - vif_chsw[i].vif = &link->sdata->vif; 1524 + old_ctx = ieee80211_link_get_chanctx(iter.link); 1525 + vif_chsw[i].vif = &iter.sdata->vif; 1624 1526 vif_chsw[i].old_ctx = &old_ctx->conf; 1625 1527 vif_chsw[i].new_ctx = &ctx->conf; 1626 - vif_chsw[i].link_conf = link->conf; 1528 + vif_chsw[i].link_conf = iter.link->conf; 1627 1529 1628 1530 i++; 1629 1531 } ··· 1647 1551 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1648 1552 continue; 1649 1553 1650 - if (!list_empty(&ctx->replace_ctx->assigned_links)) 1554 + if (ieee80211_chanctx_num_assigned(local, ctx) != 0) 1651 1555 continue; 1652 1556 1653 1557 ieee80211_del_chanctx(local, ctx->replace_ctx, false); ··· 1664 1568 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1665 1569 continue; 1666 1570 1667 - if (!list_empty(&ctx->replace_ctx->assigned_links)) 1571 + if (ieee80211_chanctx_num_assigned(local, ctx) != 0) 1668 1572 continue; 1669 1573 1670 1574 ieee80211_del_chanctx(local, ctx, false); ··· 1699 1603 */ 1700 1604 1701 1605 list_for_each_entry(ctx, &local->chanctx_list, list) { 1702 - struct ieee80211_link_data *link; 1606 + struct ieee80211_chanctx_user_iter iter; 1703 1607 1704 1608 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1705 1609 continue; ··· 1715 1619 n_reserved = 0; 1716 1620 n_ready = 0; 1717 1621 1718 - list_for_each_entry(link, &ctx->replace_ctx->assigned_links, 1719 - assigned_chanctx_list) { 1622 + for_each_chanctx_user_assigned(local, ctx, &iter) { 1720 1623 n_assigned++; 1721 - if (link->reserved_chanctx) { 1624 + if (iter.link->reserved_chanctx) { 1722 1625 n_reserved++; 1723 - if (link->reserved_ready) 1626 + if (iter.link->reserved_ready) 1724 1627 n_ready++; 1725 1628 } 1726 1629 } ··· 1736 1641 } 1737 1642 1738 1643 ctx->conf.radar_enabled = false; 1739 - list_for_each_entry(link, &ctx->reserved_links, 1740 - reserved_chanctx_list) { 1741 - if (ieee80211_link_has_in_place_reservation(link) && 1742 - !link->reserved_ready) 1644 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1645 + if (ieee80211_link_has_in_place_reservation(iter.link) && 1646 + !iter.link->reserved_ready) 1743 1647 return -EAGAIN; 1744 1648 1745 - old_ctx = ieee80211_link_get_chanctx(link); 1649 + old_ctx = ieee80211_link_get_chanctx(iter.link); 1746 1650 if (old_ctx) { 1747 1651 if (old_ctx->replace_state == 1748 1652 IEEE80211_CHANCTX_WILL_BE_REPLACED) ··· 1752 1658 n_vifs_ctxless++; 1753 1659 } 1754 1660 1755 - if (link->reserved_radar_required) 1661 + if (iter.radar_required) 1756 1662 ctx->conf.radar_enabled = true; 1757 1663 } 1758 1664 } ··· 1767 1673 1768 1674 /* update station rate control and min width before switch */ 1769 1675 list_for_each_entry(ctx, &local->chanctx_list, list) { 1770 - struct ieee80211_link_data *link; 1676 + struct ieee80211_chanctx_user_iter iter; 1771 1677 1772 1678 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1773 1679 continue; ··· 1777 1683 goto err; 1778 1684 } 1779 1685 1780 - list_for_each_entry(link, &ctx->reserved_links, 1781 - reserved_chanctx_list) { 1782 - if (!ieee80211_link_has_in_place_reservation(link)) 1686 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1687 + if (!ieee80211_link_has_in_place_reservation(iter.link)) 1783 1688 continue; 1784 1689 1785 1690 ieee80211_chan_bw_change(local, 1786 - ieee80211_link_get_chanctx(link), 1691 + ieee80211_link_get_chanctx(iter.link), 1787 1692 true, true); 1788 1693 } 1789 1694 1790 - ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true); 1695 + _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true); 1791 1696 } 1792 1697 1793 1698 /* ··· 1811 1718 * context(s). 1812 1719 */ 1813 1720 list_for_each_entry(ctx, &local->chanctx_list, list) { 1814 - struct ieee80211_link_data *link, *link_tmp; 1721 + struct ieee80211_chanctx_user_iter iter; 1815 1722 1816 1723 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1817 1724 continue; ··· 1821 1728 goto err; 1822 1729 } 1823 1730 1824 - list_for_each_entry(link, &ctx->reserved_links, 1825 - reserved_chanctx_list) { 1826 - struct ieee80211_sub_if_data *sdata = link->sdata; 1731 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1732 + struct ieee80211_link_data *link = iter.link; 1733 + struct ieee80211_sub_if_data *sdata = iter.sdata; 1827 1734 struct ieee80211_bss_conf *link_conf = link->conf; 1828 1735 u64 changed = 0; 1829 1736 ··· 1839 1746 1840 1747 ieee80211_check_fast_xmit_iface(sdata); 1841 1748 1842 - link->radar_required = link->reserved_radar_required; 1749 + link->radar_required = iter.radar_required; 1843 1750 1844 - if (link_conf->chanreq.oper.width != link->reserved.oper.width) 1751 + if (link_conf->chanreq.oper.width != iter.chanreq->oper.width) 1845 1752 changed = BSS_CHANGED_BANDWIDTH; 1846 1753 1847 1754 ieee80211_link_update_chanreq(link, &link->reserved); ··· 1856 1763 ieee80211_recalc_chanctx_chantype(local, ctx); 1857 1764 ieee80211_recalc_smps_chanctx(local, ctx); 1858 1765 ieee80211_recalc_radar_chanctx(local, ctx); 1859 - ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false); 1766 + ieee80211_recalc_chanctx_min_def(local, ctx); 1860 1767 1861 - list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1862 - reserved_chanctx_list) { 1863 - if (ieee80211_link_get_chanctx(link) != ctx) 1768 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1769 + if (ieee80211_link_get_chanctx(iter.link) != ctx) 1864 1770 continue; 1865 1771 1866 - list_del(&link->reserved_chanctx_list); 1867 - list_move(&link->assigned_chanctx_list, 1868 - &ctx->assigned_links); 1869 - link->reserved_chanctx = NULL; 1772 + iter.link->reserved_chanctx = NULL; 1870 1773 1871 - ieee80211_link_chanctx_reservation_complete(link); 1774 + ieee80211_link_chanctx_reservation_complete(iter.link); 1872 1775 ieee80211_chan_bw_change(local, ctx, false, false); 1873 1776 } 1874 1777 ··· 1875 1786 * reservation for originally requested interface has already 1876 1787 * succeeded at this point. 1877 1788 */ 1878 - list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1879 - reserved_chanctx_list) { 1880 - if (WARN_ON(ieee80211_link_has_in_place_reservation(link))) 1881 - continue; 1789 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1790 + struct ieee80211_link_data *link = iter.link; 1882 1791 1883 - if (WARN_ON(link->reserved_chanctx != ctx)) 1792 + if (WARN_ON(ieee80211_link_has_in_place_reservation(link))) 1884 1793 continue; 1885 1794 1886 1795 if (!link->reserved_ready) ··· 1921 1834 1922 1835 err: 1923 1836 list_for_each_entry(ctx, &local->chanctx_list, list) { 1924 - struct ieee80211_link_data *link, *link_tmp; 1837 + struct ieee80211_chanctx_user_iter iter; 1925 1838 1926 1839 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1927 1840 continue; 1928 1841 1929 - list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1930 - reserved_chanctx_list) { 1931 - ieee80211_link_unreserve_chanctx(link); 1932 - ieee80211_link_chanctx_reservation_complete(link); 1842 + for_each_chanctx_user_reserved(local, ctx, &iter) { 1843 + ieee80211_link_unreserve_chanctx(iter.link); 1844 + ieee80211_link_chanctx_reservation_complete(iter.link); 1933 1845 } 1934 1846 } 1935 1847 ··· 2035 1949 /* remove reservation */ 2036 1950 WARN_ON(link->reserved_chanctx != ctx); 2037 1951 link->reserved_chanctx = NULL; 2038 - list_del(&link->reserved_chanctx_list); 2039 1952 } 2040 1953 2041 1954 if (ret) { ··· 2131 2046 struct ieee80211_chan_req *tmp) 2132 2047 { 2133 2048 const struct ieee80211_chan_req *ret = req; 2134 - struct ieee80211_link_data *link; 2049 + struct ieee80211_chanctx_user_iter iter; 2135 2050 2136 2051 lockdep_assert_wiphy(local->hw.wiphy); 2137 2052 2138 - for_each_sdata_link(local, link) { 2139 - if (link == skip_link) 2053 + for_each_chanctx_user_all(local, ctx, &iter) { 2054 + if (iter.link == skip_link) 2140 2055 continue; 2141 2056 2142 - if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) { 2143 - ret = ieee80211_chanreq_compatible(ret, 2144 - &link->conf->chanreq, 2145 - tmp); 2146 - if (!ret) 2147 - return NULL; 2148 - } 2149 - 2150 - if (link->reserved_chanctx == ctx) { 2151 - ret = ieee80211_chanreq_compatible(ret, 2152 - &link->reserved, 2153 - tmp); 2154 - if (!ret) 2155 - return NULL; 2156 - } 2057 + ret = ieee80211_chanreq_compatible(ret, iter.chanreq, tmp); 2058 + if (!ret) 2059 + return NULL; 2157 2060 } 2158 2061 2159 2062 *tmp = *ret;
+6 -2
net/mac80211/driver-ops.c
··· 476 476 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 477 477 sdata->vif.type == NL80211_IFTYPE_NAN || 478 478 (sdata->vif.type == NL80211_IFTYPE_MONITOR && 479 - !sdata->vif.bss_conf.mu_mimo_owner && 480 - !(changed & BSS_CHANGED_TXPOWER)))) 479 + changed & ~(BSS_CHANGED_TXPOWER | 480 + BSS_CHANGED_MU_GROUPS)))) 481 + return; 482 + 483 + if (WARN_ON_ONCE(changed & BSS_CHANGED_MU_GROUPS && 484 + !sdata->vif.bss_conf.mu_mimo_owner)) 481 485 return; 482 486 483 487 if (!check_sdata_in_driver(sdata))
+3 -3
net/mac80211/he.c
··· 3 3 * HE handling 4 4 * 5 5 * Copyright(c) 2017 Intel Deutschland GmbH 6 - * Copyright(c) 2019 - 2024 Intel Corporation 6 + * Copyright(c) 2019-2025 Intel Corporation 7 7 */ 8 8 9 9 #include "ieee80211_i.h" ··· 313 313 ieee80211_link_sta_rc_update_omi(link, link_sta); 314 314 } else { 315 315 link_sta->rx_omi_bw_rx = bw; 316 - ieee80211_recalc_chanctx_min_def(local, chanctx, NULL, false); 316 + ieee80211_recalc_chanctx_min_def(local, chanctx); 317 317 } 318 318 319 319 link_sta->rx_omi_bw_staging = bw; ··· 359 359 /* channel context in finalize only when narrowing bandwidth */ 360 360 WARN_ON(link_sta->rx_omi_bw_rx < link_sta->rx_omi_bw_staging); 361 361 link_sta->rx_omi_bw_rx = link_sta->rx_omi_bw_staging; 362 - ieee80211_recalc_chanctx_min_def(local, chanctx, NULL, false); 362 + ieee80211_recalc_chanctx_min_def(local, chanctx); 363 363 } 364 364 365 365 trace_api_return_void(local);
+9 -5
net/mac80211/ibss.c
··· 9 9 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> 10 10 * Copyright 2013-2014 Intel Mobile Communications GmbH 11 11 * Copyright(c) 2016 Intel Deutschland GmbH 12 - * Copyright(c) 2018-2024 Intel Corporation 12 + * Copyright(c) 2018-2025 Intel Corporation 13 13 */ 14 14 15 15 #include <linux/delay.h> ··· 1554 1554 { 1555 1555 size_t baselen; 1556 1556 struct ieee802_11_elems *elems; 1557 + u16 type; 1557 1558 1558 1559 BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) != 1559 1560 offsetof(typeof(mgmt->u.beacon), variable)); ··· 1567 1566 if (baselen > len) 1568 1567 return; 1569 1568 1569 + type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE; 1570 1570 elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable, 1571 - len - baselen, false, NULL); 1571 + len - baselen, type, NULL); 1572 1572 1573 1573 if (elems) { 1574 1574 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, elems); ··· 1618 1616 if (ies_len < 0) 1619 1617 break; 1620 1618 1621 - elems = ieee802_11_parse_elems( 1622 - mgmt->u.action.u.chan_switch.variable, 1623 - ies_len, true, NULL); 1619 + elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable, 1620 + ies_len, 1621 + IEEE80211_FTYPE_MGMT | 1622 + IEEE80211_STYPE_ACTION, 1623 + NULL); 1624 1624 1625 1625 if (elems && !elems->parse_error) 1626 1626 ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt,
+20 -30
net/mac80211/ieee80211_i.h
··· 916 916 struct list_head list; 917 917 struct rcu_head rcu_head; 918 918 919 - struct list_head assigned_links; 920 - struct list_head reserved_links; 921 - 922 919 enum ieee80211_chanctx_replace_state replace_state; 923 920 struct ieee80211_chanctx *replace_ctx; 924 921 ··· 1067 1070 struct ieee80211_link_data { 1068 1071 struct ieee80211_sub_if_data *sdata; 1069 1072 unsigned int link_id; 1070 - 1071 - struct list_head assigned_chanctx_list; /* protected by wiphy mutex */ 1072 - struct list_head reserved_chanctx_list; /* protected by wiphy mutex */ 1073 1073 1074 1074 /* multicast keys only */ 1075 1075 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + ··· 1233 1239 for (struct ieee80211_sub_if_data *___sdata = NULL; \ 1234 1240 !___sdata; \ 1235 1241 ___sdata = (void *)~0 /* always stop */) \ 1242 + for (int ___link_id = ARRAY_SIZE(___sdata->link); \ 1243 + ___link_id; ___link_id = 0 /* always stop */) \ 1236 1244 list_for_each_entry(___sdata, &(_local)->interfaces, list) \ 1237 - if (ieee80211_sdata_running(___sdata)) \ 1238 - for (int ___link_id = 0; \ 1245 + if (___link_id == ARRAY_SIZE(___sdata->link) && \ 1246 + ieee80211_sdata_running(___sdata)) \ 1247 + for (___link_id = 0; \ 1239 1248 ___link_id < ARRAY_SIZE(___sdata->link); \ 1240 1249 ___link_id++) \ 1241 1250 if ((_link = wiphy_dereference((_local)->hw.wiphy, \ ··· 1252 1255 for (struct ieee80211_sub_if_data *___sdata = NULL; \ 1253 1256 !___sdata; \ 1254 1257 ___sdata = (void *)~0 /* always stop */) \ 1255 - list_for_each_entry_rcu(___sdata, &(_local)->interfaces, list) \ 1256 - if (ieee80211_sdata_running(___sdata)) \ 1257 - for (int ___link_id = 0; \ 1258 + for (int ___link_id = ARRAY_SIZE(___sdata->link); \ 1259 + ___link_id; ___link_id = 0 /* always stop */) \ 1260 + list_for_each_entry(___sdata, &(_local)->interfaces, list) \ 1261 + if (___link_id == ARRAY_SIZE(___sdata->link) && \ 1262 + ieee80211_sdata_running(___sdata)) \ 1263 + for (___link_id = 0; \ 1258 1264 ___link_id < ARRAY_SIZE((___sdata)->link); \ 1259 1265 ___link_id++) \ 1260 1266 if ((_link = rcu_dereference((___sdata)->link[___link_id]))) ··· 2107 2107 const int offset); 2108 2108 int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); 2109 2109 void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); 2110 - int ieee80211_add_virtual_monitor(struct ieee80211_local *local); 2110 + int ieee80211_add_virtual_monitor(struct ieee80211_local *local, 2111 + struct ieee80211_sub_if_data *creator_sdata); 2111 2112 void ieee80211_del_virtual_monitor(struct ieee80211_local *local); 2112 2113 2113 2114 bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link); ··· 2423 2422 * @mode: connection mode for parsing 2424 2423 * @start: pointer to the elements 2425 2424 * @len: length of the elements 2426 - * @action: %true if the elements came from an action frame 2425 + * @type: type of the frame the elements came from 2426 + * (action, probe response, beacon, etc.) 2427 2427 * @filter: bitmap of element IDs to filter out while calculating 2428 2428 * the element CRC 2429 2429 * @crc: CRC starting value ··· 2442 2440 enum ieee80211_conn_mode mode; 2443 2441 const u8 *start; 2444 2442 size_t len; 2445 - bool action; 2443 + u8 type; 2446 2444 u64 filter; 2447 2445 u32 crc; 2448 2446 struct cfg80211_bss *bss; ··· 2454 2452 ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params); 2455 2453 2456 2454 static inline struct ieee802_11_elems * 2457 - ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, 2458 - u64 filter, u32 crc, 2459 - struct cfg80211_bss *bss) 2455 + ieee802_11_parse_elems(const u8 *start, size_t len, u8 type, 2456 + struct cfg80211_bss *bss) 2460 2457 { 2461 2458 struct ieee80211_elems_parse_params params = { 2462 2459 .mode = IEEE80211_CONN_MODE_HIGHEST, 2463 2460 .start = start, 2464 2461 .len = len, 2465 - .action = action, 2466 - .filter = filter, 2467 - .crc = crc, 2462 + .type = type, 2468 2463 .bss = bss, 2469 2464 .link_id = -1, 2470 2465 }; 2471 2466 2472 2467 return ieee802_11_parse_elems_full(&params); 2473 - } 2474 - 2475 - static inline struct ieee802_11_elems * 2476 - ieee802_11_parse_elems(const u8 *start, size_t len, bool action, 2477 - struct cfg80211_bss *bss) 2478 - { 2479 - return ieee802_11_parse_elems_crc(start, len, action, 0, 0, bss); 2480 2468 } 2481 2469 2482 2470 extern const int ieee802_1d_to_ac[8]; ··· 2760 2768 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 2761 2769 struct ieee80211_chanctx *chanctx); 2762 2770 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, 2763 - struct ieee80211_chanctx *ctx, 2764 - struct ieee80211_link_data *rsvd_for, 2765 - bool check_reserved); 2771 + struct ieee80211_chanctx *ctx); 2766 2772 bool ieee80211_is_radar_required(struct ieee80211_local *local, 2767 2773 struct cfg80211_scan_request *req); 2768 2774 bool ieee80211_is_radio_idx_in_scan_req(struct wiphy *wiphy,
+40 -6
net/mac80211/iface.c
··· 733 733 ieee80211_configure_filter(local); 734 734 ieee80211_hw_config(local, -1, hw_reconf_flags); 735 735 736 + /* Passing NULL means an interface is picked for configuration */ 736 737 if (local->virt_monitors == local->open_count) 737 - ieee80211_add_virtual_monitor(local); 738 + ieee80211_add_virtual_monitor(local, NULL); 738 739 } 739 740 740 741 void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) ··· 1169 1168 ieee80211_link_init(sdata, -1, &sdata->deflink, &sdata->vif.bss_conf); 1170 1169 } 1171 1170 1172 - int ieee80211_add_virtual_monitor(struct ieee80211_local *local) 1171 + int ieee80211_add_virtual_monitor(struct ieee80211_local *local, 1172 + struct ieee80211_sub_if_data *creator_sdata) 1173 1173 { 1174 1174 struct ieee80211_sub_if_data *sdata; 1175 1175 int ret; ··· 1178 1176 ASSERT_RTNL(); 1179 1177 lockdep_assert_wiphy(local->hw.wiphy); 1180 1178 1181 - if (local->monitor_sdata || 1182 - ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) 1179 + if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) 1183 1180 return 0; 1181 + 1182 + /* Already have a monitor set up, configure it */ 1183 + sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); 1184 + if (sdata) 1185 + goto configure_monitor; 1184 1186 1185 1187 sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); 1186 1188 if (!sdata) ··· 1237 1231 skb_queue_head_init(&sdata->skb_queue); 1238 1232 skb_queue_head_init(&sdata->status_queue); 1239 1233 wiphy_work_init(&sdata->work, ieee80211_iface_work); 1234 + 1235 + configure_monitor: 1236 + /* Copy in the MU-MIMO configuration if set */ 1237 + if (!creator_sdata) { 1238 + struct ieee80211_sub_if_data *other; 1239 + 1240 + list_for_each_entry(other, &local->mon_list, list) { 1241 + if (!other->vif.bss_conf.mu_mimo_owner) 1242 + continue; 1243 + 1244 + creator_sdata = other; 1245 + break; 1246 + } 1247 + } 1248 + 1249 + if (creator_sdata && creator_sdata->vif.bss_conf.mu_mimo_owner) { 1250 + sdata->vif.bss_conf.mu_mimo_owner = true; 1251 + memcpy(&sdata->vif.bss_conf.mu_group, 1252 + &creator_sdata->vif.bss_conf.mu_group, 1253 + sizeof(sdata->vif.bss_conf.mu_group)); 1254 + memcpy(&sdata->u.mntr.mu_follow_addr, 1255 + creator_sdata->u.mntr.mu_follow_addr, ETH_ALEN); 1256 + 1257 + ieee80211_link_info_change_notify(sdata, &sdata->deflink, 1258 + BSS_CHANGED_MU_GROUPS); 1259 + } 1240 1260 1241 1261 return 0; 1242 1262 } ··· 1420 1388 if (res) 1421 1389 goto err_stop; 1422 1390 } else { 1423 - if (local->virt_monitors == 0 && local->open_count == 0) { 1424 - res = ieee80211_add_virtual_monitor(local); 1391 + /* add/configure if there is no non-monitor interface */ 1392 + if (local->virt_monitors == local->open_count) { 1393 + res = ieee80211_add_virtual_monitor(local, sdata); 1425 1394 if (res) 1426 1395 goto err_stop; 1427 1396 } 1397 + 1428 1398 local->virt_monitors++; 1429 1399 1430 1400 /* must be before the call to ieee80211_configure_filter */
-5
net/mac80211/link.c
··· 23 23 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { 24 24 int link_id; 25 25 26 - if (!vlan) 27 - continue; 28 - 29 26 /* No support for 4addr with MLO yet */ 30 27 if (vlan->wdev.use_4addr) 31 28 return; ··· 116 119 ieee80211_color_change_finalize_work); 117 120 wiphy_delayed_work_init(&link->color_collision_detect_work, 118 121 ieee80211_color_collision_detection_work); 119 - INIT_LIST_HEAD(&link->assigned_chanctx_list); 120 - INIT_LIST_HEAD(&link->reserved_chanctx_list); 121 122 wiphy_delayed_work_init(&link->dfs_cac_timer_work, 122 123 ieee80211_dfs_cac_timer_work); 123 124
+1 -2
net/mac80211/main.c
··· 356 356 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 357 357 sdata->vif.type == NL80211_IFTYPE_NAN || 358 358 (sdata->vif.type == NL80211_IFTYPE_MONITOR && 359 - !sdata->vif.bss_conf.mu_mimo_owner && 360 - !(changed & BSS_CHANGED_TXPOWER)))) 359 + changed & ~BSS_CHANGED_TXPOWER))) 361 360 return; 362 361 363 362 if (!check_sdata_in_driver(sdata))
+16 -10
net/mac80211/mesh.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2008, 2009 open80211s Ltd. 4 - * Copyright (C) 2018 - 2024 Intel Corporation 4 + * Copyright (C) 2018 - 2025 Intel Corporation 5 5 * Authors: Luis Carlos Cobo <luisca@cozybit.com> 6 6 * Javier Cardona <javier@cozybit.com> 7 7 */ ··· 1410 1410 if (baselen > len) 1411 1411 return; 1412 1412 1413 - elems = ieee802_11_parse_elems(pos, len - baselen, false, NULL); 1413 + elems = ieee802_11_parse_elems(pos, len - baselen, 1414 + IEEE80211_FTYPE_MGMT | 1415 + IEEE80211_STYPE_PROBE_REQ, 1416 + NULL); 1414 1417 if (!elems) 1415 1418 return; 1416 1419 ··· 1458 1455 } 1459 1456 1460 1457 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, 1461 - u16 stype, 1462 1458 struct ieee80211_mgmt *mgmt, 1463 1459 size_t len, 1464 1460 struct ieee80211_rx_status *rx_status) 1465 1461 { 1462 + u16 type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE; 1466 1463 struct ieee80211_local *local = sdata->local; 1467 1464 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 1468 1465 struct ieee802_11_elems *elems; ··· 1472 1469 enum nl80211_band band = rx_status->band; 1473 1470 1474 1471 /* ignore ProbeResp to foreign address */ 1475 - if (stype == IEEE80211_STYPE_PROBE_RESP && 1472 + if (type == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP) && 1476 1473 !ether_addr_equal(mgmt->da, sdata->vif.addr)) 1477 1474 return; 1478 1475 ··· 1481 1478 return; 1482 1479 1483 1480 elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable, 1484 - len - baselen, 1485 - false, NULL); 1481 + len - baselen, type, NULL); 1486 1482 if (!elems) 1487 1483 return; 1488 1484 ··· 1516 1514 } 1517 1515 1518 1516 if (ifmsh->sync_ops) 1519 - ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len, 1517 + ifmsh->sync_ops->rx_bcn_presp(sdata, 1518 + type & IEEE80211_FCTL_STYPE, 1519 + mgmt, len, 1520 1520 elems->mesh_config, rx_status); 1521 1521 free: 1522 1522 kfree(elems); ··· 1626 1622 pos = mgmt->u.action.u.chan_switch.variable; 1627 1623 baselen = offsetof(struct ieee80211_mgmt, 1628 1624 u.action.u.chan_switch.variable); 1629 - elems = ieee802_11_parse_elems(pos, len - baselen, true, NULL); 1625 + elems = ieee802_11_parse_elems(pos, len - baselen, 1626 + IEEE80211_FTYPE_MGMT | 1627 + IEEE80211_STYPE_ACTION, 1628 + NULL); 1630 1629 if (!elems) 1631 1630 return; 1632 1631 ··· 1706 1699 switch (stype) { 1707 1700 case IEEE80211_STYPE_PROBE_RESP: 1708 1701 case IEEE80211_STYPE_BEACON: 1709 - ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, 1710 - rx_status); 1702 + ieee80211_mesh_rx_bcn_presp(sdata, mgmt, skb->len, rx_status); 1711 1703 break; 1712 1704 case IEEE80211_STYPE_PROBE_REQ: 1713 1705 ieee80211_mesh_rx_probe_req(sdata, mgmt, skb->len);
+5 -2
net/mac80211/mesh_hwmp.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2008, 2009 open80211s Ltd. 4 - * Copyright (C) 2019, 2021-2023 Intel Corporation 4 + * Copyright (C) 2019, 2021-2023, 2025 Intel Corporation 5 5 * Author: Luis Carlos Cobo <luisca@cozybit.com> 6 6 */ 7 7 ··· 951 951 952 952 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; 953 953 elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, 954 - len - baselen, false, NULL); 954 + len - baselen, 955 + IEEE80211_FTYPE_MGMT | 956 + IEEE80211_STYPE_ACTION, 957 + NULL); 955 958 if (!elems) 956 959 return; 957 960
+5 -2
net/mac80211/mesh_plink.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2008, 2009 open80211s Ltd. 4 - * Copyright (C) 2019, 2021-2024 Intel Corporation 4 + * Copyright (C) 2019, 2021-2025 Intel Corporation 5 5 * Author: Luis Carlos Cobo <luisca@cozybit.com> 6 6 */ 7 7 #include <linux/gfp.h> ··· 1248 1248 if (baselen > len) 1249 1249 return; 1250 1250 } 1251 - elems = ieee802_11_parse_elems(baseaddr, len - baselen, true, NULL); 1251 + elems = ieee802_11_parse_elems(baseaddr, len - baselen, 1252 + IEEE80211_FTYPE_MGMT | 1253 + IEEE80211_STYPE_ACTION, 1254 + NULL); 1252 1255 if (elems) { 1253 1256 mesh_process_plink_frame(sdata, mgmt, elems, rx_status); 1254 1257 kfree(elems);
+37 -34
net/mac80211/mlme.c
··· 276 276 return IEEE80211_CONN_MODE_VHT; 277 277 } 278 278 } else if (!vht_oper || !elems->vht_cap_elem) { 279 - if (sband->band == NL80211_BAND_5GHZ) { 280 - sdata_info(sdata, 281 - "VHT information is missing, disabling VHT\n"); 279 + if (sband->band == NL80211_BAND_5GHZ) 282 280 return IEEE80211_CONN_MODE_HT; 283 - } 284 281 no_vht = true; 285 282 } else if (sband->band == NL80211_BAND_2GHZ) { 286 283 no_vht = true; ··· 999 1002 .from_ap = true, 1000 1003 .start = ies->data, 1001 1004 .len = ies->len, 1005 + .type = ies->from_beacon ? 1006 + IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON : 1007 + IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP, 1002 1008 }; 1003 1009 struct ieee802_11_elems *elems; 1004 1010 struct ieee80211_supported_band *sband; ··· 5180 5180 continue; 5181 5181 } 5182 5182 5183 - elems = ieee802_11_parse_elems(ies->data, ies->len, false, 5183 + elems = ieee802_11_parse_elems(ies->data, ies->len, 5184 + IEEE80211_FTYPE_MGMT | 5185 + IEEE80211_STYPE_BEACON, 5184 5186 NULL); 5185 5187 if (!elems) { 5186 5188 rcu_read_unlock(); ··· 5228 5226 .len = elem_len, 5229 5227 .link_id = link_id == assoc_data->assoc_link_id ? -1 : link_id, 5230 5228 .from_ap = true, 5229 + .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE, 5231 5230 }; 5232 5231 bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ; 5233 5232 bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; ··· 6034 6031 conn->bw_limit, tmp.bw_limit); 6035 6032 } 6036 6033 6037 - static enum ieee80211_ap_reg_power 6038 - ieee80211_ap_power_type(u8 control) 6039 - { 6040 - switch (u8_get_bits(control, IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) { 6041 - case IEEE80211_6GHZ_CTRL_REG_LPI_AP: 6042 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP: 6043 - return IEEE80211_REG_LPI_AP; 6044 - case IEEE80211_6GHZ_CTRL_REG_SP_AP: 6045 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP: 6046 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD: 6047 - return IEEE80211_REG_SP_AP; 6048 - case IEEE80211_6GHZ_CTRL_REG_VLP_AP: 6049 - return IEEE80211_REG_VLP_AP; 6050 - default: 6051 - return IEEE80211_REG_UNSET_AP; 6052 - } 6053 - } 6054 - 6055 6034 static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, 6056 6035 struct ieee80211_link_data *link, 6057 6036 int link_id, ··· 6076 6091 he_6ghz_oper = ieee80211_he_6ghz_oper(elems->he_operation); 6077 6092 if (he_6ghz_oper) 6078 6093 link->conf->power_type = 6079 - ieee80211_ap_power_type(he_6ghz_oper->control); 6094 + cfg80211_6ghz_power_type(he_6ghz_oper->control, 6095 + cbss->channel->flags); 6080 6096 else 6081 6097 link_info(link, 6082 6098 "HE 6 GHz operation missing (on %d MHz), expect issues\n", ··· 6345 6359 .bss = NULL, 6346 6360 .link_id = -1, 6347 6361 .from_ap = true, 6362 + .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE, 6348 6363 }; 6349 6364 struct ieee802_11_elems *elems; 6350 6365 int ac; ··· 7254 7267 (prof->sta_info_len - 1), 7255 7268 len - 7256 7269 (prof->sta_info_len - 1), 7257 - false, NULL); 7270 + IEEE80211_FTYPE_MGMT | 7271 + IEEE80211_STYPE_BEACON, 7272 + NULL); 7258 7273 7259 7274 /* memory allocation failed - let's hope that's transient */ 7260 7275 if (!prof_elems) ··· 7360 7371 .mode = link->u.mgd.conn.mode, 7361 7372 .link_id = -1, 7362 7373 .from_ap = true, 7374 + .type = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_TYPE, 7363 7375 }; 7364 7376 7365 7377 lockdep_assert_wiphy(local->hw.wiphy); ··· 7963 7973 ies_len = len - offsetof(struct ieee80211_mgmt, 7964 7974 u.action.u.ttlm_req.variable); 7965 7975 elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable, 7966 - ies_len, true, NULL); 7976 + ies_len, 7977 + IEEE80211_FTYPE_MGMT | 7978 + IEEE80211_STYPE_ACTION, 7979 + NULL); 7967 7980 if (!elems) { 7968 7981 ttlm_res = NEG_TTLM_RES_REJECT; 7969 7982 goto out; ··· 8172 8179 break; 8173 8180 8174 8181 /* CSA IE cannot be overridden, no need for BSSID */ 8175 - elems = ieee802_11_parse_elems( 8176 - mgmt->u.action.u.chan_switch.variable, 8177 - ies_len, true, NULL); 8182 + elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable, 8183 + ies_len, 8184 + IEEE80211_FTYPE_MGMT | 8185 + IEEE80211_STYPE_ACTION, 8186 + NULL); 8178 8187 8179 8188 if (elems && !elems->parse_error) { 8180 8189 enum ieee80211_csa_source src = ··· 8203 8208 * extended CSA IE can't be overridden, no need for 8204 8209 * BSSID 8205 8210 */ 8206 - elems = ieee802_11_parse_elems( 8207 - mgmt->u.action.u.ext_chan_switch.variable, 8208 - ies_len, true, NULL); 8211 + elems = ieee802_11_parse_elems(mgmt->u.action.u.ext_chan_switch.variable, 8212 + ies_len, 8213 + IEEE80211_FTYPE_MGMT | 8214 + IEEE80211_STYPE_ACTION, 8215 + NULL); 8209 8216 8210 8217 if (elems && !elems->parse_error) { 8211 8218 enum ieee80211_csa_source src; ··· 10985 10988 pos = scratch + sizeof(control); 10986 10989 len -= sizeof(control); 10987 10990 10988 - link_elems = ieee802_11_parse_elems(pos, len, false, NULL); 10991 + link_elems = ieee802_11_parse_elems(pos, len, 10992 + IEEE80211_FTYPE_MGMT | 10993 + IEEE80211_STYPE_ACTION, 10994 + NULL); 10989 10995 if (!link_elems) 10990 10996 continue; 10991 10997 ··· 11039 11039 u.action.u.epcs.variable) - 11040 11040 IEEE80211_EPCS_ENA_RESP_BODY_LEN; 11041 11041 11042 - elems = ieee802_11_parse_elems(pos, ies_len, true, NULL); 11042 + elems = ieee802_11_parse_elems(pos, ies_len, 11043 + IEEE80211_FTYPE_MGMT | 11044 + IEEE80211_STYPE_ACTION, 11045 + NULL); 11043 11046 if (!elems) 11044 11047 return; 11045 11048
+25 -5
net/mac80211/parse.c
··· 6 6 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 7 7 * Copyright 2013-2014 Intel Mobile Communications GmbH 8 8 * Copyright (C) 2015-2017 Intel Deutschland GmbH 9 - * Copyright (C) 2018-2024 Intel Corporation 9 + * Copyright (C) 2018-2025 Intel Corporation 10 10 * 11 11 * element parsing for mac80211 12 12 */ ··· 285 285 u32 crc = params->crc; 286 286 287 287 bitmap_zero(seen_elems, 256); 288 + 289 + switch (params->type) { 290 + /* we don't need to parse assoc request, luckily (it's value 0) */ 291 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ: 292 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ: 293 + default: 294 + WARN(1, "invalid frame type 0x%x for element parsing\n", 295 + params->type); 296 + break; 297 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP: 298 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP: 299 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: 300 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP: 301 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON: 302 + case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION: 303 + case IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON: 304 + break; 305 + } 288 306 289 307 for_each_element(elem, params->start, params->len) { 290 308 const struct element *subelem; ··· 584 566 if (params->mode < IEEE80211_CONN_MODE_VHT) 585 567 break; 586 568 587 - if (!params->action) { 569 + if (params->type != (IEEE80211_FTYPE_MGMT | 570 + IEEE80211_STYPE_ACTION)) { 588 571 elem_parse_failed = 589 572 IEEE80211_PARSE_ERR_UNEXPECTED_ELEM; 590 573 break; ··· 601 582 case WLAN_EID_CHANNEL_SWITCH_WRAPPER: 602 583 if (params->mode < IEEE80211_CONN_MODE_VHT) 603 584 break; 604 - if (params->action) { 585 + if (params->type == (IEEE80211_FTYPE_MGMT | 586 + IEEE80211_STYPE_ACTION)) { 605 587 elem_parse_failed = 606 588 IEEE80211_PARSE_ERR_UNEXPECTED_ELEM; 607 589 break; ··· 962 942 sub->len = end - sub->start; 963 943 964 944 sub->mode = params->mode; 965 - sub->action = params->action; 945 + sub->type = params->type; 966 946 sub->from_ap = params->from_ap; 967 947 sub->link_id = -1; 968 948 ··· 1061 1041 sub.start = elems_parse->scratch_pos; 1062 1042 sub.mode = params->mode; 1063 1043 sub.len = nontx_len; 1064 - sub.action = params->action; 1044 + sub.type = params->type; 1065 1045 sub.link_id = params->link_id; 1066 1046 1067 1047 /* consume the space used for non-transmitted profile */
+5 -1
net/mac80211/scan.c
··· 76 76 if (!update_data) 77 77 return; 78 78 79 - elems = ieee802_11_parse_elems(ies->data, ies->len, false, NULL); 79 + elems = ieee802_11_parse_elems(ies->data, ies->len, 80 + update_data->beacon ? 81 + IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON : 82 + IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP, 83 + NULL); 80 84 if (!elems) 81 85 return; 82 86
+9 -3
net/mac80211/tdls.c
··· 6 6 * Copyright 2014, Intel Corporation 7 7 * Copyright 2014 Intel Mobile Communications GmbH 8 8 * Copyright 2015 - 2016 Intel Deutschland GmbH 9 - * Copyright (C) 2019, 2021-2024 Intel Corporation 9 + * Copyright (C) 2019, 2021-2025 Intel Corporation 10 10 */ 11 11 12 12 #include <linux/ieee80211.h> ··· 1783 1783 } 1784 1784 1785 1785 elems = ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, 1786 - skb->len - baselen, false, NULL); 1786 + skb->len - baselen, 1787 + IEEE80211_FTYPE_MGMT | 1788 + IEEE80211_STYPE_ACTION, 1789 + NULL); 1787 1790 if (!elems) { 1788 1791 ret = -ENOMEM; 1789 1792 goto out; ··· 1905 1902 } 1906 1903 1907 1904 elems = ieee802_11_parse_elems(tf->u.chan_switch_req.variable, 1908 - skb->len - baselen, false, NULL); 1905 + skb->len - baselen, 1906 + IEEE80211_FTYPE_MGMT | 1907 + IEEE80211_STYPE_ACTION, 1908 + NULL); 1909 1909 if (!elems) 1910 1910 return -ENOMEM; 1911 1911
+3 -1
net/mac80211/tests/elems.c
··· 2 2 /* 3 3 * KUnit tests for element parsing 4 4 * 5 - * Copyright (C) 2023-2024 Intel Corporation 5 + * Copyright (C) 2023-2025 Intel Corporation 6 6 */ 7 7 #include <kunit/test.h> 8 8 #include "../ieee80211_i.h" ··· 15 15 .link_id = 12, 16 16 .from_ap = true, 17 17 .mode = IEEE80211_CONN_MODE_EHT, 18 + /* type is not really relevant here */ 19 + .type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON, 18 20 }; 19 21 struct ieee802_11_elems *parsed; 20 22 struct sk_buff *skb;
+19 -18
net/mac80211/util.c
··· 2206 2206 } 2207 2207 } 2208 2208 2209 + /* Passing NULL means an interface is picked for configuration */ 2209 2210 if (local->virt_monitors > 0 && 2210 2211 local->virt_monitors == local->open_count) 2211 - ieee80211_add_virtual_monitor(local); 2212 + ieee80211_add_virtual_monitor(local, NULL); 2212 2213 2213 2214 if (!suspended) 2214 2215 return 0; ··· 2348 2347 2349 2348 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, 2350 2349 conf); 2351 - ieee80211_recalc_chanctx_min_def(local, chanctx, NULL, false); 2350 + ieee80211_recalc_chanctx_min_def(local, chanctx); 2352 2351 } 2353 2352 } 2354 2353 ··· 4017 4016 if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)) 4018 4017 return 0; 4019 4018 4020 - list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) 4021 - if (link->reserved_radar_required) 4019 + for_each_sdata_link(local, link) { 4020 + if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) { 4021 + /* 4022 + * An in-place reservation context should not have any 4023 + * assigned links until it replaces the other context. 4024 + */ 4025 + WARN_ON(ctx->replace_state == 4026 + IEEE80211_CHANCTX_REPLACES_OTHER); 4027 + 4028 + if (link->radar_required) 4029 + radar_detect |= 4030 + BIT(link->conf->chanreq.oper.width); 4031 + } 4032 + 4033 + if (link->reserved_chanctx == ctx && 4034 + link->reserved_radar_required) 4022 4035 radar_detect |= BIT(link->reserved.oper.width); 4023 - 4024 - /* 4025 - * An in-place reservation context should not have any assigned vifs 4026 - * until it replaces the other context. 4027 - */ 4028 - WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER && 4029 - !list_empty(&ctx->assigned_links)); 4030 - 4031 - list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) { 4032 - if (!link->radar_required) 4033 - continue; 4034 - 4035 - radar_detect |= 4036 - BIT(link->conf->chanreq.oper.width); 4037 4036 } 4038 4037 4039 4038 return radar_detect;
+6 -6
net/wireless/core.c
··· 1066 1066 wiphy_regulatory_register(wiphy); 1067 1067 1068 1068 if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { 1069 - struct regulatory_request request; 1070 - 1071 - request.wiphy_idx = get_wiphy_idx(wiphy); 1072 - request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 1073 - request.alpha2[0] = '9'; 1074 - request.alpha2[1] = '9'; 1069 + struct regulatory_request request = { 1070 + .wiphy_idx = get_wiphy_idx(wiphy), 1071 + .initiator = NL80211_REGDOM_SET_BY_DRIVER, 1072 + .alpha2[0] = '9', 1073 + .alpha2[1] = '9', 1074 + }; 1075 1075 1076 1076 nl80211_send_reg_change_event(&request); 1077 1077 }
+2 -1
net/wireless/core.h
··· 550 550 bool signal_valid, unsigned long ts); 551 551 552 552 enum ieee80211_ap_reg_power 553 - cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len); 553 + cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len, 554 + u32 client_flags); 554 555 555 556 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 556 557 #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
+2 -2
net/wireless/nl80211.c
··· 6748 6748 beacon_check.relax = true; 6749 6749 beacon_check.reg_power = 6750 6750 cfg80211_get_6ghz_power_type(params->beacon.tail, 6751 - params->beacon.tail_len); 6751 + params->beacon.tail_len, 0); 6752 6752 if (!cfg80211_reg_check_beaconing(&rdev->wiphy, &params->chandef, 6753 6753 &beacon_check)) { 6754 6754 err = -EINVAL; ··· 6927 6927 beacon_check.relax = true; 6928 6928 beacon_check.reg_power = 6929 6929 cfg80211_get_6ghz_power_type(params->beacon.tail, 6930 - params->beacon.tail_len); 6930 + params->beacon.tail_len, 0); 6931 6931 if (!cfg80211_reg_check_beaconing(&rdev->wiphy, 6932 6932 &wdev->links[link_id].ap.chandef, 6933 6933 &beacon_check)) {
+4 -16
net/wireless/scan.c
··· 2212 2212 }; 2213 2213 2214 2214 enum ieee80211_ap_reg_power 2215 - cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len) 2215 + cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len, 2216 + u32 client_flags) 2216 2217 { 2217 2218 const struct ieee80211_he_6ghz_oper *he_6ghz_oper; 2218 2219 struct ieee80211_he_operation *he_oper; ··· 2231 2230 if (!he_6ghz_oper) 2232 2231 return IEEE80211_REG_UNSET_AP; 2233 2232 2234 - switch (u8_get_bits(he_6ghz_oper->control, 2235 - IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) { 2236 - case IEEE80211_6GHZ_CTRL_REG_LPI_AP: 2237 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP: 2238 - return IEEE80211_REG_LPI_AP; 2239 - case IEEE80211_6GHZ_CTRL_REG_SP_AP: 2240 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP: 2241 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD: 2242 - return IEEE80211_REG_SP_AP; 2243 - case IEEE80211_6GHZ_CTRL_REG_VLP_AP: 2244 - return IEEE80211_REG_VLP_AP; 2245 - default: 2246 - return IEEE80211_REG_UNSET_AP; 2247 - } 2233 + return cfg80211_6ghz_power_type(he_6ghz_oper->control, client_flags); 2248 2234 } 2249 2235 2250 2236 static bool cfg80211_6ghz_power_type_valid(const u8 *elems, size_t elems_len, 2251 2237 const u32 flags) 2252 2238 { 2253 - switch (cfg80211_get_6ghz_power_type(elems, elems_len)) { 2239 + switch (cfg80211_get_6ghz_power_type(elems, elems_len, flags)) { 2254 2240 case IEEE80211_REG_LPI_AP: 2255 2241 return true; 2256 2242 case IEEE80211_REG_SP_AP: