* [PATCH RFC wireless-next 01/13] wifi: nl80211: reduce multiple deference of link_sta_params
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions Karthikeyan Kathirvel
` (12 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Reduce multiple dereferencing for link_sta_params, since this crosses the
maximum column width in multiple lines.
Replace multiple dereferences of link_sta_params with a local variable
lsta.
No functional changes.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
net/wireless/nl80211.c | 84 ++++++++++++++++++++++--------------------
1 file changed, 44 insertions(+), 40 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c961cd42a832..6b99416862a4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8250,38 +8250,39 @@ static int nl80211_parse_sta_channel_info(struct genl_info *info,
static int nl80211_set_station_tdls(struct genl_info *info,
struct station_parameters *params)
{
+ struct link_station_parameters *lsta = ¶ms->link_sta_params;
int err;
/* Dummy STA entry gets updated once the peer capabilities are known */
if (info->attrs[NL80211_ATTR_PEER_AID])
params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
- params->link_sta_params.ht_capa =
+ lsta->ht_capa =
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
- params->link_sta_params.vht_capa =
+ lsta->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
- params->link_sta_params.he_capa =
+ lsta->he_capa =
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
- params->link_sta_params.he_capa_len =
+ lsta->he_capa_len =
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
- params->link_sta_params.eht_capa =
+ lsta->eht_capa =
nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
- params->link_sta_params.eht_capa_len =
+ lsta->eht_capa_len =
nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
- if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
- (const u8 *)params->link_sta_params.eht_capa,
- params->link_sta_params.eht_capa_len,
+ if (!ieee80211_eht_capa_size_ok((const u8 *)lsta->he_capa,
+ (const u8 *)lsta->eht_capa,
+ lsta->eht_capa_len,
false))
return -EINVAL;
}
}
if (info->attrs[NL80211_ATTR_S1G_CAPABILITY])
- params->link_sta_params.s1g_capa =
+ lsta->s1g_capa =
nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]);
err = nl80211_parse_sta_channel_info(info, params);
@@ -8492,6 +8493,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct link_station_parameters *lsta;
int err;
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -8518,23 +8520,25 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
!info->attrs[NL80211_ATTR_PEER_AID])
return -EINVAL;
- params.link_sta_params.link_id =
+ lsta = ¶ms.link_sta_params;
+
+ lsta->link_id =
nl80211_link_id_or_invalid(info->attrs);
if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
- params.link_sta_params.mld_mac = mac_addr;
- params.link_sta_params.link_mac =
+ lsta->mld_mac = mac_addr;
+ lsta->link_mac =
nla_data(info->attrs[NL80211_ATTR_MAC]);
- if (!is_valid_ether_addr(params.link_sta_params.link_mac))
+ if (!is_valid_ether_addr(lsta->link_mac))
return -EINVAL;
} else {
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
}
- params.link_sta_params.supported_rates =
+ lsta->supported_rates =
nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
- params.link_sta_params.supported_rates_len =
+ lsta->supported_rates_len =
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
params.listen_interval =
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
@@ -8573,28 +8577,28 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
- params.link_sta_params.ht_capa =
+ lsta->ht_capa =
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
- params.link_sta_params.vht_capa =
+ lsta->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
- params.link_sta_params.he_capa =
+ lsta->he_capa =
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
- params.link_sta_params.he_capa_len =
+ lsta->he_capa_len =
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
- params.link_sta_params.eht_capa =
+ lsta->eht_capa =
nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
- params.link_sta_params.eht_capa_len =
+ lsta->eht_capa_len =
nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
- if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
- (const u8 *)params.link_sta_params.eht_capa,
- params.link_sta_params.eht_capa_len,
+ if (!ieee80211_eht_capa_size_ok((const u8 *)lsta->he_capa,
+ (const u8 *)lsta->eht_capa,
+ lsta->eht_capa_len,
false))
return -EINVAL;
}
@@ -8607,7 +8611,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
- params.link_sta_params.he_6ghz_capa =
+ lsta->he_6ghz_capa =
nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
if (info->attrs[NL80211_ATTR_S1G_CAPABILITY])
@@ -8615,8 +8619,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]);
if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
- params.link_sta_params.opmode_notif_used = true;
- params.link_sta_params.opmode_notif =
+ lsta->opmode_notif_used = true;
+ lsta->opmode_notif =
nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
}
@@ -8634,8 +8638,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
err = nl80211_parse_sta_txpower_setting(info,
- ¶ms.link_sta_params.txpwr,
- ¶ms.link_sta_params.txpwr_set);
+ &lsta->txpwr,
+ &lsta->txpwr_set);
if (err)
return err;
@@ -8656,19 +8660,19 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
* error in this case.
*/
if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
- params.link_sta_params.ht_capa = NULL;
- params.link_sta_params.vht_capa = NULL;
+ lsta->ht_capa = NULL;
+ lsta->vht_capa = NULL;
/* HE and EHT require WME */
- if (params.link_sta_params.he_capa_len ||
- params.link_sta_params.he_6ghz_capa ||
- params.link_sta_params.eht_capa_len)
+ if (lsta->he_capa_len ||
+ lsta->he_6ghz_capa ||
+ lsta->eht_capa_len)
return -EINVAL;
}
/* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
- if (params.link_sta_params.he_6ghz_capa &&
- (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
+ if (lsta->he_6ghz_capa &&
+ (lsta->ht_capa || lsta->vht_capa))
return -EINVAL;
/* When you run into this, adjust the code below for the new flag */
@@ -8765,16 +8769,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
/* be aware of params.vlan when changing code here */
if (wdev->valid_links) {
- if (params.link_sta_params.link_id < 0) {
+ if (lsta->link_id < 0) {
err = -EINVAL;
goto out;
}
- if (!(wdev->valid_links & BIT(params.link_sta_params.link_id))) {
+ if (!(wdev->valid_links & BIT(lsta->link_id))) {
err = -ENOLINK;
goto out;
}
} else {
- if (params.link_sta_params.link_id >= 0) {
+ if (lsta->link_id >= 0) {
err = -EINVAL;
goto out;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 01/13] wifi: nl80211: reduce multiple deference of link_sta_params Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 9:08 ` Johannes Berg
2025-12-16 6:26 ` [PATCH RFC wireless-next 03/13] wifi: cfg80211: Add data structures to capture UHR capabilities Karthikeyan Kathirvel
` (11 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Add ieee80211bn MAC and PHY Capabilities based on Draft P802.11bn_D1.0.
Introduce helper functions to calculate UHR capabilities and operation.
Some of fields in UHR capability and operation elements are
still in TBD state in the standard, the bit position and size
adjustments will be done later.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/linux/ieee80211-uhr.h | 416 ++++++++++++++++++++++++++++++++++
include/linux/ieee80211.h | 3 +
2 files changed, 419 insertions(+)
create mode 100644 include/linux/ieee80211-uhr.h
diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h
new file mode 100644
index 000000000000..53259fd7f633
--- /dev/null
+++ b/include/linux/ieee80211-uhr.h
@@ -0,0 +1,416 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * IEEE 802.11 UHR definitions
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef LINUX_IEEE80211_UHR_H
+#define LINUX_IEEE80211_UHR_H
+
+/* UHR MAC capabilities as defined in P802.11bn_D1.0 section 9.4.2.aa2.2 */
+#define IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT 0x01
+#define IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT 0x02
+#define IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPPORT 0x04
+#define IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT 0x08
+#define IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED 0x10
+#define IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT 0x20
+#define IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT 0x40
+#define IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT 0x80
+#define IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT 0x01
+#define IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT 0x02
+#define IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT 0x04
+#define IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT 0x08
+#define IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT 0x10
+#define IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT 0x20
+#define IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT 0x40
+#define IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT 0x80
+#define IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT 0x01
+#define IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT 0x02
+#define IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT 0x04
+#define IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT 0x08
+#define IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT 0x10
+#define IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG 0x20
+#define IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK 0xc0
+#define IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK 0x03
+#define IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK 0x1c
+#define IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK 0xe0
+#define IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK 0x03
+#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04
+#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08
+
+/* UHR PHY capabilities as defined in P802.11bn_D1.0 section 9.4.2.aa2.3 */
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ 0x01
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ 0x02
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ 0x04
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ 0x08
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ 0x10
+#define IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ 0x20
+#define IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT 0x40
+#define IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT 0x80
+
+/**
+ * struct ieee80211_uhr_mcs_nss_supp_20mhz_only - UHR 20 MHz only station max
+ * supported NSS for per MCS.
+ *
+ * As per spec P802.11bn_D1.0 38.3.11 - "UHR-MCS 0-15 are the same as
+ * EHT-MCS 0-15"
+ *
+ * For each field below, bits 0 - 3 indicate the maximal number of spatial
+ * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams
+ * for Tx.
+ *
+ * @rx_tx_mcs7_max_nss: indicates the maximum number of spatial streams
+ * supported for reception and the maximum number of spatial streams
+ * supported for transmission for MCS 0 - 7.
+ * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams
+ * supported for reception and the maximum number of spatial streams
+ * supported for transmission for MCS 8 - 9.
+ * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams
+ * supported for reception and the maximum number of spatial streams
+ * supported for transmission for MCS 10 - 11.
+ * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
+ * supported for reception and the maximum number of spatial streams
+ * supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
+ */
+struct ieee80211_uhr_mcs_nss_supp_20mhz_only {
+ union {
+ struct {
+ u8 rx_tx_mcs7_max_nss;
+ u8 rx_tx_mcs9_max_nss;
+ u8 rx_tx_mcs11_max_nss;
+ u8 rx_tx_mcs13_max_nss;
+ };
+ u8 rx_tx_max_nss[4];
+ };
+} __packed;
+
+#define IEEE80211_UHR_DBE_CAP_MAX_BW GENMASK(2, 0)
+#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ_PRES BIT(3)
+#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ_PRES BIT(4)
+#define IEEE80211_UHR_DBE_CAP_RESERVED GENMASK(7, 5)
+#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ GENMASK(31, 8)
+#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ GENMASK(55, 32)
+
+/**
+ * struct ieee80211_dbe_cap - UHR DBE Capability parameter
+ *
+ * As per spec P802.11bn_D1.0 Figure 9-aa8 "DBE Capability Parameters
+ * field format"
+ *
+ * Please refer IEEE80211_UHR_DBE_CAP*
+ * @dbe_cap_param:
+ * DBE Maximum Supported Bandwidth - indicates the maximum bandwidth
+ * that the AP supports for
+ * DBE operation.
+ * EHT-MCS Map (BW=160 MHz) Present - indicates whether the EHT-MCS Map
+ * (BW=160 MHz) field is present in
+ * the DBE Capability Parameters field
+ * EHT-MCS Map (BW=320 MHz) Present - indicates whether the EHT-MCS Map
+ * (BW=320 MHz) field is present in
+ * the DBE Capability Parameters field
+ * EHT-MCS Map (BW=160 MHz) - indicates the combinations of EHT-MCS 0-13,
+ * and number of spatial streams NSS, that the
+ * AP supports for reception and the
+ * combinations that it supports for
+ * transmission for 160 MHz DBE bandwidth
+ * EHT-MCS Map (BW=320 MHz) - indicates the combinations of EHT-MCS 0-13,
+ * and number of spatial streams NSS, that the
+ * AP supports for reception and the
+ * combinations that it supports for
+ * transmission for 320 MHz DBE bandwidth
+ */
+struct ieee80211_dbe_cap {
+ __le64 dbe_cap_param;
+} __packed;
+
+/**
+ * struct ieee80211_uhr_cap_elem_fixed - UHR capabilities fixed data
+ *
+ * This structure is the "UHR Capabilities element" fixed fields as
+ * described in P802.11bn_D1.0 section 9.4.2.aa2.
+ *
+ * @mac_cap_info: MAC capabilities, see IEEE80211_UHR_MAC_CAP*
+ * @dbe_cap: DBE Capabilities, see IEEE80211_UHR_DBE_CAP*
+ * @phy_cap_info: PHY capabilities, see IEEE80211_UHR_PHY_CAP*
+ */
+struct ieee80211_uhr_cap_elem_fixed {
+ u8 mac_cap_info[5];
+ struct ieee80211_dbe_cap dbe_cap;
+ u8 phy_cap_info[2];
+} __packed;
+
+/**
+ * struct ieee80211_uhr_cap_elem - UHR capabilities element
+ * @fixed: fixed parts, see &ieee80211_uhr_cap_elem_fixed
+ */
+struct ieee80211_uhr_cap_elem {
+ struct ieee80211_uhr_cap_elem_fixed fixed;
+} __packed;
+
+#define IEEE80211_UHR_OPER_DPS_ENABLED BIT(0)
+#define IEEE80211_UHR_OPER_NPCA_ENABLED BIT(1)
+#define IEEE80211_UHR_OPER_DBE_ENABLED BIT(2)
+#define IEEE80211_UHR_OPER_P_EDCA_ENABLED BIT(3)
+
+#define IEEE80211_UHR_DBE_BANDWIDTH GENMASK(2, 0)
+#define IEEE80211_UHR_DBE_RESERVED GENMASK(7, 3)
+#define IEEE80211_UHR_DBE_DIS_SUBCHANNEL_BITMAP GENMASK(15, 0)
+/**
+ * struct ieee80211_dbe_info - dbe operation information
+ *
+ * This structure is the "UHR Operation Element" fields as described
+ * in P802.11bn_D1.0 section 9.4.2.aa1. Refer Figure 9-aa5.
+ *
+ * Please refer IEEE80211_UHR_DBE*
+ * @dbe_bandwidth: DBE Bandwidth field is set to indicate
+ * expanded bandwidth for DBE mode
+ * Value 0 is reserved.
+ * Set to 1 to indicate 40 MHz DBE bandwidth.
+ * Set to 2 to indicate 80 MHz DBE bandwidth.
+ * Set to 3 to indicate 160 MHz DBE bandwidth.
+ * Set to 4 to indicate 320-1 MHz DBE bandwidth.
+ * Set to 5 to indicate 320-2 MHz DBE bandwidth.
+ * Values 6 to 7 are reserved.
+ * @dbe_disabled_subchannel_bitmap: DBE Disabled Subchannel
+ * Bitmap field is set to indicate disabled 20 MHz subchannels
+ * within the DBE Bandwidth.
+ */
+struct ieee80211_dbe_info {
+ u8 dbe_bandwidth;
+ __le16 dbe_disabled_subchannel_bitmap;
+} __packed;
+
+#define IEEE80211_UHR_P_EDCA_ECWMIN GENMASK(3, 0)
+#define IEEE80211_UHR_P_EDCA_ECWMAX GENMASK(7, 4)
+#define IEEE80211_UHR_P_EDCA_AIFSN GENMASK(3, 0)
+#define IEEE80211_UHR_P_EDCA_CW_DS GENMASK(5, 4)
+#define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD GENMASK(8, 6)
+#define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD GENMASK(10, 9)
+#define IEEE80211_UHR_P_EDCA_RESERVED GENMASK(14, 11)
+/**
+ * struct ieee80211_p_edca_info - p_edca operation information
+ *
+ * This structure is the "UHR Operation Element" fields as described
+ * in P802.11bn_D1.0 section 9.4.2.aa1. Refer Figure 9-aa4.
+ *
+ * Please refer IEEE80211_UHR_P_EDCA*
+ * @p_edca_ec: The P-EDCA ECWmin, P-EDCA and ECWmax
+ * fields indicate the CWmin and CWmax
+ * value that are used by a P-EDCA STA during P-EDCA contention.
+ * @p_edca_params: The AIFSN field indicate the AIFSN value that are
+ * used by a P-EDCA STA during P-EDCA contention.
+ * The CW DS field indicate the value used
+ * for the randomization of the transmission slot of the DS-CTS
+ * frame. The value 3 is reserved. The value 0 indicate that
+ * randomization not enabled.
+ * The P-EDCA PSRC threshold field indicates the maximum number
+ * of allowed consecutive DS-CTS transmissions. The value 0 and
+ * values greater than 4 are reserved
+ * The P-EDCA QSRC threshold field indicates the value of the
+ * QSRC[AC_VO] counter to be allowed to start P-EDCA contention.
+ * The value 0 is reserved
+ */
+struct ieee80211_p_edca_info {
+ u8 p_edca_ec;
+ __le16 p_edca_params;
+} __packed;
+
+#define IEEE80211_UHR_NPCA_PRIMARY_CHAN GENMASK(3, 0)
+#define IEEE80211_UHR_NPCA_MIN_DUR_THRESHOLD GENMASK(7, 4)
+#define IEEE80211_UHR_NPCA_SWITCHING_DELAY GENMASK(13, 8)
+#define IEEE80211_UHR_NPCA_SWITCH_BACK_DELAY GENMASK(19, 14)
+#define IEEE80211_UHR_NPCA_INITIAL_QSRC GENMASK(21, 20)
+#define IEEE80211_UHR_NPCA_MOPLEN BIT(22)
+#define IEEE80211_UHR_NPCA_DIS_SUBCHAN_BITMAP_PRESENT BIT(23)
+#define IEEE80211_UHR_NPCA_RESERVED GENMASK(31, 24)
+
+/**
+ * struct ieee80211_npca_info - npca operation information
+ *
+ * This structure is the "UHR Operation Element" fields as described
+ * in P802.11bn_D1.0 section 9.4.2.aa1. Refer Figure 9-aa3.
+ *
+ * Please refer IEEE80211_UHR_NPCA*
+ * @npca_params:
+ * npca_primary_chan - NPCA primary channel
+ * npca_min_dur_threshold - Minimum duration of inter-BSS activity
+ * npca_switching_delay - Time needed by an NPCA AP to switch from the
+ * BSS primary channel to the NPCA primary channel
+ * in the unit of 4 µs.
+ * npca_switch_back_delay - Time to switch from the NPCA primary channel
+ * to the BSS primary channel in the unit of 4 µs.
+ * npca_initial_qsrc - initialize the EDCAF QSRC[AC] variables
+ * when an NPCA STA in the BSS
+ * switches to NPCA operation.
+ * npca_moplen - indicates which conditions can be used to
+ * initiate an NPCA operation,
+ * 1 -> both PHYLEN NPCA operation and MOPLEN
+ * NPCA operation are
+ * permitted in the BSS
+ * 0 -> only PHYLEN NPCA operation is allowed in the BSS.
+ * @npca_disabled_subchan_bitmap: indicates whether the NPCA
+ * Disabled Subchannel
+ * Bitmap field is present.
+ */
+struct ieee80211_npca_info {
+ __le32 npca_params;
+ __le16 npca_disabled_subchan_bitmap;
+} __packed;
+
+#define IEEE80211_UHR_DPS_PADDING_DELAY GENMASK(5, 0)
+#define IEEE80211_UHR_DPS_RESERVED1 GENMASK(7, 6)
+#define IEEE80211_UHR_DPS_TRANSITION_DELAY GENMASK(13, 8)
+#define IEEE80211_UHR_DPS_RESERVED2 GENMASK(15, 14)
+#define IEEE80211_UHR_DPS_ICF_REQUIRED BIT(16)
+#define IEEE80211_UHR_DPS_PARAMETERIZED_FLAG BIT(17)
+#define IEEE80211_UHR_DPS_LC_MODE_BW GENMASK(20, 18)
+#define IEEE80211_UHR_DPS_LC_MODE_NSS GENMASK(24, 21)
+#define IEEE80211_UHR_DPS_LC_MODE_MCS GENMASK(28, 25)
+#define IEEE80211_UHR_DPS_MOBILE_AP_DPS_STATIC_HCM BIT(29)
+#define IEEE80211_UHR_DPS_RESERVED3 GENMASK(31, 30)
+
+/**
+ * struct ieee80211_dps_info - dps operation information
+ *
+ * This structure is the "UHR Operation Element" fields as described
+ * in P802.11bn_D1.0 section 9.4.1.87. Refer Figure 9-207u.
+ *
+ * Please refer IEEE80211_UHR_DPS*
+ * @dps_delay_params:
+ * DPS Padding Delay - indicates the minimum MAC padding
+ * duration that is required by a DPS STA
+ * in an ICF to cause the STA to transition
+ * from the lower capability mode to the
+ * higher capability mode. The DPS Padding
+ * Delay field is in units of 4 µs.
+ * DPS Transition - indicates the amount of time required by a
+ * DPS STA to transition from the higher
+ * capability mode to the lower capability
+ * mode. The DPS Transition Delay field is in
+ * units of 4 µs.
+ * @dps_params:
+ * ICF Required - indicates when the DPS assisting STA needs
+ * to transmit an ICF frame to the peer DPS STA
+ * before performing the frame exchanges with
+ * the peer DPS STA in a TXOP.
+ * 1 -> indicates that the transmission of the
+ * ICF frame to the peer DPS STA prior to
+ * any frame exchange is needed.
+ * 0 -> ICF transmission before the frame
+ * exchanges with the peer DPS STA is only
+ * needed if the frame exchange is performed
+ * in the HC mode.
+ * Parameterized Flag - 0 -> indicate that only 20 MHz, 1 SS,
+ * non-HT PPDU format with the data
+ * rate of 6, 12, and 24 Mb/s as the
+ * default mode are supported by the
+ * DPS STA in the LC mode
+ * 1 -> indicate that a bandwidth up to the
+ * bandwidth indicated in the LC Mode
+ * Bandwidth field, a number of spatial
+ * streams up to the NSS indicated in
+ * the LC Mode Nss field, and an MCS up
+ * to the MCS indicated in the LC Mode
+ * MCS fields are supported by the DPS
+ * STA in the LC mode as the
+ * parameterized mode.
+ * LC Mode Bandwidth - indicates the maximum bandwidth supported
+ * by the STA in the LC mode.
+ * LC Mode Nss - indicates the maximum number of the spatial
+ * streams supported by the STA in the LC mode.
+ * LC Mode MCS - indicates the highest MCS supported by the STA
+ * in the LC mode.
+ * Mobile AP DPS Static HCM -
+ * 1 -> indicate that it will remain in the DPS high
+ * capability mode until the next TBTT on that
+ * link.
+ * 0 -> otherwise.
+ */
+struct ieee80211_dps_info {
+ __le16 dps_delay_params;
+ __le16 dps_params;
+} __packed;
+
+/**
+ * struct ieee80211_uhr_operation_info - uhr operation information
+ *
+ * @dps_info: DPS operation information
+ * @npca_info: NPCA operation information
+ * @p_edca_info: P-EDCA operation information
+ * @dbe_info: DBE operation information
+ */
+struct ieee80211_uhr_operation_info {
+ struct ieee80211_dps_info dps_info;
+ struct ieee80211_npca_info npca_info;
+ struct ieee80211_p_edca_info p_edca_info;
+ struct ieee80211_dbe_info dbe_info;
+} __packed;
+
+/**
+ * struct ieee80211_uhr_operation - uhr operation element
+ *
+ * This structure is the "UHR Operation Element" fields as
+ * described in P802.11bn_D1.0 section 9.4.2.aa1
+ *
+ * @params: UHR operation element parameters. See &IEEE80211_UHR_OPER_*
+ * @basic_mcs_nss: indicates the UHR-MCSs for each number of spatial streams in
+ * UHR PPDUs that are supported by all UHR STAs in the BSS in transmit and
+ * receive.
+ * @optional: optional parts
+ */
+
+struct ieee80211_uhr_operation {
+ __le16 params;
+ struct ieee80211_uhr_mcs_nss_supp_20mhz_only basic_mcs_nss;
+ u8 optional[];
+} __packed;
+
+static inline bool
+ieee80211_uhr_capa_size_ok(const u8 *data, u8 len)
+{
+ const struct ieee80211_uhr_cap_elem_fixed *elem = (const void *)data;
+ u8 needed = sizeof(struct ieee80211_uhr_cap_elem_fixed) -
+ sizeof(struct ieee80211_dbe_cap);
+
+ if (elem->mac_cap_info[1] &
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT) {
+ needed += 1;
+
+ if (le64_to_cpu(elem->dbe_cap.dbe_cap_param) &
+ IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ_PRES)
+ needed += 3;
+
+ if (le64_to_cpu(elem->dbe_cap.dbe_cap_param) &
+ IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ_PRES)
+ needed += 3;
+ }
+
+ return len >= needed;
+}
+
+static inline bool
+ieee80211_uhr_oper_size_ok(const u8 *data, u8 len, bool is_bcn)
+{
+ const struct ieee80211_uhr_operation *elem = (const void *)data;
+ u8 needed = sizeof(*elem);
+
+ if (len < needed)
+ return false;
+
+ if (is_bcn)
+ return len >= needed;
+
+ if (le16_to_cpu(elem->params) & IEEE80211_UHR_OPER_DPS_ENABLED)
+ needed += sizeof(struct ieee80211_dps_info);
+ if (le16_to_cpu(elem->params) & IEEE80211_UHR_OPER_NPCA_ENABLED)
+ needed += sizeof(struct ieee80211_npca_info);
+ if (le16_to_cpu(elem->params) & IEEE80211_UHR_OPER_DBE_ENABLED)
+ needed += sizeof(struct ieee80211_dbe_info);
+ if (le16_to_cpu(elem->params) & IEEE80211_UHR_OPER_P_EDCA_ENABLED)
+ needed += sizeof(struct ieee80211_p_edca_info);
+
+ return len >= needed;
+}
+
+#endif /* LINUX_IEEE80211_UHR_H */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 96439de55f07..8497c45bd96a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1801,6 +1801,8 @@ enum ieee80211_eid_ext {
WLAN_EID_EXT_BANDWIDTH_INDICATION = 135,
WLAN_EID_EXT_KNOWN_STA_IDENTIFCATION = 136,
WLAN_EID_EXT_NON_AP_STA_REG_CON = 137,
+ WLAN_EID_EXT_UHR_OPERATION = 151,
+ WLAN_EID_EXT_UHR_CAPABILITY = 152,
};
/* Action category code */
@@ -2820,6 +2822,7 @@ struct ieee80211_tbtt_info_ge_11 {
#include "ieee80211-vht.h"
#include "ieee80211-he.h"
#include "ieee80211-eht.h"
+#include "ieee80211-uhr.h"
#include "ieee80211-mesh.h"
#include "ieee80211-s1g.h"
#include "ieee80211-p2p.h"
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions
2025-12-16 6:26 ` [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions Karthikeyan Kathirvel
@ 2025-12-16 9:08 ` Johannes Berg
2025-12-17 12:54 ` Karthikeyan Kathirvel
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2025-12-16 9:08 UTC (permalink / raw)
To: Karthikeyan Kathirvel; +Cc: linux-wireless
On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
>
> +/**
> + * struct ieee80211_uhr_mcs_nss_supp_20mhz_only - UHR 20 MHz only station max
> + * supported NSS for per MCS.
I think I'd rename this? Due to
> + * As per spec P802.11bn_D1.0 38.3.11 - "UHR-MCS 0-15 are the same as
> + * EHT-MCS 0-15"
it will only ever be used for basic UHR MCSes.
> +#define IEEE80211_UHR_DBE_CAP_MAX_BW GENMASK(2, 0)
> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ_PRES BIT(3)
> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ_PRES BIT(4)
> +#define IEEE80211_UHR_DBE_CAP_RESERVED GENMASK(7, 5)
> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ GENMASK(31, 8)
> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ GENMASK(55, 32)
For the record, I'm not a huge fan of GENMASK(), I tend to think just
hex is more readable :-)
Here, using GENMASK() is also wrong for the last one of those, and it's
really not obvious.
> +/**
> + * struct ieee80211_uhr_operation_info - uhr operation information
nit: "UHR" (throughout)
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions
2025-12-16 9:08 ` Johannes Berg
@ 2025-12-17 12:54 ` Karthikeyan Kathirvel
2025-12-17 12:55 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-17 12:54 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 12/16/2025 2:38 PM, Johannes Berg wrote:
> On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
>>
>> +/**
>> + * struct ieee80211_uhr_mcs_nss_supp_20mhz_only - UHR 20 MHz only station max
>> + * supported NSS for per MCS.
>
> I think I'd rename this? Due to
>
>> + * As per spec P802.11bn_D1.0 38.3.11 - "UHR-MCS 0-15 are the same as
>> + * EHT-MCS 0-15"
>
> it will only ever be used for basic UHR MCSes.
>
Noted.
>> +#define IEEE80211_UHR_DBE_CAP_MAX_BW GENMASK(2, 0)
>> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ_PRES BIT(3)
>> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ_PRES BIT(4)
>> +#define IEEE80211_UHR_DBE_CAP_RESERVED GENMASK(7, 5)
>> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ GENMASK(31, 8)
>> +#define IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ GENMASK(55, 32)
>
> For the record, I'm not a huge fan of GENMASK(), I tend to think just
> hex is more readable :-)
>
> Here, using GENMASK() is also wrong for the last one of those, and it's
> really not obvious.
>
>
Sure, I will change it to hex format. Last bit mask is fine right it is
from B32 - B55, what is wrong here ?
>> +/**
>> + * struct ieee80211_uhr_operation_info - uhr operation information
>
> nit: "UHR" (throughout)
>
> johannes
Sure, will address it
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions
2025-12-17 12:54 ` Karthikeyan Kathirvel
@ 2025-12-17 12:55 ` Johannes Berg
2025-12-17 12:56 ` Karthikeyan Kathirvel
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2025-12-17 12:55 UTC (permalink / raw)
To: Karthikeyan Kathirvel; +Cc: linux-wireless
On Wed, 2025-12-17 at 18:24 +0530, Karthikeyan Kathirvel wrote:
> >
> Sure, I will change it to hex format. Last bit mask is fine right it is
> from B32 - B55, what is wrong here ?
You'd need GENMASK_ULL()
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions
2025-12-17 12:55 ` Johannes Berg
@ 2025-12-17 12:56 ` Karthikeyan Kathirvel
0 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-17 12:56 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 12/17/2025 6:25 PM, Johannes Berg wrote:
> On Wed, 2025-12-17 at 18:24 +0530, Karthikeyan Kathirvel wrote:
>>>
>> Sure, I will change it to hex format. Last bit mask is fine right it is
>> from B32 - B55, what is wrong here ?
>
> You'd need GENMASK_ULL()
>
> johannes
Oops Sorry, thanks for pointing out :)
/KK
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH RFC wireless-next 03/13] wifi: cfg80211: Add data structures to capture UHR capabilities
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 01/13] wifi: nl80211: reduce multiple deference of link_sta_params Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 02/13] wifi: ieee80211: Add UHR (802.11bn) definitions Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 04/13] wifi: cfg80211: add a helper function to return the UHR interface capabilities Karthikeyan Kathirvel
` (10 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Add data structures to capture UHR capabilities and advertise UHR
capabilities to user space when supported via NL attributes.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 16 ++++++++++++++++
include/uapi/linux/nl80211.h | 6 ++++++
net/wireless/nl80211.c | 11 +++++++++++
3 files changed, 33 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 899f267b7cf9..378fd54c282c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -429,6 +429,20 @@ struct ieee80211_sta_eht_cap {
u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN];
};
+/**
+ * struct ieee80211_sta_uhr_cap - STA's UHR capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11bn UHR capabilities for a STA.
+ *
+ * @has_uhr: true if UHR data is valid.
+ * @uhr_cap_elem: Fixed portion of the uhr capabilities element.
+ */
+struct ieee80211_sta_uhr_cap {
+ bool has_uhr;
+ struct ieee80211_uhr_cap_elem_fixed uhr_cap_elem;
+};
+
/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
#ifdef __CHECKER__
/*
@@ -454,6 +468,7 @@ struct ieee80211_sta_eht_cap {
* @he_6ghz_capa: HE 6 GHz capabilities, must be filled in for a
* 6 GHz band channel (and 0 may be valid value).
* @eht_cap: STA's EHT capabilities
+ * @uhr_cap: STA's UHR capabilities
* @vendor_elems: vendor element(s) to advertise
* @vendor_elems.data: vendor element(s) data
* @vendor_elems.len: vendor element(s) length
@@ -463,6 +478,7 @@ struct ieee80211_sband_iftype_data {
struct ieee80211_sta_he_cap he_cap;
struct ieee80211_he_6ghz_capa he_6ghz_capa;
struct ieee80211_sta_eht_cap eht_cap;
+ struct ieee80211_sta_uhr_cap uhr_cap;
struct {
const u8 *data;
unsigned int len;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8134f10e4e6c..8d9038ba1208 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4248,6 +4248,10 @@ enum nl80211_mpath_info {
* capabilities element
* @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as
* defined in EHT capabilities element
+ * @NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC: UHR MAC capabilities as in UHR
+ * capabilities element
+ * @NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY: UHR PHY capabilities as in UHR
+ * capabilities element
* @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use
* @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined
*/
@@ -4265,6 +4269,8 @@ enum nl80211_band_iftype_attr {
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
+ NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC,
+ NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY,
/* keep last */
__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6b99416862a4..d05d098c4dc7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1947,6 +1947,7 @@ nl80211_send_iftype_data(struct sk_buff *msg,
{
const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
+ const struct ieee80211_sta_uhr_cap *uhr_cap = &iftdata->uhr_cap;
if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
iftdata->types_mask))
@@ -2004,6 +2005,16 @@ nl80211_send_iftype_data(struct sk_buff *msg,
&iftdata->he_6ghz_capa))
return -ENOBUFS;
+ if (uhr_cap->has_uhr && eht_cap->has_eht && he_cap->has_he) {
+ if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_UHR_CAP_MAC,
+ sizeof(uhr_cap->uhr_cap_elem.mac_cap_info),
+ uhr_cap->uhr_cap_elem.mac_cap_info) ||
+ nla_put(msg, NL80211_BAND_IFTYPE_ATTR_UHR_CAP_PHY,
+ sizeof(uhr_cap->uhr_cap_elem.phy_cap_info),
+ uhr_cap->uhr_cap_elem.phy_cap_info))
+ return -ENOBUFS;
+ }
+
if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
iftdata->vendor_elems.len, iftdata->vendor_elems.data))
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 04/13] wifi: cfg80211: add a helper function to return the UHR interface capabilities
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (2 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 03/13] wifi: cfg80211: Add data structures to capture UHR capabilities Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 05/13] wifi: cfg80211: Support configuration of station UHR capabilities Karthikeyan Kathirvel
` (9 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Introduce a helper function which returns the UHR capabilities based on the
interface type.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 378fd54c282c..7964dd1ee691 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -720,6 +720,26 @@ ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *sband,
return NULL;
}
+/**
+ * ieee80211_get_uhr_iftype_cap - return UHR capabilities for an sband's iftype
+ * @sband: the sband to search for the iftype on
+ * @iftype: enum nl80211_iftype
+ *
+ * Return: pointer to the struct ieee80211_sta_uhr_cap, or NULL if none found
+ */
+static inline const struct ieee80211_sta_uhr_cap *
+ieee80211_get_uhr_iftype_cap(const struct ieee80211_supported_band *sband,
+ enum nl80211_iftype iftype)
+{
+ const struct ieee80211_sband_iftype_data *data =
+ ieee80211_get_sband_iftype_data(sband, iftype);
+
+ if (data && data->uhr_cap.has_uhr)
+ return &data->uhr_cap;
+
+ return NULL;
+}
+
/**
* wiphy_read_of_freq_limits - read frequency limits from device tree
*
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 05/13] wifi: cfg80211: Support configuration of station UHR capabilities
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (3 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 04/13] wifi: cfg80211: add a helper function to return the UHR interface capabilities Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 06/13] wifi: nl80211: retrieve UHR related elements in AP mode Karthikeyan Kathirvel
` (8 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Introduce support for configuring UHR capabilities of stations
via userspace. This includes adding new attributes and corresponding
logic to parse and apply the UHR parameters provided by userspace
applications.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 4 +++
include/uapi/linux/nl80211.h | 13 ++++++++
net/wireless/nl80211.c | 63 ++++++++++++++++++++++++++++++++----
3 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7964dd1ee691..7593f1a1875b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1734,6 +1734,8 @@ struct sta_txpwr {
* @eht_capa: EHT capabilities of station
* @eht_capa_len: the length of the EHT capabilities
* @s1g_capa: S1G capabilities of station
+ * @uhr_capa: UHR capabilities of station
+ * @uhr_capa_len: the length of the UHR capabilities
*/
struct link_station_parameters {
const u8 *mld_mac;
@@ -1753,6 +1755,8 @@ struct link_station_parameters {
const struct ieee80211_eht_cap_elem *eht_capa;
u8 eht_capa_len;
const struct ieee80211_s1g_cap *s1g_capa;
+ const struct ieee80211_uhr_cap_elem *uhr_capa;
+ u8 uhr_capa_len;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8d9038ba1208..3488fa638bbd 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2973,6 +2973,10 @@ enum nl80211_commands {
* primary channel is 2 MHz wide, and the control channel designates
* the 1 MHz primary subchannel within that 2 MHz primary.
*
+ * @NL80211_ATTR_UHR_CAPABILITY: UHR Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION). Can be set
+ * only if %NL80211_STA_FLAG_WME is set.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3541,6 +3545,8 @@ enum nl80211_attrs {
NL80211_ATTR_S1G_PRIMARY_2MHZ,
+ NL80211_ATTR_UHR_CAPABILITY,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3612,6 +3618,13 @@ enum nl80211_attrs {
#define NL80211_CQM_TXE_MAX_INTVL 1800
+/*
+ * TODO: as of now used the len same as EHT, modify it
+ * based on UHR once spec is finalized
+ */
+#define NL80211_UHR_MIN_CAPABILITY_LEN 2
+#define NL80211_UHR_MAX_CAPABILITY_LEN 51
+
/**
* enum nl80211_iftype - (virtual) interface types
*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d05d098c4dc7..a54618eae8e5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -932,6 +932,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NLA_POLICY_NESTED(nl80211_s1g_short_beacon),
[NL80211_ATTR_BSS_PARAM] = { .type = NLA_FLAG },
[NL80211_ATTR_S1G_PRIMARY_2MHZ] = { .type = NLA_FLAG },
+ [NL80211_ATTR_UHR_CAPABILITY] =
+ NLA_POLICY_RANGE(NLA_BINARY, NL80211_UHR_MIN_CAPABILITY_LEN,
+ NL80211_UHR_MAX_CAPABILITY_LEN),
};
/* policy for the key attributes */
@@ -8292,6 +8295,19 @@ static int nl80211_set_station_tdls(struct genl_info *info,
}
}
+ if (info->attrs[NL80211_ATTR_HE_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_EHT_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_UHR_CAPABILITY]) {
+ lsta->uhr_capa =
+ nla_data(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+ lsta->uhr_capa_len =
+ nla_len(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+
+ if (!ieee80211_uhr_capa_size_ok((const u8 *)lsta->uhr_capa,
+ lsta->uhr_capa_len))
+ return -EINVAL;
+ }
+
if (info->attrs[NL80211_ATTR_S1G_CAPABILITY])
lsta->s1g_capa =
nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]);
@@ -8615,6 +8631,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
}
}
+ if (info->attrs[NL80211_ATTR_HE_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_EHT_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_UHR_CAPABILITY]) {
+ const u8 *uhr_capa;
+
+ lsta->uhr_capa =
+ nla_data(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+ lsta->uhr_capa_len =
+ nla_len(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+
+ uhr_capa = (const u8 *)lsta->uhr_capa;
+
+ if (!ieee80211_uhr_capa_size_ok(uhr_capa,
+ lsta->uhr_capa_len))
+ return -EINVAL;
+ }
+
if (info->attrs[NL80211_ATTR_EML_CAPABILITY]) {
params.eml_cap_present = true;
params.eml_cap =
@@ -8665,19 +8698,20 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms))
return -EINVAL;
- /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
- * as userspace might just pass through the capabilities from the IEs
- * directly, rather than enforcing this restriction and returning an
- * error in this case.
+ /* HT/VHT/EHT and UHR requires QoS, but if we don't have that just
+ * ignore HT/VHT/EHT and UHR as userspace might just pass through
+ * the capabilities from the IEs directly, rather than enforcing
+ * this restriction and returning an error in this case.
*/
if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
lsta->ht_capa = NULL;
lsta->vht_capa = NULL;
- /* HE and EHT require WME */
+ /* HE, EHT and UHR require WME */
if (lsta->he_capa_len ||
lsta->he_6ghz_capa ||
- lsta->eht_capa_len)
+ lsta->eht_capa_len ||
+ lsta->uhr_capa_len)
return -EINVAL;
}
@@ -17651,6 +17685,23 @@ nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
}
}
+ if (info->attrs[NL80211_ATTR_HE_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_EHT_CAPABILITY] &&
+ info->attrs[NL80211_ATTR_UHR_CAPABILITY]) {
+ const u8 *uhr_capa;
+
+ params.uhr_capa =
+ nla_data(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+ params.uhr_capa_len =
+ nla_len(info->attrs[NL80211_ATTR_UHR_CAPABILITY]);
+
+ uhr_capa = (const u8 *)params.uhr_capa;
+
+ if (!ieee80211_uhr_capa_size_ok(uhr_capa,
+ params.uhr_capa_len))
+ return -EINVAL;
+ }
+
if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
params.he_6ghz_capa =
nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 06/13] wifi: nl80211: retrieve UHR related elements in AP mode
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (4 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 05/13] wifi: cfg80211: Support configuration of station UHR capabilities Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 07/13] wifi: nl80211/reg: add no-UHR regulatory flag Karthikeyan Kathirvel
` (7 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
As per spec, ieee80211bn D1.0 Section 37.29 Beacon Optimization,
add support to retrieve UHR operation elements passed by the
userspace in the beacon template and store the pointers
in struct cfg80211_ap_settings to be used by the drivers.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 2 ++
net/wireless/nl80211.c | 10 ++++++++++
2 files changed, 12 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7593f1a1875b..e3b66da4c243 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1522,6 +1522,7 @@ struct cfg80211_s1g_short_beacon {
* @he_cap: HE capabilities (or %NULL if HE isn't enabled)
* @eht_cap: EHT capabilities (or %NULL if EHT isn't enabled)
* @eht_oper: EHT operation IE (or %NULL if EHT isn't enabled)
+ * @uhr_oper: UHR operation IE (or %NULL if UHR isn't enabled)
* @ht_required: stations must support HT
* @vht_required: stations must support VHT
* @twt_responder: Enable Target Wait Time
@@ -1561,6 +1562,7 @@ struct cfg80211_ap_settings {
const struct ieee80211_he_operation *he_oper;
const struct ieee80211_eht_cap_elem *eht_cap;
const struct ieee80211_eht_operation *eht_oper;
+ const struct ieee80211_uhr_operation *uhr_oper;
bool ht_required, vht_required, he_required, sae_h2e_required;
bool twt_responder;
u32 flags;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a54618eae8e5..7fc0f675a383 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6443,6 +6443,16 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
cap->datalen - 1))
return -EINVAL;
}
+ cap = cfg80211_find_ext_elem(WLAN_EID_EXT_UHR_OPERATION, ies, ies_len);
+ if (cap) {
+ if (!cap->datalen)
+ return -EINVAL;
+ params->uhr_oper = (void *)(cap->data + 1);
+ if (!ieee80211_uhr_oper_size_ok((const u8 *)params->uhr_oper,
+ cap->datalen - 1, true))
+ return -EINVAL;
+ }
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 07/13] wifi: nl80211/reg: add no-UHR regulatory flag
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (5 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 06/13] wifi: nl80211: retrieve UHR related elements in AP mode Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 08/13] wifi: mac80211: Support parsing UHR elements Karthikeyan Kathirvel
` (6 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
If driver disables a channel based on its regulatory rule with
NL80211_RRF_NO_UHR flag, disable UHR operation.
This is needed to disable particular channels which are not
supported/allowed in that country.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 5 +++++
net/wireless/nl80211.c | 8 ++++++++
net/wireless/reg.c | 2 ++
4 files changed, 17 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e3b66da4c243..85321948b7ec 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -126,6 +126,7 @@ struct wiphy;
* @IEEE80211_CHAN_NO_4MHZ: 4 MHz bandwidth is not permitted on this channel.
* @IEEE80211_CHAN_NO_8MHZ: 8 MHz bandwidth is not permitted on this channel.
* @IEEE80211_CHAN_NO_16MHZ: 16 MHz bandwidth is not permitted on this channel.
+ * @IEEE80211_CHAN_NO_UHR: UHR operation is not permitted on this channel.
*/
enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = BIT(0),
@@ -155,6 +156,7 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_4MHZ = BIT(28),
IEEE80211_CHAN_NO_8MHZ = BIT(29),
IEEE80211_CHAN_NO_16MHZ = BIT(30),
+ IEEE80211_CHAN_NO_UHR = BIT(31),
};
#define IEEE80211_CHAN_NO_HT40 \
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 3488fa638bbd..9e957378f43b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4463,6 +4463,8 @@ enum nl80211_wmm_rule {
* channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_NO_16MHZ: 16 MHz operation is not allowed on this
* channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_UHR: UHR operation is not allowed on this channel
+ * in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4511,6 +4513,7 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_4MHZ,
NL80211_FREQUENCY_ATTR_NO_8MHZ,
NL80211_FREQUENCY_ATTR_NO_16MHZ,
+ NL80211_FREQUENCY_ATTR_NO_UHR,
/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -4724,6 +4727,7 @@ enum nl80211_sched_scan_match_attr {
* despite NO_IR configuration.
* @NL80211_RRF_ALLOW_20MHZ_ACTIVITY: Allow activity in 20 MHz bandwidth,
* despite NO_IR configuration.
+ * @NL80211_RRF_NO_UHR: UHR operation not allowed
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1 << 0,
@@ -4750,6 +4754,7 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1 << 23,
NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1 << 24,
NL80211_RRF_ALLOW_20MHZ_ACTIVITY = 1 << 25,
+ NL80211_RRF_NO_UHR = 1 << 26,
};
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7fc0f675a383..cb0592c292b4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1317,6 +1317,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
if ((chan->flags & IEEE80211_CHAN_NO_16MHZ) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_16MHZ))
goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_NO_UHR) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_UHR))
+ goto nla_put_failure;
}
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
@@ -6576,6 +6579,11 @@ static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params
(channel->flags & IEEE80211_CHAN_NO_EHT))
return -EOPNOTSUPP;
+ /* Check for uhr_capa if it is parsed in start_ap */
+ if (params->uhr_oper &&
+ (channel->flags & IEEE80211_CHAN_NO_UHR))
+ return -EOPNOTSUPP;
+
return 0;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 73cab51f6379..c995f33cb212 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1605,6 +1605,8 @@ static u32 map_regdom_flags(u32 rd_flags)
channel_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP;
if (rd_flags & NL80211_RRF_ALLOW_20MHZ_ACTIVITY)
channel_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY;
+ if (rd_flags & NL80211_RRF_NO_UHR)
+ channel_flags |= IEEE80211_CHAN_NO_UHR;
return channel_flags;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 08/13] wifi: mac80211: Support parsing UHR elements
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (6 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 07/13] wifi: nl80211/reg: add no-UHR regulatory flag Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 9:10 ` Johannes Berg
2025-12-16 6:26 ` [PATCH RFC wireless-next 09/13] wifi: mac80211: Add UHR capabilities to association/probe request for STA mode Karthikeyan Kathirvel
` (5 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Parse the new UHR elements in the element parsing utilities.
As per spec ieee80211bn D1.0 Section 37.29 Beacon Optimization
"A UHR AP shall not include the parameters associated with
operating modes currently enabled at the AP defined by UHR
in the UHR Operation element or any other element carried in the
Beacon frame, except when specified otherwise"
For beacon frames UHR operation size check done only for UHR operation
parameters not for operation information.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
net/mac80211/ieee80211_i.h | 5 +++++
net/mac80211/mlme.c | 2 ++
net/mac80211/parse.c | 13 +++++++++++++
3 files changed, 20 insertions(+)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9d9313eee59f..04f1df209cec 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1826,6 +1826,8 @@ struct ieee802_11_elems {
const struct ieee80211_multi_link_elem *ml_epcs;
const struct ieee80211_bandwidth_indication *bandwidth_indication;
const struct ieee80211_ttlm_elem *ttlm[IEEE80211_TTLM_MAX_CNT];
+ const struct ieee80211_uhr_cap_elem *uhr_cap;
+ const struct ieee80211_uhr_operation *uhr_operation;
/* not the order in the psd values is per element, not per chandef */
struct ieee80211_parsed_tpe tpe;
@@ -1866,6 +1868,7 @@ struct ieee802_11_elems {
struct ieee80211_mle_per_sta_profile *prof;
size_t sta_prof_len;
+ u8 uhr_cap_len;
/* whether/which parse error occurred while retrieving these elements */
u8 parse_error;
};
@@ -2423,6 +2426,7 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
* @mode: connection mode for parsing
* @start: pointer to the elements
* @len: length of the elements
+ * @is_beacon: %true if the elements came from beacon frame
* @type: type of the frame the elements came from
* (action, probe response, beacon, etc.)
* @filter: bitmap of element IDs to filter out while calculating
@@ -2442,6 +2446,7 @@ struct ieee80211_elems_parse_params {
enum ieee80211_conn_mode mode;
const u8 *start;
size_t len;
+ bool is_beacon;
u8 type;
u64 filter;
u32 crc;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e56ad4b9330f..73649d57d0c3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -7400,6 +7400,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
!WARN_ON(ieee80211_vif_is_mld(&sdata->vif)) &&
ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->link[0].bss)) {
parse_params.bss = ifmgd->assoc_data->link[0].bss;
+ parse_params.is_beacon = true;
elems = ieee802_11_parse_elems_full(&parse_params);
if (!elems)
return;
@@ -7470,6 +7471,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
parse_params.bss = bss_conf->bss;
parse_params.filter = care_about_ies;
parse_params.crc = ncrc;
+ parse_params.is_beacon = true;
elems = ieee802_11_parse_elems_full(&parse_params);
if (!elems)
return;
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index bfc4ecb7a048..ed8411aa8b32 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -189,6 +189,17 @@ ieee80211_parse_extension_element(u32 *crc,
elems->ttlm_num++;
}
break;
+ case WLAN_EID_EXT_UHR_CAPABILITY:
+ if (ieee80211_uhr_capa_size_ok(data, len)) {
+ elems->uhr_cap = data;
+ elems->uhr_cap_len = len;
+ }
+ break;
+ case WLAN_EID_EXT_UHR_OPERATION:
+ if (ieee80211_uhr_oper_size_ok(data, len, params->is_beacon))
+ elems->uhr_operation = data;
+ calc_crc = true;
+ break;
}
if (crc && calc_crc)
@@ -963,6 +974,7 @@ ieee80211_prep_mle_link_parse(struct ieee80211_elems_parse *elems_parse,
sub->mode = params->mode;
sub->type = params->type;
+ sub->is_beacon = params->is_beacon;
sub->from_ap = params->from_ap;
sub->link_id = -1;
@@ -1062,6 +1074,7 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
sub.mode = params->mode;
sub.len = nontx_len;
sub.type = params->type;
+ sub.is_beacon = params->is_beacon;
sub.link_id = params->link_id;
/* consume the space used for non-transmitted profile */
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 09/13] wifi: mac80211: Add UHR capabilities to association/probe request for STA mode
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (7 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 08/13] wifi: mac80211: Support parsing UHR elements Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 10/13] wifi: mac80211: Handle station association response with UHR Karthikeyan Kathirvel
` (4 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Add the UHR capabilities element to both probe request and
association request frames, if advertised by the driver.
Introduce IEEE80211_CONN_MODE_UHR flag to disable the UHR connection
if AP doesn't send UHR operation or the operating channel is not UHR
supported.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/mac80211.h | 14 ++++++++++++++
net/mac80211/ieee80211_i.h | 4 ++++
net/mac80211/main.c | 12 +++++++++++-
net/mac80211/mlme.c | 37 +++++++++++++++++++++++++++++++++++-
net/mac80211/parse.c | 4 ++++
net/mac80211/util.c | 39 +++++++++++++++++++++++++++++++++++++-
6 files changed, 107 insertions(+), 3 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c2e49542626c..7f1d2953a074 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -7236,6 +7236,20 @@ ieee80211_get_eht_iftype_cap_vif(const struct ieee80211_supported_band *sband,
return ieee80211_get_eht_iftype_cap(sband, ieee80211_vif_type_p2p(vif));
}
+/**
+ * ieee80211_get_uhr_iftype_cap_vif - return UHR capabilities for sband/vif
+ * @sband: the sband to search for the iftype on
+ * @vif: the vif to get the iftype from
+ *
+ * Return: pointer to the struct ieee80211_sta_uhr_cap, or %NULL is none found
+ */
+static inline const struct ieee80211_sta_uhr_cap *
+ieee80211_get_uhr_iftype_cap_vif(const struct ieee80211_supported_band *sband,
+ struct ieee80211_vif *vif)
+{
+ return ieee80211_get_uhr_iftype_cap(sband, ieee80211_vif_type_p2p(vif));
+}
+
/**
* ieee80211_update_mu_groups - set the VHT MU-MIMO groud data
*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 04f1df209cec..3a61710b1532 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -394,6 +394,7 @@ enum ieee80211_conn_mode {
IEEE80211_CONN_MODE_VHT,
IEEE80211_CONN_MODE_HE,
IEEE80211_CONN_MODE_EHT,
+ IEEE80211_CONN_MODE_UHR,
};
#define IEEE80211_CONN_MODE_HIGHEST IEEE80211_CONN_MODE_EHT
@@ -2691,6 +2692,9 @@ int ieee80211_put_eht_cap(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata,
const struct ieee80211_supported_band *sband,
const struct ieee80211_conn_settings *conn);
+int ieee80211_put_uhr_cap(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata,
+ const struct ieee80211_supported_band *sband);
int ieee80211_put_reg_conn(struct sk_buff *skb,
enum ieee80211_channel_flags flags);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b05e313c7f17..ffe957eb0c8e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1123,7 +1123,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int result, i;
enum nl80211_band band;
int channels, max_bitrates;
- bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g;
+ bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g, supp_uhr;
struct cfg80211_chan_def dflt_chandef = {};
if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
@@ -1237,6 +1237,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
supp_he = false;
supp_eht = false;
supp_s1g = false;
+ supp_uhr = false;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_supported_band *sband;
@@ -1293,6 +1294,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
supp_he = supp_he || iftd->he_cap.has_he;
supp_eht = supp_eht || iftd->eht_cap.has_eht;
+ supp_uhr = supp_uhr || iftd->uhr_cap.has_uhr;
if (band == NL80211_BAND_2GHZ)
he_40_mhz_cap =
@@ -1325,6 +1327,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (WARN_ON(supp_eht && !supp_he))
return -EINVAL;
+ /* UHR requires EHT support */
+ if (WARN_ON(supp_uhr && !supp_eht))
+ return -EINVAL;
+
if (!sband->ht_cap.ht_supported)
continue;
@@ -1435,6 +1441,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
3 + sizeof(struct ieee80211_eht_cap_elem) +
sizeof(struct ieee80211_eht_mcs_nss_supp) +
IEEE80211_EHT_PPE_THRES_MAX_LEN;
+
+ if (supp_uhr)
+ local->scan_ies_len +=
+ 3 + sizeof(struct ieee80211_uhr_cap_elem);
}
if (!local->ops->hw_scan) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 73649d57d0c3..9b730aa5fc3a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -162,6 +162,7 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_vht_operation *vht_oper = elems->vht_operation;
const struct ieee80211_he_operation *he_oper = elems->he_operation;
const struct ieee80211_eht_operation *eht_oper = elems->eht_operation;
+ const struct ieee80211_uhr_operation *uhr_oper = elems->uhr_operation;
struct ieee80211_supported_band *sband =
sdata->local->hw.wiphy->bands[channel->band];
struct cfg80211_chan_def vht_chandef;
@@ -340,7 +341,12 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
*chandef = eht_chandef;
}
- return IEEE80211_CONN_MODE_EHT;
+ /* stick to EHT if STA or the AP don't have UHR */
+ if (conn->mode < IEEE80211_CONN_MODE_UHR ||
+ !uhr_oper)
+ return IEEE80211_CONN_MODE_EHT;
+
+ return IEEE80211_CONN_MODE_UHR;
}
static bool
@@ -1091,6 +1097,7 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
IEEE80211_CONN_BW_LIMIT_160);
break;
case IEEE80211_CONN_MODE_EHT:
+ case IEEE80211_CONN_MODE_UHR:
conn->bw_limit = min_t(enum ieee80211_conn_bw_limit,
conn->bw_limit,
IEEE80211_CONN_BW_LIMIT_320);
@@ -1152,6 +1159,15 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
IEEE80211_CONN_BW_LIMIT_160);
}
+ if (conn->mode >= IEEE80211_CONN_MODE_UHR &&
+ !cfg80211_chandef_usable(sdata->wdev.wiphy, &chanreq->oper,
+ IEEE80211_CHAN_NO_UHR)) {
+ conn->mode = IEEE80211_CONN_MODE_EHT;
+ conn->bw_limit = min_t(enum ieee80211_conn_bw_limit,
+ conn->bw_limit,
+ IEEE80211_CONN_BW_LIMIT_160);
+ }
+
if (chanreq->oper.width != ap_chandef->width || ap_mode != conn->mode)
link_id_info(sdata, link_id,
"regulatory prevented using AP config, downgraded\n");
@@ -1887,6 +1903,9 @@ ieee80211_add_link_elems(struct ieee80211_sub_if_data *sdata,
if (assoc_data->link[link_id].conn.mode >= IEEE80211_CONN_MODE_EHT)
ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_EHT_CAPABILITY);
+ if (assoc_data->link[link_id].conn.mode >= IEEE80211_CONN_MODE_UHR)
+ ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_UHR_CAPABILITY);
+
if (link_id == assoc_data->assoc_link_id)
ieee80211_assoc_add_ml_elem(sdata, skb, orig_capab, ext_capa,
present_elems, assoc_data);
@@ -1898,6 +1917,9 @@ ieee80211_add_link_elems(struct ieee80211_sub_if_data *sdata,
ieee80211_put_eht_cap(skb, sdata, sband,
&assoc_data->link[link_id].conn);
+ if (assoc_data->link[link_id].conn.mode >= IEEE80211_CONN_MODE_UHR)
+ ieee80211_put_uhr_cap(skb, sdata, sband);
+
if (sband->band == NL80211_BAND_S1GHZ) {
ieee80211_add_aid_request_ie(sdata, skb);
ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb);
@@ -2132,6 +2154,8 @@ ieee80211_link_common_elems_size(struct ieee80211_sub_if_data *sdata,
sizeof(struct ieee80211_eht_mcs_nss_supp) +
IEEE80211_EHT_PPE_THRES_MAX_LEN;
+ size += 2 + 1 + sizeof(struct ieee80211_uhr_cap_elem);
+
return size;
}
@@ -5808,6 +5832,7 @@ ieee80211_determine_our_sta_mode(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_sta_he_cap *he_cap;
const struct ieee80211_sta_eht_cap *eht_cap;
struct ieee80211_sta_vht_cap vht_cap;
+ const struct ieee80211_sta_uhr_cap *uhr_cap;
if (sband->band == NL80211_BAND_S1GHZ) {
conn->mode = IEEE80211_CONN_MODE_S1G;
@@ -5995,6 +6020,16 @@ ieee80211_determine_our_sta_mode(struct ieee80211_sub_if_data *sdata,
mlme_link_id_dbg(sdata, link_id,
"no EHT 320 MHz cap in 6 GHz, limiting to 160 MHz\n");
+ uhr_cap = ieee80211_get_uhr_iftype_cap_vif(sband, &sdata->vif);
+ if (!uhr_cap) {
+ mlme_link_id_dbg(sdata, link_id,
+ "no UHR support, limiting to EHT\n");
+ goto out;
+ }
+
+ /* we have UHR */
+ conn->mode = IEEE80211_CONN_MODE_UHR;
+
out:
mlme_link_id_dbg(sdata, link_id,
"determined local STA to be %s, BW limited to %d MHz\n",
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index ed8411aa8b32..43fe1483c32b 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -190,12 +190,16 @@ ieee80211_parse_extension_element(u32 *crc,
}
break;
case WLAN_EID_EXT_UHR_CAPABILITY:
+ if (params->mode < IEEE80211_CONN_MODE_UHR)
+ break;
if (ieee80211_uhr_capa_size_ok(data, len)) {
elems->uhr_cap = data;
elems->uhr_cap_len = len;
}
break;
case WLAN_EID_EXT_UHR_OPERATION:
+ if (params->mode < IEEE80211_CONN_MODE_UHR)
+ break;
if (ieee80211_uhr_oper_size_ok(data, len, params->is_beacon))
elems->uhr_operation = data;
calc_crc = true;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0c46009a3d63..dc8706305ebe 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -47,7 +47,7 @@ struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
const struct ieee80211_conn_settings ieee80211_conn_settings_unlimited = {
- .mode = IEEE80211_CONN_MODE_EHT,
+ .mode = IEEE80211_CONN_MODE_UHR,
.bw_limit = IEEE80211_CONN_BW_LIMIT_320,
};
@@ -1365,6 +1365,15 @@ static int ieee80211_put_preq_ies_band(struct sk_buff *skb,
return err;
}
+ if (cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band),
+ IEEE80211_CHAN_NO_HE |
+ IEEE80211_CHAN_NO_EHT |
+ IEEE80211_CHAN_NO_UHR)) {
+ err = ieee80211_put_uhr_cap(skb, sdata, sband);
+ if (err)
+ return err;
+ }
+
err = ieee80211_put_he_6ghz_cap(skb, sdata, IEEE80211_SMPS_OFF);
if (err)
return err;
@@ -4475,6 +4484,33 @@ int ieee80211_put_eht_cap(struct sk_buff *skb,
return 0;
}
+int ieee80211_put_uhr_cap(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata,
+ const struct ieee80211_supported_band *sband)
+{
+ const struct ieee80211_sta_uhr_cap *uhr_cap =
+ ieee80211_get_uhr_iftype_cap_vif(sband, &sdata->vif);
+ struct ieee80211_uhr_cap_elem_fixed fixed;
+ u8 ie_len;
+
+ /* Make sure we have place for the IE */
+ if (!uhr_cap)
+ return 0;
+
+ fixed = uhr_cap->uhr_cap_elem;
+
+ ie_len = 2 + 1 + sizeof(uhr_cap->uhr_cap_elem);
+ if (skb_tailroom(skb) < ie_len)
+ return -ENOBUFS;
+
+ skb_put_u8(skb, WLAN_EID_EXTENSION);
+ skb_put_u8(skb, ie_len - 2);
+ skb_put_u8(skb, WLAN_EID_EXT_UHR_CAPABILITY);
+ skb_put_data(skb, &fixed, sizeof(fixed));
+
+ return 0;
+}
+
const char *ieee80211_conn_mode_str(enum ieee80211_conn_mode mode)
{
static const char * const modes[] = {
@@ -4484,6 +4520,7 @@ const char *ieee80211_conn_mode_str(enum ieee80211_conn_mode mode)
[IEEE80211_CONN_MODE_VHT] = "VHT",
[IEEE80211_CONN_MODE_HE] = "HE",
[IEEE80211_CONN_MODE_EHT] = "EHT",
+ [IEEE80211_CONN_MODE_UHR] = "UHR",
};
if (WARN_ON(mode >= ARRAY_SIZE(modes)))
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 10/13] wifi: mac80211: Handle station association response with UHR
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (8 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 09/13] wifi: mac80211: Add UHR capabilities to association/probe request for STA mode Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 11/13] wifi: mac80211: set UHR support flag in AP mode Karthikeyan Kathirvel
` (3 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
When the association is an UHR association, parse the UHR
element from the association response and update the
station's UHR capabilities accordingly.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/mac80211.h | 4 ++++
net/mac80211/Makefile | 3 ++-
net/mac80211/cfg.c | 6 +++++
net/mac80211/ieee80211_i.h | 6 +++++
net/mac80211/uhr.c | 48 ++++++++++++++++++++++++++++++++++++++
5 files changed, 66 insertions(+), 1 deletion(-)
create mode 100644 net/mac80211/uhr.c
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7f1d2953a074..73bd3331ad5d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -760,6 +760,7 @@ struct ieee80211_parsed_tpe {
* (as opposed to hearing its value from another link's beacon).
* @s1g_long_beacon_period: number of beacon intervals between each long
* beacon transmission.
+ * @uhr_support: does this BSS support UHR
*/
struct ieee80211_bss_conf {
struct ieee80211_vif *vif;
@@ -861,6 +862,7 @@ struct ieee80211_bss_conf {
u8 bss_param_ch_cnt_link_id;
u8 s1g_long_beacon_period;
+ bool uhr_support;
};
/**
@@ -2442,6 +2444,7 @@ struct ieee80211_sta_aggregates {
* notifications and capabilities. The value is only valid after
* the station moves to associated state.
* @txpwr: the station tx power configuration
+ * @uhr_cap: UHR capabilities of this STA
*
*/
struct ieee80211_link_sta {
@@ -2464,6 +2467,7 @@ struct ieee80211_link_sta {
u8 rx_nss;
enum ieee80211_sta_rx_bandwidth bandwidth;
struct ieee80211_sta_txpwr txpwr;
+ struct ieee80211_sta_uhr_cap uhr_cap;
};
/**
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index a33884967f21..33a290787241 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -36,7 +36,8 @@ mac80211-y := \
tdls.o \
ocb.o \
airtime.o \
- eht.o
+ eht.o \
+ uhr.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b51c2c8584ae..94ded4a44c4d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2170,6 +2170,12 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
ieee80211_s1g_cap_to_sta_s1g_cap(sdata, params->s1g_capa,
link_sta);
+ if (params->uhr_capa)
+ ieee80211_uhr_ie_to_sta_uhr(sdata, sband,
+ params->uhr_capa,
+ params->uhr_capa_len,
+ link_sta);
+
ieee80211_sta_init_nss(link_sta);
if (params->opmode_notif_used) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3a61710b1532..4ffdb8f75468 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2846,6 +2846,12 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
u8 eht_cap_len,
struct link_sta_info *link_sta);
+void
+ieee80211_uhr_ie_to_sta_uhr(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
+ const struct ieee80211_uhr_cap_elem *uhr_cap_elem,
+ u8 uhr_cap_len,
+ struct link_sta_info *link_sta);
void ieee80211_process_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/uhr.c b/net/mac80211/uhr.c
new file mode 100644
index 000000000000..da68088a4fe6
--- /dev/null
+++ b/net/mac80211/uhr.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UHR handling
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include "ieee80211_i.h"
+
+void
+ieee80211_uhr_ie_to_sta_uhr(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
+ const struct ieee80211_uhr_cap_elem *uhr_cap_elem,
+ u8 uhr_cap_len,
+ struct link_sta_info *link_sta)
+{
+ struct ieee80211_sta_uhr_cap *uhr_cap = &link_sta->pub->uhr_cap;
+ u8 *pos = (u8 *)uhr_cap_elem;
+ u8 uhr_total_size = sizeof(uhr_cap->uhr_cap_elem) -
+ sizeof(struct ieee80211_dbe_cap);
+
+ memset(uhr_cap, 0, sizeof(*uhr_cap));
+
+ if (!uhr_cap_elem ||
+ !ieee80211_get_uhr_iftype_cap_vif(sband, &sdata->vif))
+ return;
+
+ if (uhr_cap_elem->fixed.mac_cap_info[1] &
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT) {
+ uhr_total_size += 1;
+
+ if (le64_to_cpu(uhr_cap_elem->fixed.dbe_cap.dbe_cap_param) &
+ IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_160MHZ_PRES)
+ uhr_total_size += 3;
+
+ if (le64_to_cpu(uhr_cap_elem->fixed.dbe_cap.dbe_cap_param) &
+ IEEE80211_UHR_DBE_CAP_EHT_MCS_BW_320MHZ_PRES)
+ uhr_total_size += 3;
+ }
+
+ if (uhr_cap_len < uhr_total_size)
+ return;
+
+ /* Copy the static portion of the UHR capabilities */
+ memcpy(&uhr_cap->uhr_cap_elem, pos, sizeof(uhr_cap->uhr_cap_elem));
+
+ uhr_cap->has_uhr = true;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 11/13] wifi: mac80211: set UHR support flag in AP mode
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (9 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 10/13] wifi: mac80211: Handle station association response with UHR Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 12/13] wifi: cfg80211: support disabling UHR mode Karthikeyan Kathirvel
` (2 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Set 'uhr_support' flag if UHR operation is present.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
net/mac80211/cfg.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 94ded4a44c4d..e16b0e9b40f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1610,6 +1610,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->eht_mu_beamformer = false;
}
+ if (params->uhr_oper) {
+ if (!link_conf->eht_support)
+ return -EOPNOTSUPP;
+
+ link_conf->uhr_support = true;
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata,
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 12/13] wifi: cfg80211: support disabling UHR mode
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (10 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 11/13] wifi: mac80211: set UHR support flag in AP mode Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 6:26 ` [PATCH RFC wireless-next 13/13] wifi: mac80211_hwsim: Add UHR capabilities in driver Karthikeyan Kathirvel
2025-12-16 9:04 ` [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Johannes Berg
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Allow userspace to disable UHR mode during association
via NL80211_ATTR_DISABLE_UHR.
This attribute provides a mechanism for userspace applications to
explicitly opt out of UHR operation during association. It is
necessary because certain regulatory or deployment scenarios may
require disabling UHR features on specific channels or devices.
By exposing this control to userspace, we ensure flexibility and
compliance without relying on static kernel configurations.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 4 ++++
net/mac80211/mlme.c | 9 ++++++++-
net/wireless/nl80211.c | 7 +++++++
4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 85321948b7ec..a72247b05cf5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3307,6 +3307,7 @@ struct cfg80211_ml_reconf_req {
* Drivers shall disable MLO features for the current association if this
* flag is not set.
* @ASSOC_REQ_SPP_AMSDU: SPP A-MSDUs will be used on this connection (if any)
+ * @ASSOC_REQ_DISABLE_UHR: Disable UHR
*/
enum cfg80211_assoc_req_flags {
ASSOC_REQ_DISABLE_HT = BIT(0),
@@ -3317,6 +3318,7 @@ enum cfg80211_assoc_req_flags {
ASSOC_REQ_DISABLE_EHT = BIT(5),
CONNECT_REQ_MLO_SUPPORT = BIT(6),
ASSOC_REQ_SPP_AMSDU = BIT(7),
+ ASSOC_REQ_DISABLE_UHR = BIT(8),
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9e957378f43b..1bda6a379bbc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2976,6 +2976,9 @@ enum nl80211_commands {
* @NL80211_ATTR_UHR_CAPABILITY: UHR Capability information element (from
* association request when used with NL80211_CMD_NEW_STATION). Can be set
* only if %NL80211_STA_FLAG_WME is set.
+ * @NL80211_ATTR_DISABLE_UHR: Force UHR capable interfaces to disable
+ * this feature during association. This is a flag attribute.
+ * Currently only supported in mac80211 drivers.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -3546,6 +3549,7 @@ enum nl80211_attrs {
NL80211_ATTR_S1G_PRIMARY_2MHZ,
NL80211_ATTR_UHR_CAPABILITY,
+ NL80211_ATTR_DISABLE_UHR,
/* add attributes here, update the policy in nl80211.c */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9b730aa5fc3a..9d5906682a1f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -6020,6 +6020,12 @@ ieee80211_determine_our_sta_mode(struct ieee80211_sub_if_data *sdata,
mlme_link_id_dbg(sdata, link_id,
"no EHT 320 MHz cap in 6 GHz, limiting to 160 MHz\n");
+ if (req && req->flags & ASSOC_REQ_DISABLE_UHR) {
+ mlme_link_id_dbg(sdata, link_id,
+ "UHR disabled by flag, limiting to EHT\n");
+ goto out;
+ }
+
uhr_cap = ieee80211_get_uhr_iftype_cap_vif(sband, &sdata->vif);
if (!uhr_cap) {
mlme_link_id_dbg(sdata, link_id,
@@ -9727,7 +9733,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & (ASSOC_REQ_DISABLE_HT |
ASSOC_REQ_DISABLE_VHT |
ASSOC_REQ_DISABLE_HE |
- ASSOC_REQ_DISABLE_EHT)) {
+ ASSOC_REQ_DISABLE_EHT |
+ ASSOC_REQ_DISABLE_UHR)) {
err = -EINVAL;
goto err_free;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cb0592c292b4..1e18606c5e44 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -935,6 +935,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_UHR_CAPABILITY] =
NLA_POLICY_RANGE(NLA_BINARY, NL80211_UHR_MIN_CAPABILITY_LEN,
NL80211_UHR_MAX_CAPABILITY_LEN),
+ [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -12399,6 +12400,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
req.flags |= ASSOC_REQ_DISABLE_EHT;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_UHR]))
+ req.flags |= ASSOC_REQ_DISABLE_UHR;
+
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&req.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
@@ -13278,6 +13282,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
connect.flags |= ASSOC_REQ_DISABLE_EHT;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_UHR]))
+ connect.flags |= ASSOC_REQ_DISABLE_UHR;
+
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&connect.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH RFC wireless-next 13/13] wifi: mac80211_hwsim: Add UHR capabilities in driver.
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (11 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 12/13] wifi: cfg80211: support disabling UHR mode Karthikeyan Kathirvel
@ 2025-12-16 6:26 ` Karthikeyan Kathirvel
2025-12-16 9:04 ` [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Johannes Berg
13 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-16 6:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Karthikeyan Kathirvel
Add UHR capabilities for bringing up interface in UHR mode.
It is required for validating UHR test cases.
Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 288 ++++++++++++++++++
1 file changed, 288 insertions(+)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 551f5eb4e747..b3de13aa7354 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -4478,6 +4478,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
{
.types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -4586,6 +4634,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
#ifdef CONFIG_MAC80211_MESH
{
@@ -4755,6 +4851,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
{
.types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -4880,6 +5024,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
#ifdef CONFIG_MAC80211_MESH
{
@@ -5073,6 +5265,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
{
.types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -5219,6 +5459,54 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
},
/* PPE threshold information is not supported */
},
+ .uhr_cap = {
+ .has_uhr = true,
+ .uhr_cap_elem = {
+ .mac_cap_info[0] =
+ IEEE80211_UHR_MAC_CAP0_DPS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_DPS_ASSISTING_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ML_POWER_MANAGEMENT |
+ IEEE80211_UHR_MAC_CAP0_NPCA_SUPPORTED |
+ IEEE80211_UHR_MAC_CAP0_ENHANCED_BSR_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_ADDITIONAL_MAPPED_TID_SUPPORT |
+ IEEE80211_UHR_MAC_CAP0_EOTSP_SUPPORT,
+ .mac_cap_info[1] =
+ IEEE80211_UHR_MAC_CAP1_DSO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P_EDCA_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DBE_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPPORT |
+ IEEE80211_UHR_MAC_CAP1_DUO_SUPPORT,
+ .mac_cap_info[2] =
+ IEEE80211_UHR_MAC_CAP2_OM_UL_MU_DATA_DIS_RX_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_AOM_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_IFCS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXSPG_SUPPORT |
+ IEEE80211_UHR_MAC_CAP2_TXOP_RETURN_SUPPORT_INTXSPG |
+ IEEE80211_UHR_MAC_CAP2_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK,
+ .mac_cap_info[3] =
+ IEEE80211_UHR_MAC_CAP3_UHR_OPER_MODE_PARAM_UPDATE_TIMEOUT_MASK |
+ IEEE80211_UHR_MAC_CAP3_PARAM_UPDATE_ADV_NOTIFY_INT_MASK |
+ IEEE80211_UHR_MAC_CAP3_UPDATE_IND_IN_TIM_INT_MASK,
+ .mac_cap_info[4] =
+ IEEE80211_UHR_MAC_CAP4_UPDATE_IND_IN_TIM_INT_MASK |
+ IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
+ IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE,
+
+ .phy_cap_info[0] =
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_80MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_160MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_RX_NDP_SOUNDING_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_MAX_NSS_TOTAL_RX_DL_MUMIMO_320MHZ |
+ IEEE80211_UHR_PHY_CAP0_ELR_RX_SUPPORT |
+ IEEE80211_UHR_PHY_CAP0_ELR_TX_SUPPORT,
+ },
+ },
},
#ifdef CONFIG_MAC80211_MESH
{
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support
2025-12-16 6:26 [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Karthikeyan Kathirvel
` (12 preceding siblings ...)
2025-12-16 6:26 ` [PATCH RFC wireless-next 13/13] wifi: mac80211_hwsim: Add UHR capabilities in driver Karthikeyan Kathirvel
@ 2025-12-16 9:04 ` Johannes Berg
2025-12-16 9:12 ` Johannes Berg
13 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2025-12-16 9:04 UTC (permalink / raw)
To: Karthikeyan Kathirvel; +Cc: linux-wireless
On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
> This series covers support for UHR capability and operation (11bn)
> advertisement in AP and STA mode. The objective here is to give an
> idea of basic changes needed for UHR in cfg80211/nl80211/mac80211.
Huh. I never posted my version, sorry about that! I'll see if I can do
that soon so we can compare notes, but I'll also go over yours quickly.
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support
2025-12-16 9:04 ` [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support Johannes Berg
@ 2025-12-16 9:12 ` Johannes Berg
2025-12-17 10:05 ` Karthikeyan Kathirvel
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2025-12-16 9:12 UTC (permalink / raw)
To: Karthikeyan Kathirvel; +Cc: linux-wireless
On Tue, 2025-12-16 at 10:04 +0100, Johannes Berg wrote:
> On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
> > This series covers support for UHR capability and operation (11bn)
> > advertisement in AP and STA mode. The objective here is to give an
> > idea of basic changes needed for UHR in cfg80211/nl80211/mac80211.
>
> Huh. I never posted my version, sorry about that! I'll see if I can do
> that soon so we can compare notes, but I'll also go over yours quickly.
For what you have, mine was pretty similar, not all the naming
(obviously), and you also have a few more definitions for DBE etc. that
I didn't add since some were still broken.
I also had the rate calculation and more ELR stuff, IIRC.
Anyway, I'll post it soon and we can see that we arrive at a good
combination.
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support
2025-12-16 9:12 ` Johannes Berg
@ 2025-12-17 10:05 ` Karthikeyan Kathirvel
2025-12-22 11:59 ` Karthikeyan Kathirvel
0 siblings, 1 reply; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-17 10:05 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 12/16/2025 2:42 PM, Johannes Berg wrote:
> On Tue, 2025-12-16 at 10:04 +0100, Johannes Berg wrote:
>> On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
>>> This series covers support for UHR capability and operation (11bn)
>>> advertisement in AP and STA mode. The objective here is to give an
>>> idea of basic changes needed for UHR in cfg80211/nl80211/mac80211.
>>
>> Huh. I never posted my version, sorry about that! I'll see if I can do
>> that soon so we can compare notes, but I'll also go over yours quickly.
>
> For what you have, mine was pretty similar, not all the naming
> (obviously), and you also have a few more definitions for DBE etc. that
> I didn't add since some were still broken.
>
> I also had the rate calculation and more ELR stuff, IIRC.
>
> Anyway, I'll post it soon and we can see that we arrive at a good
> combination.
>
> johannes
I received your version, I will review the gaps between both of our
patches and get back.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH RFC wireless-next 00/13] wifi: ieee80211/cfg80211: Add UHR (802.11bn) Capability and Operation support
2025-12-17 10:05 ` Karthikeyan Kathirvel
@ 2025-12-22 11:59 ` Karthikeyan Kathirvel
0 siblings, 0 replies; 23+ messages in thread
From: Karthikeyan Kathirvel @ 2025-12-22 11:59 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 12/17/2025 3:35 PM, Karthikeyan Kathirvel wrote:
>
>
> On 12/16/2025 2:42 PM, Johannes Berg wrote:
>> On Tue, 2025-12-16 at 10:04 +0100, Johannes Berg wrote:
>>> On Tue, 2025-12-16 at 11:56 +0530, Karthikeyan Kathirvel wrote:
>>>> This series covers support for UHR capability and operation (11bn)
>>>> advertisement in AP and STA mode. The objective here is to give an
>>>> idea of basic changes needed for UHR in cfg80211/nl80211/mac80211.
>>>
>>> Huh. I never posted my version, sorry about that! I'll see if I can do
>>> that soon so we can compare notes, but I'll also go over yours quickly.
>>
>> For what you have, mine was pretty similar, not all the naming
>> (obviously), and you also have a few more definitions for DBE etc. that
>> I didn't add since some were still broken.
>>
>> I also had the rate calculation and more ELR stuff, IIRC.
>>
>> Anyway, I'll post it soon and we can see that we arrive at a good
>> combination.
>>
>> johannes
>
> I received your version, I will review the gaps between both of our
> patches and get back.
Hi Johannes
I have reviewed your patches and listed down the changes which are
missing between our patches
-Johannes-
Defined EBPCC and SMD Info
Handled UHR MCS, ELR and IM
Handled NPCA in ieee80211_determine_ap_chan()
Handled STA_STATS_RATE_TYPE_UHR
-KK-
Handled DPS, DBE and P-EDCA in ieee80211_uhr_oper_size_ok()
Handled DBE calculation in ieee80211_uhr_capa_size_ok()
Handled parsing of ieee80211 elems differently for beacons
mac80211 hwsim
I can add your missing changes on my list of patch series and send a
next version, please comment your opinion ?
Thanks
KK
^ permalink raw reply [flat|nested] 23+ messages in thread