Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * IEEE 802.11 UHR definitions
4 *
5 * Copyright (c) 2025-2026 Intel Corporation
6 */
7#ifndef LINUX_IEEE80211_UHR_H
8#define LINUX_IEEE80211_UHR_H
9
10#include <linux/types.h>
11#include <linux/if_ether.h>
12
13#define IEEE80211_UHR_OPER_PARAMS_DPS_ENA 0x0001
14#define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA 0x0002
15#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0004
16#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0008
17
18struct ieee80211_uhr_operation {
19 __le16 params;
20 u8 basic_mcs_nss_set[4];
21 u8 variable[];
22} __packed;
23
24#define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS 0x0000000F
25#define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x000000F0
26#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x00003F00
27#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x000FC000
28#define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x00300000
29#define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x00400000
30#define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x00800000
31
32/**
33 * struct ieee80211_uhr_npca_info - npca operation information
34 *
35 * This structure is the "NPCA Operation Parameters field format" of "UHR
36 * Operation Element" fields as described in P802.11bn_D1.3
37 * subclause 9.4.2.353. See Figure 9-aa4.
38 *
39 * Refer to IEEE80211_UHR_NPCA*
40 * @params:
41 * NPCA Primary Channel - NPCA primary channel
42 * NPCA_Min Duration Threshold - Minimum duration of inter-BSS activity
43 * NPCA Switching Delay -
44 * Time needed by an NPCA AP to switch from the
45 * BSS primary channel to the NPCA primary channel
46 * in the unit of 4 µs.
47 * NPCA Switching Back Delay -
48 * Time to switch from the NPCA primary channel
49 * to the BSS primary channel in the unit of 4 µs.
50 * NPCA Initial QSRC -
51 * Initialize the EDCAF QSRC[AC] variables
52 * when an NPCA STA in the BSS
53 * switches to NPCA operation.
54 * NPCA MOPLEN -
55 * Indicates which conditions can be used to
56 * initiate an NPCA operation,
57 * 1 -> both PHYLEN NPCA operation and MOPLEN
58 * NPCA operation are
59 * permitted in the BSS
60 * 0 -> only PHYLEN NPCA operation is allowed in the BSS.
61 * NPCA Disabled Subchannel Bitmap Present -
62 * Indicates whether the NPCA Disabled Subchannel
63 * Bitmap field is present. A 1 in this field indicates that
64 * the NPCA Disabled Subchannel Bitmap field is present
65 * @dis_subch_bmap:
66 * A bit in the bitmap that lies within the BSS bandwidth is set
67 * to 1 to indicate that the corresponding 20 MHz subchannel is
68 * punctured and is set to 0 to indicate that the corresponding
69 * 20 MHz subchannel is not punctured. A bit in the bitmap that
70 * falls outside of the BSS bandwidth is reserved. This field is
71 * present when the value of the NPCA Disabled Subchannel Bitmap
72 * Field Present field is equal to 1, and not present, otherwise
73 */
74struct ieee80211_uhr_npca_info {
75 __le32 params;
76 __le16 dis_subch_bmap[];
77} __packed;
78
79#define IEEE80211_UHR_DPS_PADDING_DELAY 0x0000003F
80#define IEEE80211_UHR_DPS_TRANSITION_DELAY 0x00003F00
81#define IEEE80211_UHR_DPS_ICF_REQUIRED 0x00010000
82#define IEEE80211_UHR_DPS_PARAMETERIZED_FLAG 0x00020000
83#define IEEE80211_UHR_DPS_LC_MODE_BW 0x001C0000
84#define IEEE80211_UHR_DPS_LC_MODE_NSS 0x01E00000
85#define IEEE80211_UHR_DPS_LC_MODE_MCS 0x1E000000
86#define IEEE80211_UHR_DPS_MOBILE_AP_DPS_STATIC_HCM 0x20000000
87
88/**
89 * struct ieee80211_uhr_dps_info - DPS operation information
90 *
91 * This structure is the "DPS Operation Parameter field" of "UHR
92 * Operation Element" fields as described in P802.11bn_D1.3
93 * subclause 9.4.1.87. See Figure 9-207u.
94 *
95 * Refer to IEEE80211_UHR_DPS*
96 * @params:
97 * DPS Padding Delay -
98 * Indicates the minimum MAC padding
99 * duration that is required by a DPS STA
100 * in an ICF to cause the STA to transition
101 * from the lower capability mode to the
102 * higher capability mode. The DPS Padding
103 * Delay field is in units of 4 µs.
104 * DPS Transition Delay -
105 * Indicates the amount of time required by a
106 * DPS STA to transition from the higher
107 * capability mode to the lower capability
108 * mode. The DPS Transition Delay field is in
109 * units of 4 µs.
110 * ICF Required -
111 * Indicates when the DPS assisting STA needs
112 * to transmit an ICF frame to the peer DPS STA
113 * before performing the frame exchanges with
114 * the peer DPS STA in a TXOP.
115 * 1 -> indicates that the transmission of the
116 * ICF frame to the peer DPS STA prior to
117 * any frame exchange is needed.
118 * 0 -> ICF transmission before the frame
119 * exchanges with the peer DPS STA is only
120 * needed if the frame exchange is performed
121 * in the HC mode.
122 * Parameterized Flag -
123 * 0 -> indicates that only 20 MHz, 1 SS,
124 * non-HT PPDU format with the data
125 * rate of 6, 12, and 24 Mb/s as the
126 * default mode are supported by the
127 * DPS STA in the LC mode
128 * 1 -> indicates that a bandwidth up to the
129 * bandwidth indicated in the LC Mode
130 * Bandwidth field, a number of spatial
131 * streams up to the NSS indicated in
132 * the LC Mode Nss field, and an MCS up
133 * to the MCS indicated in the LC Mode
134 * MCS fields are supported by the DPS
135 * STA in the LC mode as the
136 * parameterized mode.
137 * LC Mode Bandwidth -
138 * Indicates the maximum bandwidth supported
139 * by the STA in the LC mode.
140 * LC Mode NSS -
141 * Indicates the maximum number of the spatial
142 * streams supported by the STA in the LC mode.
143 * LC Mode MCS -
144 * Indicates the highest MCS supported by the STA
145 * in the LC mode.
146 * Mobile AP DPS Static HCM -
147 * 1 -> indicates that it will remain in the DPS high
148 * capability mode until the next TBTT on that
149 * link.
150 * 0 -> otherwise.
151 */
152struct ieee80211_uhr_dps_info {
153 __le32 params;
154} __packed;
155
156#define IEEE80211_UHR_DBE_OPER_BANDWIDTH 0x07
157#define IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES 0x08
158
159/**
160 * enum ieee80211_uhr_dbe_oper_bw - DBE Operational Bandwidth
161 *
162 * Encoding for the DBE Operational Bandwidth field in the UHR Operation
163 * element (DBE Operation Parameters).
164 *
165 * @IEEE80211_UHR_DBE_OPER_BW_40: 40 MHz operational DBE bandwidth
166 * @IEEE80211_UHR_DBE_OPER_BW_80: 80 MHz operational DBE bandwidth
167 * @IEEE80211_UHR_DBE_OPER_BW_160: 160 MHz operational DBE bandwidth
168 * @IEEE80211_UHR_DBE_OPER_BW_320_1: 320-1 MHz operational DBE bandwidth
169 * @IEEE80211_UHR_DBE_OPER_BW_320_2: 320-2 MHz operational DBE bandwidth
170 */
171enum ieee80211_uhr_dbe_oper_bw {
172 IEEE80211_UHR_DBE_OPER_BW_40 = 1,
173 IEEE80211_UHR_DBE_OPER_BW_80 = 2,
174 IEEE80211_UHR_DBE_OPER_BW_160 = 3,
175 IEEE80211_UHR_DBE_OPER_BW_320_1 = 4,
176 IEEE80211_UHR_DBE_OPER_BW_320_2 = 5,
177};
178
179/**
180 * struct ieee80211_uhr_dbe_info - DBE operation information
181 *
182 * This structure is the "DBE Operation Parameters field" of
183 * "UHR Operation Element" fields as described in P802.11bn_D1.3
184 * subclause 9.4.2.353. See Figure 9-aa6.
185 *
186 * Refer to IEEE80211_UHR_DBE_OPER*
187 * @params:
188 * B0-B2 - DBE Operational Bandwidth field, see
189 * "enum ieee80211_uhr_dbe_oper_bw" for values.
190 * Value 0 is reserved.
191 * Value 1 indicates 40 MHz operational DBE bandwidth.
192 * Value 2 indicates 80 MHz operational DBE bandwidth.
193 * Value 3 indicates 160 MHz operational DBE bandwidth.
194 * Value 4 indicates 320-1 MHz operational DBE bandwidth.
195 * Value 5 indicates 320-2 MHz operational DBE bandwidth.
196 * Values 6 to 7 are reserved.
197 * B3 - DBE Disabled Subchannel Bitmap Present.
198 * @dis_subch_bmap: DBE Disabled Subchannel Bitmap field is set to indicate
199 * disabled 20 MHz subchannels within the DBE Bandwidth.
200 */
201struct ieee80211_uhr_dbe_info {
202 u8 params;
203 __le16 dis_subch_bmap[];
204} __packed;
205
206#define IEEE80211_UHR_P_EDCA_ECWMIN 0x0F
207#define IEEE80211_UHR_P_EDCA_ECWMAX 0xF0
208#define IEEE80211_UHR_P_EDCA_AIFSN 0x000F
209#define IEEE80211_UHR_P_EDCA_CW_DS 0x0030
210#define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD 0x01C0
211#define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD 0x0600
212
213/**
214 * struct ieee80211_uhr_p_edca_info - P-EDCA operation information
215 *
216 * This structure is the "P-EDCA Operation Parameters field" of
217 * "UHR Operation Element" fields as described in P802.11bn_D1.3
218 * subclause 9.4.2.353. See Figure 9-aa5.
219 *
220 * Refer to IEEE80211_UHR_P_EDCA*
221 * @p_edca_ec: P-EDCA ECWmin and ECWmax.
222 * These fields indicate the CWmin and CWmax values used by a
223 * P-EDCA STA during P-EDCA contention.
224 * @params: AIFSN, CW DS, PSRC threshold, and QSRC threshold.
225 * - The AIFSN field indicates the AIFSN value used by a P-EDCA STA
226 * during P-EDCA contention.
227 * - The CW DS field indicates the value used for randomization of the
228 * transmission slot of the DS-CTS frame. The value 3 is reserved.
229 * The value 0 indicates that randomization is not enabled.
230 * - The P-EDCA PSRC threshold field indicates the maximum number of
231 * allowed consecutive DS-CTS transmissions. The value 0 and values
232 * greater than 4 are reserved.
233 * - The P-EDCA QSRC threshold field indicates the value of the
234 * QSRC[AC_VO] counter required to start P-EDCA contention. The
235 * value 0 is reserved.
236 */
237struct ieee80211_uhr_p_edca_info {
238 u8 p_edca_ec;
239 __le16 params;
240} __packed;
241
242static inline bool ieee80211_uhr_oper_size_ok(const u8 *data, u8 len,
243 bool beacon)
244{
245 const struct ieee80211_uhr_operation *oper = (const void *)data;
246 u8 needed = sizeof(*oper);
247
248 if (len < needed)
249 return false;
250
251 /* nothing else present in beacons */
252 if (beacon)
253 return true;
254
255 /* DPS Operation Parameters (fixed 4 bytes) */
256 if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA)) {
257 needed += sizeof(struct ieee80211_uhr_dps_info);
258 if (len < needed)
259 return false;
260 }
261
262 /* NPCA Operation Parameters (fixed 4 bytes + optional 2 bytes) */
263 if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)) {
264 const struct ieee80211_uhr_npca_info *npca =
265 (const void *)(data + needed);
266
267 needed += sizeof(*npca);
268 if (len < needed)
269 return false;
270
271 if (npca->params &
272 cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)) {
273 needed += sizeof(npca->dis_subch_bmap[0]);
274 if (len < needed)
275 return false;
276 }
277 }
278
279 /* P-EDCA Operation Parameters (fixed 3 bytes) */
280 if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA)) {
281 needed += sizeof(struct ieee80211_uhr_p_edca_info);
282 if (len < needed)
283 return false;
284 }
285
286 /* DBE Operation Parameters (fixed 1 byte + optional 2 bytes) */
287 if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DBE_ENA)) {
288 const struct ieee80211_uhr_dbe_info *dbe =
289 (const void *)(data + needed);
290
291 needed += sizeof(*dbe);
292 if (len < needed)
293 return false;
294
295 if (dbe->params &
296 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES) {
297 needed += sizeof(dbe->dis_subch_bmap[0]);
298 if (len < needed)
299 return false;
300 }
301 }
302
303 return len >= needed;
304}
305
306/*
307 * Note: cannot call this on the element coming from a beacon,
308 * must ensure ieee80211_uhr_oper_size_ok(..., false) first
309 */
310static inline const struct ieee80211_uhr_npca_info *
311ieee80211_uhr_npca_info(const struct ieee80211_uhr_operation *oper)
312{
313 const u8 *pos = oper->variable;
314
315 if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)))
316 return NULL;
317
318 if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA))
319 pos += sizeof(struct ieee80211_uhr_dps_info);
320
321 return (const void *)pos;
322}
323
324static inline const __le16 *
325ieee80211_uhr_npca_dis_subch_bitmap(const struct ieee80211_uhr_operation *oper)
326{
327 const struct ieee80211_uhr_npca_info *npca;
328
329 npca = ieee80211_uhr_npca_info(oper);
330 if (!npca)
331 return NULL;
332 if (!(npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)))
333 return NULL;
334 return npca->dis_subch_bmap;
335}
336
337#define IEEE80211_UHR_MAC_CAP0_DPS_SUPP 0x01
338#define IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP 0x02
339#define IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP 0x04
340#define IEEE80211_UHR_MAC_CAP0_NPCA_SUPP 0x10
341#define IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP 0x20
342#define IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP 0x40
343#define IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP 0x80
344
345#define IEEE80211_UHR_MAC_CAP1_DSO_SUPP 0x01
346#define IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP 0x02
347#define IEEE80211_UHR_MAC_CAP1_DBE_SUPP 0x04
348#define IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP 0x08
349#define IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP 0x10
350#define IEEE80211_UHR_MAC_CAP1_PUO_SUPP 0x20
351#define IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP 0x40
352#define IEEE80211_UHR_MAC_CAP1_DUO_SUPP 0x80
353
354#define IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP 0x01
355#define IEEE80211_UHR_MAC_CAP2_AOM_SUPP 0x02
356#define IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP 0x04
357#define IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP 0x08
358#define IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP 0x10
359#define IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG 0x20
360#define IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW 0xC0
361
362#define IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH 0x03
363#define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x1C
364#define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0xE0
365
366#define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x03
367#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04
368#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08
369#define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x10
370
371#define IEEE80211_UHR_MAC_CAP_DBE_MAX_BW 0x07
372#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES 0x08
373#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES 0x10
374
375/**
376 * enum ieee80211_uhr_dbe_max_supported_bw - DBE Maximum Supported Bandwidth
377 *
378 * As per spec P802.11bn_D1.3 "Table 9-bb5—Encoding of the DBE Maximum
379 * Supported Bandwidth field".
380 *
381 * @IEEE80211_UHR_DBE_MAX_BW_40: Indicates 40 MHz DBE max supported bw
382 * @IEEE80211_UHR_DBE_MAX_BW_80: Indicates 80 MHz DBE max supported bw
383 * @IEEE80211_UHR_DBE_MAX_BW_160: Indicates 160 MHz DBE max supported bw
384 * @IEEE80211_UHR_DBE_MAX_BW_320: Indicates 320 MHz DBE max supported bw
385 */
386enum ieee80211_uhr_dbe_max_supported_bw {
387 IEEE80211_UHR_DBE_MAX_BW_40 = 1,
388 IEEE80211_UHR_DBE_MAX_BW_80 = 2,
389 IEEE80211_UHR_DBE_MAX_BW_160 = 3,
390 IEEE80211_UHR_DBE_MAX_BW_320 = 4,
391};
392
393struct ieee80211_uhr_cap_mac {
394 u8 mac_cap[5];
395} __packed;
396
397struct ieee80211_uhr_cap {
398 struct ieee80211_uhr_cap_mac mac;
399 /* DBE, PHY capabilities */
400 u8 variable[];
401} __packed;
402
403#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 0x01
404#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 0x02
405#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 0x04
406#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 0x08
407#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 0x10
408#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 0x20
409#define IEEE80211_UHR_PHY_CAP_ELR_RX 0x40
410#define IEEE80211_UHR_PHY_CAP_ELR_TX 0x80
411
412struct ieee80211_uhr_cap_phy {
413 u8 cap;
414} __packed;
415
416static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len,
417 bool from_ap)
418{
419 const struct ieee80211_uhr_cap *cap = (const void *)data;
420 size_t needed = sizeof(*cap) + sizeof(struct ieee80211_uhr_cap_phy);
421
422 if (len < needed)
423 return false;
424
425 /*
426 * A non-AP STA does not include the DBE Capability Parameters field
427 * in the UHR MAC Capabilities Information field.
428 */
429 if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
430 u8 dbe;
431
432 needed += 1;
433 if (len < needed)
434 return false;
435
436 dbe = cap->variable[0];
437
438 if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
439 needed += 3;
440
441 if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
442 needed += 3;
443 }
444
445 return len >= needed;
446}
447
448static inline const struct ieee80211_uhr_cap_phy *
449ieee80211_uhr_phy_cap(const struct ieee80211_uhr_cap *cap, bool from_ap)
450{
451 u8 offs = 0;
452
453 if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
454 u8 dbe = cap->variable[0];
455
456 offs += 1;
457
458 if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
459 offs += 3;
460
461 if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
462 offs += 3;
463 }
464
465 return (const void *)&cap->variable[offs];
466}
467
468#define IEEE80211_SMD_INFO_CAPA_DL_DATA_FWD 0x01
469#define IEEE80211_SMD_INFO_CAPA_MAX_NUM_PREP 0x0E
470#define IEEE80211_SMD_INFO_CAPA_TYPE 0x10
471#define IEEE80211_SMD_INFO_CAPA_PTK_PER_AP_MLD 0x20
472
473struct ieee80211_smd_info {
474 u8 id[ETH_ALEN];
475 u8 capa;
476 __le16 timeout;
477} __packed;
478
479#endif /* LINUX_IEEE80211_UHR_H */