File Index
Files and directories
Sign in
FILE

ieee80211-eht.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/ieee80211-eht.h C
   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 */
  42struct 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 */
  72struct 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 */
 103struct 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 */
 123struct 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 */
 133struct 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 */
 163struct 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 */
 178struct 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 */
 283static inline u8
 284ieee80211_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 */
 323static inline u8
 324ieee80211_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
 345static inline bool
 346ieee80211_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
 376static inline bool
 377ieee80211_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 */
 397static inline u16
 398ieee80211_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
 414struct ieee80211_bandwidth_indication {
 415	u8 params;
 416	struct ieee80211_eht_operation_info info;
 417} __packed;
 418
 419static inline bool
 420ieee80211_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 */
 435enum 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
 462struct 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
 534struct 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
 542struct 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
 554struct 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 */
 569static 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 */
 601static 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 */
 624static inline int
 625ieee80211_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 */
 653static 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 */
 682static 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 */
 713static 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 */
 757static 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 */
 796static 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 */
 831static 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 */
 908static 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
 924enum 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
 939struct 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 */
 952static 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 */
 995static inline u8
 996ieee80211_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 */
1042static 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
1069static 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
1111static 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
1135static 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
1161static 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 */
~/ Read-only file preview.