Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH iwlwifi-next 09/15] wifi: iwlwifi: add CQM event support for per-link RSSI changes
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless
  Cc: Avinash Bhatt, Emmanuel Grumbach, Johannes Berg,
	Pagadala Yesu Anjaneyulu
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Avinash Bhatt <avinash.bhatt@intel.com>

Implement CQM RSSI threshold handling by tracking the last reported RSSI
and issuing CQM low/high events when the RSSI crosses the configured
threshold with the required hysteresis. This provides proper CQM support
and enables userspace to receive per-link RSSI notifications.

Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Reviewed-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/link.h |  2 ++
 .../net/wireless/intel/iwlwifi/mld/stats.c    | 26 ++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h
index 9e4da8e4de93..ca691259fc5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h
@@ -40,6 +40,7 @@ struct iwl_probe_resp_data {
  * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
  * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
  * @mon_sta: station used for TX injection in monitor interface.
+ * @last_cqm_rssi_event: rssi of the last cqm rssi event
  * @average_beacon_energy: average beacon energy for beacons received during
  *	client connections
  * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
@@ -66,6 +67,7 @@ struct iwl_mld_link {
 	struct iwl_mld_int_sta bcast_sta;
 	struct iwl_mld_int_sta mcast_sta;
 	struct iwl_mld_int_sta mon_sta;
+	int last_cqm_rssi_event;
 
 	/* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
 	struct ieee80211_key_conf *ap_early_keys[6];
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
index 7b8709716324..9b3149b9d2c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
@@ -369,15 +369,39 @@ static void iwl_mld_stats_recalc_traffic_load(struct iwl_mld *mld,
 static void iwl_mld_update_link_sig(struct ieee80211_vif *vif, int sig,
 				    struct ieee80211_bss_conf *bss_conf)
 {
+	struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
 	struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld;
 	int exit_emlsr_thresh;
+	int last_event;
 
 	if (sig == 0) {
 		IWL_DEBUG_RX(mld, "RSSI is 0 - skip signal based decision\n");
 		return;
 	}
 
-	/* TODO: task=statistics handle CQM notifications */
+	if (WARN_ON(!link))
+		return;
+
+	/* CQM Notification */
+	if (vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI) {
+		int thold = bss_conf->cqm_rssi_thold;
+		int hyst = bss_conf->cqm_rssi_hyst;
+
+		last_event = link->last_cqm_rssi_event;
+		if (thold && sig < thold &&
+		    (last_event == 0 || sig < last_event - hyst)) {
+			link->last_cqm_rssi_event = sig;
+			ieee80211_cqm_rssi_notify(vif,
+						  NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+						  sig, GFP_KERNEL);
+		} else if (sig > thold &&
+			   (last_event == 0 || sig > last_event + hyst)) {
+			link->last_cqm_rssi_event = sig;
+			ieee80211_cqm_rssi_notify(vif,
+						  NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+						  sig, GFP_KERNEL);
+		}
+	}
 
 	if (!iwl_mld_emlsr_active(vif)) {
 		/* We're not in EMLSR and our signal is bad,
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 08/15] wifi: iwlwifi: mld: eliminate duplicate WIDE_ID in PPAG command handling
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Pagadala Yesu Anjaneyulu, Emmanuel Grumbach, Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>

Extract the PER_PLATFORM_ANT_GAIN_CMD command ID into a local variable
to avoid duplicating WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD).

Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/regulatory.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
index 2486d78d6fc3..f91f61ca9b2e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
@@ -211,10 +211,8 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
 		.v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
 		.v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
 	};
-	int cmd_ver =
-		iwl_fw_lookup_cmd_ver(mld->fw,
-				      WIDE_ID(PHY_OPS_GROUP,
-					      PER_PLATFORM_ANT_GAIN_CMD), 1);
+	u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD);
+	int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 1);
 	int cmd_len = sizeof(cmd.v8);
 	int ret;
 
@@ -271,9 +269,7 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
 	}
 
 	IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
-	ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
-						PER_PLATFORM_ANT_GAIN_CMD),
-				   &cmd, cmd_len);
+	ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_len);
 	if (ret < 0)
 		IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
 			ret);
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 07/15] wifi: iwlwifi: fw: Add TLV support for BIOS revision of command
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Pagadala Yesu Anjaneyulu, Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>

Add support for newer firmware API versions that support
multiple BIOS revisions. Use the new TLV provided by
firmware to determine which BIOS revision it supports.

Future patches will use this information to either
drop commands when the BIOS revision is higher than
supported or convert commands based on the command
specific implementation.

Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/fw/file.h | 15 +++++++++
 drivers/net/wireless/intel/iwlwifi/fw/img.c  | 32 +++++++++++++++++++-
 drivers/net/wireless/intel/iwlwifi/fw/img.h  |  8 +++++
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 21 +++++++++++++
 4 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 378788de1d74..f7a6f21267e9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -103,6 +103,7 @@ enum iwl_ucode_tlv_type {
 	IWL_UCODE_TLV_D3_KEK_KCK_ADDR		= 67,
 	IWL_UCODE_TLV_CURRENT_PC		= 68,
 	IWL_UCODE_TLV_FSEQ_BIN_VERSION		= 72,
+	IWL_UCODE_TLV_CMD_BIOS_TABLE		= 73,
 
 	/* contains sub-sections like PNVM file does (did) */
 	IWL_UCODE_TLV_PNVM_DATA			= 74,
@@ -1040,6 +1041,20 @@ struct iwl_fw_cmd_version {
 	u8 notif_ver;
 } __packed;
 
+/**
+ * struct iwl_fw_cmd_bios_table - firmware command BIOS revision entry
+ * @cmd: command ID
+ * @group: group ID
+ * @max_acpi_revision: max supported ACPI revision of command.
+ * @max_uefi_revision: max supported UEFI revision of command.
+ */
+struct iwl_fw_cmd_bios_table {
+	u8 cmd;
+	u8 group;
+	u8 max_acpi_revision;
+	u8 max_uefi_revision;
+} __packed;
+
 struct iwl_fw_tcm_error_addr {
 	__le32 addr;
 }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c
index c2f4fc83a22c..3cc1e3ae0858 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c
@@ -1,11 +1,41 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
  * Copyright(c) 2019 - 2021 Intel Corporation
- * Copyright(c) 2024 Intel Corporation
+ * Copyright(c) 2024 - 2025 Intel Corporation
  */
 #include <fw/api/commands.h>
 #include "img.h"
 
+u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
+					     enum bios_source table_source,
+					     u32 cmd_id, u8 def)
+{
+	const struct iwl_fw_cmd_bios_table *entry;
+	/* prior to LONG_GROUP, we never used this CMD version API */
+	u8 grp = iwl_cmd_groupid(cmd_id) ?: LONG_GROUP;
+	u8 cmd = iwl_cmd_opcode(cmd_id);
+
+	if (table_source != BIOS_SOURCE_ACPI &&
+	    table_source != BIOS_SOURCE_UEFI)
+		return def;
+
+	if (!fw->ucode_capa.cmd_bios_tables ||
+	    !fw->ucode_capa.n_cmd_bios_tables)
+		return def;
+
+	entry = fw->ucode_capa.cmd_bios_tables;
+	for (int i = 0; i < fw->ucode_capa.n_cmd_bios_tables; i++, entry++) {
+		if (entry->group == grp && entry->cmd == cmd) {
+			if (table_source == BIOS_SOURCE_ACPI)
+				return entry->max_acpi_revision;
+			return entry->max_uefi_revision;
+		}
+	}
+
+	return def;
+}
+EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_bios_supported_revision);
+
 u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def)
 {
 	const struct iwl_fw_cmd_version *entry;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index 045a3e009429..94113d1db8e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 
 #include "api/dbg-tlv.h"
+#include "api/nvm-reg.h"
 
 #include "file.h"
 #include "error-dump.h"
@@ -57,6 +58,9 @@ struct iwl_ucode_capabilities {
 
 	const struct iwl_fw_cmd_version *cmd_versions;
 	u32 n_cmd_versions;
+
+	const struct iwl_fw_cmd_bios_table *cmd_bios_tables;
+	u32 n_cmd_bios_tables;
 };
 
 static inline bool
@@ -274,6 +278,10 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type)
 	return &fw->img[ucode_type];
 }
 
+u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw,
+					     enum bios_source table_source,
+					     u32 cmd_id, u8 def);
+
 u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def);
 
 u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 475b3e417efa..4cdd0fe1b788 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -133,6 +133,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
 	kfree(drv->fw.dbg.mem_tlv);
 	kfree(drv->fw.iml);
 	kfree(drv->fw.ucode_capa.cmd_versions);
+	kfree(drv->fw.ucode_capa.cmd_bios_tables);
 	kfree(drv->fw.phy_integration_ver);
 	kfree(drv->trans->dbg.pc_data);
 	drv->trans->dbg.pc_data = NULL;
@@ -1426,6 +1427,26 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
 				return -ENOMEM;
 			drv->fw.pnvm_size = tlv_len;
 			break;
+		case IWL_UCODE_TLV_CMD_BIOS_TABLE:
+			if (tlv_len % sizeof(struct iwl_fw_cmd_bios_table)) {
+				IWL_ERR(drv,
+					"Invalid length for command bios table: %u\n",
+					tlv_len);
+				return -EINVAL;
+			}
+
+			if (capa->cmd_bios_tables) {
+				IWL_ERR(drv, "Duplicate TLV type 0x%02X detected\n",
+					tlv_type);
+				return -EINVAL;
+			}
+			capa->cmd_bios_tables = kmemdup(tlv_data, tlv_len,
+							GFP_KERNEL);
+			if (!capa->cmd_bios_tables)
+				return -ENOMEM;
+			capa->n_cmd_bios_tables =
+				tlv_len / sizeof(struct iwl_fw_cmd_bios_table);
+			break;
 		default:
 			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
 			break;
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 06/15] wifi: iwlwifi: bump core version for BZ/SC/DR
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

Start supporting Core 102 FW on these devices.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
 drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
 drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index 77db8c75e6e2..3653ddbf3ce9 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware core release supported */
-#define IWL_BZ_UCODE_CORE_MAX	101
+#define IWL_BZ_UCODE_CORE_MAX	102
 
 /* Lowest firmware API version supported */
 #define IWL_BZ_UCODE_API_MIN	100
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
index a279dcfd3083..83d893b10f8e 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
@@ -9,7 +9,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware core release supported */
-#define IWL_DR_UCODE_CORE_MAX	101
+#define IWL_DR_UCODE_CORE_MAX	102
 
 /* Lowest firmware API version supported */
 #define IWL_DR_UCODE_API_MIN	100
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index ee00b2af7a1d..749d46dc0236 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware core release supported */
-#define IWL_SC_UCODE_CORE_MAX	101
+#define IWL_SC_UCODE_CORE_MAX	102
 
 /* Lowest firmware API version supported */
 #define IWL_SC_UCODE_API_MIN	100
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 05/15] wifi: iwlwifi: add support for additional channels in NVM_GET_INFO
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Emmanuel Grumbach, Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>

We need to expect more channels on devices that support UNII-9.
Since iwl_ext_nvm_channels and iwl_uhb_nvm_channels are just a prefix
of iwl_unii9_nvm_channels just use iwl_unii9_nvm_channels and modify the
number of channels if the device does not support UNII-9 channels.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 .../net/wireless/intel/iwlwifi/cfg/rf-pe.c    |  1 +
 .../wireless/intel/iwlwifi/fw/api/nvm-reg.h   | 37 +++++++++--
 .../net/wireless/intel/iwlwifi/iwl-config.h   |  2 +
 .../wireless/intel/iwlwifi/iwl-nvm-parse.c    | 64 ++++++++++++-------
 4 files changed, 76 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
index c02478b73057..06c615f4d3e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
@@ -17,6 +17,7 @@
 	.non_shared_ant = ANT_B,					\
 	.vht_mu_mimo_supported = true,					\
 	.uhb_supported = true,						\
+	.unii9_supported = true,					\
 	.eht_supported = true,						\
 	.uhr_supported = true,						\
 	.num_rbds = IWL_NUM_RBDS_EHT,					\
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 25c860a05b0e..0172c0747a47 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -204,7 +204,8 @@ struct iwl_nvm_get_info_phy {
 } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
 
 #define IWL_NUM_CHANNELS_V1	51
-#define IWL_NUM_CHANNELS	110
+#define IWL_NUM_CHANNELS_V2	110
+#define IWL_NUM_CHANNELS_V3	115
 
 /**
  * struct iwl_nvm_get_info_regulatory_v1 - regulatory information
@@ -219,15 +220,15 @@ struct iwl_nvm_get_info_regulatory_v1 {
 } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
 
 /**
- * struct iwl_nvm_get_info_regulatory - regulatory information
+ * struct iwl_nvm_get_info_regulatory_v2 - regulatory information
  * @lar_enabled: is LAR enabled
  * @n_channels: number of valid channels in the array
  * @channel_profile: regulatory data of this channel
  */
-struct iwl_nvm_get_info_regulatory {
+struct iwl_nvm_get_info_regulatory_v2 {
 	__le32 lar_enabled;
 	__le32 n_channels;
-	__le32 channel_profile[IWL_NUM_CHANNELS];
+	__le32 channel_profile[IWL_NUM_CHANNELS_V2];
 } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */
 
 /**
@@ -244,6 +245,32 @@ struct iwl_nvm_get_info_rsp_v3 {
 	struct iwl_nvm_get_info_regulatory_v1 regulatory;
 } __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */
 
+/**
+ * struct iwl_nvm_get_info_rsp_v4 - response to get NVM data
+ * @general: general NVM data
+ * @mac_sku: data relating to MAC sku
+ * @phy_sku: data relating to PHY sku
+ * @regulatory: regulatory data
+ */
+struct iwl_nvm_get_info_rsp_v4 {
+	struct iwl_nvm_get_info_general general;
+	struct iwl_nvm_get_info_sku mac_sku;
+	struct iwl_nvm_get_info_phy phy_sku;
+	struct iwl_nvm_get_info_regulatory_v2 regulatory;
+} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
+
+/**
+ * struct iwl_nvm_get_info_regulatory - regulatory information
+ * @lar_enabled: is LAR enabled
+ * @n_channels: number of valid channels in the array
+ * @channel_profile: regulatory data of this channel
+ */
+struct iwl_nvm_get_info_regulatory {
+	__le32 lar_enabled;
+	__le32 n_channels;
+	__le32 channel_profile[IWL_NUM_CHANNELS_V3];
+} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_3 */
+
 /**
  * struct iwl_nvm_get_info_rsp - response to get NVM data
  * @general: general NVM data
@@ -256,7 +283,7 @@ struct iwl_nvm_get_info_rsp {
 	struct iwl_nvm_get_info_sku mac_sku;
 	struct iwl_nvm_get_info_phy phy_sku;
 	struct iwl_nvm_get_info_regulatory regulatory;
-} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */
+} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_5 */
 
 /**
  * struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index da6d3686e7dd..8d7ddb6e8b53 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -415,6 +415,7 @@ struct iwl_mac_cfg {
  * @vht_mu_mimo_supported: VHT MU-MIMO support
  * @nvm_type: see &enum iwl_nvm_type
  * @uhb_supported: ultra high band channels supported
+ * @unii9_supported: UNII-9 channels supported
  * @eht_supported: EHT supported
  * @uhr_supported: UHR supported
  * @num_rbds: number of receive buffer descriptors to use
@@ -450,6 +451,7 @@ struct iwl_rf_cfg {
 	    lp_xtal_workaround:1,
 	    vht_mu_mimo_supported:1,
 	    uhb_supported:1,
+	    unii9_supported:1,
 	    eht_supported:1,
 	    uhr_supported:1;
 	u8 valid_tx_ant;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index b24ac3cec412..e8f7d258b622 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -84,16 +84,7 @@ static const u16 iwl_nvm_channels[] = {
 	149, 153, 157, 161, 165
 };
 
-static const u16 iwl_ext_nvm_channels[] = {
-	/* 2.4 GHz */
-	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-	/* 5 GHz */
-	36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
-	96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
-	149, 153, 157, 161, 165, 169, 173, 177, 181
-};
-
-static const u16 iwl_uhb_nvm_channels[] = {
+static const u16 iwl_unii9_nvm_channels[] = {
 	/* 2.4 GHz */
 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
 	/* 5 GHz */
@@ -104,12 +95,16 @@ static const u16 iwl_uhb_nvm_channels[] = {
 	1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69,
 	73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129,
 	133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185,
-	189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233
+	189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233,
+
+	/* UNII-9 */
+	237, 241, 245, 249, 253
 };
 
 #define IWL_NVM_NUM_CHANNELS		ARRAY_SIZE(iwl_nvm_channels)
-#define IWL_NVM_NUM_CHANNELS_EXT	ARRAY_SIZE(iwl_ext_nvm_channels)
-#define IWL_NVM_NUM_CHANNELS_UHB	ARRAY_SIZE(iwl_uhb_nvm_channels)
+#define IWL_NVM_NUM_CHANNELS_EXT	51
+#define IWL_NVM_NUM_CHANNELS_UHB	110
+#define IWL_NVM_NUM_CHANNELS_UNII9	ARRAY_SIZE(iwl_unii9_nvm_channels)
 #define NUM_2GHZ_CHANNELS		14
 #define NUM_5GHZ_CHANNELS		37
 #define FIRST_2GHZ_HT_MINUS		5
@@ -350,12 +345,15 @@ static int iwl_init_channel_map(struct iwl_trans *trans,
 	int num_of_ch;
 	const u16 *nvm_chan;
 
-	if (cfg->uhb_supported) {
+	if (cfg->unii9_supported) {
+		num_of_ch = IWL_NVM_NUM_CHANNELS_UNII9;
+		nvm_chan = iwl_unii9_nvm_channels;
+	} else if (cfg->uhb_supported) {
 		num_of_ch = IWL_NVM_NUM_CHANNELS_UHB;
-		nvm_chan = iwl_uhb_nvm_channels;
+		nvm_chan = iwl_unii9_nvm_channels;
 	} else if (cfg->nvm_type == IWL_NVM_EXT) {
 		num_of_ch = IWL_NVM_NUM_CHANNELS_EXT;
-		nvm_chan = iwl_ext_nvm_channels;
+		nvm_chan = iwl_unii9_nvm_channels;
 	} else {
 		num_of_ch = IWL_NVM_NUM_CHANNELS;
 		nvm_chan = iwl_nvm_channels;
@@ -1401,7 +1399,9 @@ iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
 	u8 rx_chains = fw->valid_rx_ant;
 	u8 tx_chains = fw->valid_rx_ant;
 
-	if (cfg->uhb_supported)
+	if (cfg->unii9_supported)
+		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS_UNII9);
+	else if (cfg->uhb_supported)
 		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS_UHB);
 	else
 		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS_EXT);
@@ -1466,7 +1466,9 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
 	u16 lar_config;
 	const __le16 *ch_section;
 
-	if (cfg->uhb_supported)
+	if (cfg->unii9_supported)
+		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS_UNII9);
+	else if (cfg->uhb_supported)
 		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS_UHB);
 	else if (cfg->nvm_type != IWL_NVM_EXT)
 		data = kzalloc_flex(*data, channels, IWL_NVM_NUM_CHANNELS);
@@ -1687,12 +1689,15 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
 	int max_num_ch;
 	struct iwl_reg_capa reg_capa;
 
-	if (cfg->uhb_supported) {
+	if (cfg->unii9_supported) {
+		max_num_ch = IWL_NVM_NUM_CHANNELS_UNII9;
+		nvm_chan = iwl_unii9_nvm_channels;
+	} else if (cfg->uhb_supported) {
 		max_num_ch = IWL_NVM_NUM_CHANNELS_UHB;
-		nvm_chan = iwl_uhb_nvm_channels;
+		nvm_chan = iwl_unii9_nvm_channels;
 	} else if (cfg->nvm_type == IWL_NVM_EXT) {
 		max_num_ch = IWL_NVM_NUM_CHANNELS_EXT;
-		nvm_chan = iwl_ext_nvm_channels;
+		nvm_chan = iwl_unii9_nvm_channels;
 	} else {
 		max_num_ch = IWL_NVM_NUM_CHANNELS;
 		nvm_chan = iwl_nvm_channels;
@@ -2041,13 +2046,26 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
 	struct iwl_nvm_get_info_rsp_v3 *rsp_v3;
 	bool v4 = fw_has_api(&fw->ucode_capa,
 			     IWL_UCODE_TLV_API_REGULATORY_NVM_INFO);
-	size_t rsp_size = v4 ? sizeof(*rsp) : sizeof(*rsp_v3);
+	size_t rsp_size;
 	void *channel_profile;
 
 	ret = iwl_trans_send_cmd(trans, &hcmd);
 	if (ret)
 		return ERR_PTR(ret);
 
+	switch (iwl_fw_lookup_notif_ver(fw, REGULATORY_AND_NVM_GROUP,
+					NVM_GET_INFO, 0)) {
+	case 5:
+		rsp_size = sizeof(struct iwl_nvm_get_info_rsp);
+		break;
+	case 4:
+		rsp_size = sizeof(struct iwl_nvm_get_info_rsp_v4);
+		break;
+	default:
+		rsp_size = sizeof(struct iwl_nvm_get_info_rsp_v3);
+		break;
+	}
+
 	if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != rsp_size,
 		 "Invalid payload len in NVM response from FW %d",
 		 iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
@@ -2061,7 +2079,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
 	if (empty_otp)
 		IWL_INFO(trans, "OTP is empty\n");
 
-	nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS);
+	nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS_V3);
 	if (!nvm) {
 		ret = -ENOMEM;
 		goto out;
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 04/15] wifi: iwlwifi: mld: support changing iftype at runtime
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

While the interface isn't really operating, which is already
required by mac80211, we can simply remove the MAC and add
it again to change the type. Implement this simple handling.

We could almost consider moving this to mac80211 itself, as
this kind of flow should be supportable by any device, but
for now keep it here.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 .../net/wireless/intel/iwlwifi/mld/mac80211.c | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 71a9a72c9ac0..5cd3cdffb570 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -754,6 +754,30 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
 	mld->monitor.phy.valid = false;
 }
 
+static
+int iwl_mld_mac80211_change_interface(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      enum nl80211_iftype new_type, bool p2p)
+{
+	enum nl80211_iftype old_type = vif->type;
+	bool old_p2p = vif->p2p;
+	int ret;
+
+	iwl_mld_mac80211_remove_interface(hw, vif);
+
+	/* set the new type for adding it cleanly */
+	vif->type = new_type;
+	vif->p2p = p2p;
+
+	ret = iwl_mld_mac80211_add_interface(hw, vif);
+
+	/* restore for mac80211, it will change it again */
+	vif->type = old_type;
+	vif->p2p = old_p2p;
+
+	return ret;
+}
+
 struct iwl_mld_mc_iter_data {
 	struct iwl_mld *mld;
 	int port_id;
@@ -2735,6 +2759,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
 	.get_antenna = iwl_mld_get_antenna,
 	.set_antenna = iwl_mld_set_antenna,
 	.add_interface = iwl_mld_mac80211_add_interface,
+	.change_interface = iwl_mld_mac80211_change_interface,
 	.remove_interface = iwl_mld_mac80211_remove_interface,
 	.conf_tx = iwl_mld_mac80211_conf_tx,
 	.prepare_multicast = iwl_mld_mac80211_prepare_multicast,
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 03/15] wifi: iwlwifi: advertise UHR capabilities for such devices
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Advertise UHR capabilities for devices supporting UHR
(i.e. devices with some, but not all, PE RFs.)

For correct support it's also needed to plumb through
the regulatory flags the firmware might have/enforce.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 .../net/wireless/intel/iwlwifi/cfg/rf-pe.c    | 23 ++++-
 .../net/wireless/intel/iwlwifi/iwl-config.h   |  7 +-
 .../wireless/intel/iwlwifi/iwl-nvm-parse.c    | 87 +++++++++++++------
 .../wireless/intel/iwlwifi/iwl-nvm-parse.h    |  2 +
 .../wireless/intel/iwlwifi/iwl-nvm-utils.h    |  3 +-
 .../net/wireless/intel/iwlwifi/mld/iface.c    |  4 +
 drivers/net/wireless/intel/iwlwifi/pcie/drv.c |  2 +-
 7 files changed, 95 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
index 2c29054ce7b8..c02478b73057 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
@@ -4,7 +4,28 @@
  */
 #include "iwl-config.h"
 
-/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
+#define IWL_PE_NVM_VERSION		0x0a1d
+
+#define IWL_DEVICE_PE							\
+	.ht_params = {							\
+		.stbc = true,						\
+		.ldpc = true,						\
+		.ht40_bands = BIT(NL80211_BAND_2GHZ) |			\
+			      BIT(NL80211_BAND_5GHZ),			\
+	},								\
+	.led_mode = IWL_LED_RF_STATE,					\
+	.non_shared_ant = ANT_B,					\
+	.vht_mu_mimo_supported = true,					\
+	.uhb_supported = true,						\
+	.eht_supported = true,						\
+	.uhr_supported = true,						\
+	.num_rbds = IWL_NUM_RBDS_EHT,					\
+	.nvm_ver = IWL_PE_NVM_VERSION,					\
+	.nvm_type = IWL_NVM_EXT
+
+const struct iwl_rf_cfg iwl_rf_pe = {
+	IWL_DEVICE_PE,
+};
 
 const char iwl_killer_bn1850w2_name[] =
 	"Killer(R) Wi-Fi 8 BN1850w2 320MHz Wireless Network Adapter (BN201.D2W)";
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 5f40cd15e27f..da6d3686e7dd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -416,6 +416,7 @@ struct iwl_mac_cfg {
  * @nvm_type: see &enum iwl_nvm_type
  * @uhb_supported: ultra high band channels supported
  * @eht_supported: EHT supported
+ * @uhr_supported: UHR supported
  * @num_rbds: number of receive buffer descriptors to use
  *	(only used for multi-queue capable devices)
  *
@@ -449,7 +450,8 @@ struct iwl_rf_cfg {
 	    lp_xtal_workaround:1,
 	    vht_mu_mimo_supported:1,
 	    uhb_supported:1,
-	    eht_supported:1;
+	    eht_supported:1,
+	    uhr_supported:1;
 	u8 valid_tx_ant;
 	u8 valid_rx_ant;
 	u8 non_shared_ant;
@@ -744,7 +746,8 @@ extern const struct iwl_rf_cfg iwl_rf_fm_160mhz;
 #define iwl_rf_wh iwl_rf_fm
 #define iwl_rf_wh_160mhz iwl_rf_fm_160mhz
 extern const struct iwl_rf_cfg iwl_rf_wh_non_eht;
-#define iwl_rf_pe iwl_rf_fm
+extern const struct iwl_rf_cfg iwl_rf_pe;
+#define iwl_rf_pe_no_uhr iwl_rf_fm
 #endif /* CONFIG_IWLMLD */
 
 #endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 6d235c417fdd..b24ac3cec412 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -204,28 +204,30 @@ enum iwl_reg_capa_flags_v2 {
 }; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_2 */
 
 /**
- * enum iwl_reg_capa_flags_v4 - global flags applied for the whole regulatory
+ * enum iwl_reg_capa_flags_v5 - global flags applied for the whole regulatory
  * domain.
- * @REG_CAPA_V4_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ * @REG_CAPA_V5_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
  *	for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_V4_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ * @REG_CAPA_V5_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
  *	for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_V4_MCS_12_ALLOWED: 11ac with MCS 12 is allowed.
- * @REG_CAPA_V4_MCS_13_ALLOWED: 11ac with MCS 13 is allowed.
- * @REG_CAPA_V4_11BE_DISABLED: 11be is forbidden for this regulatory domain.
- * @REG_CAPA_V4_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
- * @REG_CAPA_V4_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed
+ * @REG_CAPA_V5_MCS_12_ALLOWED: 11ac with MCS 12 is allowed.
+ * @REG_CAPA_V5_MCS_13_ALLOWED: 11ac with MCS 13 is allowed.
+ * @REG_CAPA_V5_11BE_DISABLED: 11be is forbidden for this regulatory domain.
+ * @REG_CAPA_V5_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
+ * @REG_CAPA_V5_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed
  *	for this regulatory domain (valid only in 5GHz).
+ * @REG_CAPA_V5_11BN_DISABLED: UHR is not allowed for this regulatory domain
  */
-enum iwl_reg_capa_flags_v4 {
-	REG_CAPA_V4_160MHZ_ALLOWED		= BIT(3),
-	REG_CAPA_V4_80MHZ_ALLOWED		= BIT(4),
-	REG_CAPA_V4_MCS_12_ALLOWED		= BIT(5),
-	REG_CAPA_V4_MCS_13_ALLOWED		= BIT(6),
-	REG_CAPA_V4_11BE_DISABLED		= BIT(8),
-	REG_CAPA_V4_11AX_DISABLED		= BIT(13),
-	REG_CAPA_V4_320MHZ_ALLOWED		= BIT(16),
-}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4 */
+enum iwl_reg_capa_flags_v5 {
+	REG_CAPA_V5_160MHZ_ALLOWED		= BIT(3),
+	REG_CAPA_V5_80MHZ_ALLOWED		= BIT(4),
+	REG_CAPA_V5_MCS_12_ALLOWED		= BIT(5),
+	REG_CAPA_V5_MCS_13_ALLOWED		= BIT(6),
+	REG_CAPA_V5_11BE_DISABLED		= BIT(8),
+	REG_CAPA_V5_11AX_DISABLED		= BIT(13),
+	REG_CAPA_V5_320MHZ_ALLOWED		= BIT(16),
+	REG_CAPA_V5_11BN_DISABLED		= BIT(17),
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4, 5 */
 
 /*
 * API v2 for reg_capa_flags is relevant from version 6 and onwards of the
@@ -544,7 +546,7 @@ static const u8 iwl_vendor_caps[] = {
 	0x00
 };
 
-static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
+static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
 	{
 		.types_mask = BIT(NL80211_IFTYPE_STATION) |
 			      BIT(NL80211_IFTYPE_P2P_CLIENT),
@@ -688,6 +690,11 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
 			 */
 			.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
 		},
+		.uhr_cap = {
+			.has_uhr = true,
+			.phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
+				   IEEE80211_UHR_PHY_CAP_ELR_TX,
+		},
 	},
 	{
 		.types_mask = BIT(NL80211_IFTYPE_AP) |
@@ -786,6 +793,11 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
 			 */
 			.eht_ppe_thres = {0xc1, 0x0e, 0xe0 }
 		},
+		.uhr_cap = {
+			.has_uhr = true,
+			.phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
+				   IEEE80211_UHR_PHY_CAP_ELR_TX,
+		},
 	},
 };
 
@@ -853,6 +865,19 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
 	    fips_enabled)
 		iftype_data->eht_cap.has_eht = false;
 
+	if (!data->sku_cap_11bn_enable || !iftype_data->eht_cap.has_eht)
+		iftype_data->uhr_cap.has_uhr = false;
+
+	if (sband->band != NL80211_BAND_2GHZ) {
+		/* on 5 and 6 GHz ELR is uplink only */
+		if (is_ap)
+			iftype_data->uhr_cap.phy.cap &=
+				~IEEE80211_UHR_PHY_CAP_ELR_TX;
+		else
+			iftype_data->uhr_cap.phy.cap &=
+				~IEEE80211_UHR_PHY_CAP_ELR_RX;
+	}
+
 	/* Advertise an A-MPDU exponent extension based on
 	 * operating band
 	 */
@@ -1021,9 +1046,9 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
 	struct ieee80211_sband_iftype_data *iftype_data;
 	int i;
 
-	BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_he_eht_capa));
-	BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_he_eht_capa));
-	BUILD_BUG_ON(sizeof(data->iftd.uhb) != sizeof(iwl_he_eht_capa));
+	BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_iftype_cap));
+	BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_iftype_cap));
+	BUILD_BUG_ON(sizeof(data->iftd.uhb) != sizeof(iwl_iftype_cap));
 
 	switch (sband->band) {
 	case NL80211_BAND_2GHZ:
@@ -1040,10 +1065,10 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
 		return;
 	}
 
-	memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));
+	memcpy(iftype_data, iwl_iftype_cap, sizeof(iwl_iftype_cap));
 
 	_ieee80211_set_sband_iftype_data(sband, iftype_data,
-					 ARRAY_SIZE(iwl_he_eht_capa));
+					 ARRAY_SIZE(iwl_iftype_cap));
 
 	for (i = 0; i < sband->n_iftype_data; i++)
 		iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
@@ -1609,6 +1634,9 @@ u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
 	if (reg_capa.disable_11be)
 		flags |= NL80211_RRF_NO_EHT;
 
+	if (reg_capa.disable_11bn)
+		flags |= NL80211_RRF_NO_UHR;
+
 	return flags;
 }
 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_nvm_get_regdom_bw_flags);
@@ -1619,11 +1647,13 @@ static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
 
 	if (resp_ver >= REG_CAPA_V4_RESP_VER) {
 		reg_capa.allow_40mhz = true;
-		reg_capa.allow_80mhz = flags & REG_CAPA_V4_80MHZ_ALLOWED;
-		reg_capa.allow_160mhz = flags & REG_CAPA_V4_160MHZ_ALLOWED;
-		reg_capa.allow_320mhz = flags & REG_CAPA_V4_320MHZ_ALLOWED;
-		reg_capa.disable_11ax = flags & REG_CAPA_V4_11AX_DISABLED;
-		reg_capa.disable_11be = flags & REG_CAPA_V4_11BE_DISABLED;
+		reg_capa.allow_80mhz = flags & REG_CAPA_V5_80MHZ_ALLOWED;
+		reg_capa.allow_160mhz = flags & REG_CAPA_V5_160MHZ_ALLOWED;
+		reg_capa.allow_320mhz = flags & REG_CAPA_V5_320MHZ_ALLOWED;
+		reg_capa.disable_11ax = flags & REG_CAPA_V5_11AX_DISABLED;
+		reg_capa.disable_11be = flags & REG_CAPA_V5_11BE_DISABLED;
+		/* can check: was reserved and irrelevant for pre-UHR devices */
+		reg_capa.disable_11bn = flags & REG_CAPA_V5_11BN_DISABLED;
 	} else if (resp_ver >= REG_CAPA_V2_RESP_VER) {
 		reg_capa.allow_40mhz = flags & REG_CAPA_V2_40MHZ_ALLOWED;
 		reg_capa.allow_80mhz = flags & REG_CAPA_V2_80MHZ_ALLOWED;
@@ -2072,6 +2102,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
 		!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
 	if (trans->cfg->eht_supported)
 		nvm->sku_cap_11be_enable = true;
+	nvm->sku_cap_11bn_enable = trans->cfg->uhr_supported;
 
 	/* Initialize PHY sku data */
 	nvm->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
index 12f28bb0e859..e676d7c2d6cc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
@@ -35,6 +35,7 @@ enum iwl_nvm_sbands_flags {
  *	for this regulatory domain (valid only in 6 Ghz).
  * @disable_11ax: 11ax is forbidden for this regulatory domain.
  * @disable_11be: 11be is forbidden for this regulatory domain.
+ * @disable_11bn: UHR/11bn is not allowed for this regulatory domain
  */
 struct iwl_reg_capa {
 	bool allow_40mhz;
@@ -43,6 +44,7 @@ struct iwl_reg_capa {
 	bool allow_320mhz;
 	bool disable_11ax;
 	bool disable_11be;
+	bool disable_11bn;
 };
 
 /**
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h
index ac0a29a1c31f..353f5269d17a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014, 2018, 2020-2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018, 2020-2023, 2025 Intel Corporation
  * Copyright (C) 2015 Intel Mobile Communications GmbH
  */
 #ifndef __iwl_eeprom_parse_h__
@@ -32,6 +32,7 @@ struct iwl_nvm_data {
 	bool sku_cap_ipan_enable;
 	bool sku_cap_mimo_disabled;
 	bool sku_cap_11be_enable;
+	bool sku_cap_11bn_enable;
 
 	u16 radio_cfg_type;
 	u8 radio_cfg_step;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
index 9215fc7e2eca..dc96214671d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
@@ -132,6 +132,8 @@ static void iwl_mld_mac_wifi_gen_sta_iter(void *_data,
 			data->support->he_support = 1;
 		if (link_sta->eht_cap.has_eht)
 			data->support->eht_support = 1;
+		if (link_sta->uhr_cap.has_uhr)
+			data->support->uhr_support = 1;
 	}
 }
 
@@ -151,12 +153,14 @@ static void iwl_mld_set_wifi_gen(struct iwl_mld *mld,
 		/* for sniffer, set to HW capabilities */
 		support->he_support = 1;
 		support->eht_support = mld->trans->cfg->eht_supported;
+		support->uhr_support = mld->trans->cfg->uhr_supported;
 		break;
 	case NL80211_IFTYPE_AP:
 		/* for AP set according to the link configs */
 		for_each_vif_active_link(vif, link_conf, link_id) {
 			support->he_ap_support |= link_conf->he_support;
 			support->eht_support |= link_conf->eht_support;
+			support->uhr_support |= link_conf->uhr_support;
 		}
 		break;
 	default:
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index dc99e7ac4726..78482db732c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1069,7 +1069,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
 
 /* PE RF */
 	IWL_DEV_INFO(iwl_rf_pe, iwl_bn201_name, RF_TYPE(PE)),
-	IWL_DEV_INFO(iwl_rf_pe, iwl_be223_name, RF_TYPE(PE),
+	IWL_DEV_INFO(iwl_rf_pe_no_uhr, iwl_be223_name, RF_TYPE(PE),
 		     SUBDEV_MASKED(0x0524, 0xFFF)),
 	IWL_DEV_INFO(iwl_rf_pe, iwl_bn203_name, RF_TYPE(PE),
 		     SUBDEV_MASKED(0x0324, 0xFFF)),
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 01/15] wifi: iwlwifi: mld: enable UHR in TLC
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Tell the firmware if UHR is supported, including ELR (enhanced
long range) MCS support.

Note that the spec currently doesn't differentiate between 1.5
and 3 Mbps ELR MCSes, unlike the firmware.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 28 +++++++++++++++++---
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
index 62a54c37a98c..ede385909e38 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
@@ -36,7 +36,8 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
 			  struct ieee80211_vif *vif,
 			  struct ieee80211_link_sta *link_sta,
 			  const struct ieee80211_sta_he_cap *own_he_cap,
-			  const struct ieee80211_sta_eht_cap *own_eht_cap)
+			  const struct ieee80211_sta_eht_cap *own_eht_cap,
+			  const struct ieee80211_sta_uhr_cap *own_uhr_cap)
 {
 	struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
 	struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
@@ -90,6 +91,12 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
 		flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
 	}
 
+	if (link_sta->uhr_cap.has_uhr && own_uhr_cap &&
+	    link_sta->uhr_cap.phy.cap & IEEE80211_UHR_PHY_CAP_ELR_RX &&
+	    own_uhr_cap->phy.cap & IEEE80211_UHR_PHY_CAP_ELR_TX)
+		flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
+			 IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;
+
 	return cpu_to_le16(flags);
 }
 
@@ -406,6 +413,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
 			struct ieee80211_supported_band *sband,
 			const struct ieee80211_sta_he_cap *own_he_cap,
 			const struct ieee80211_sta_eht_cap *own_eht_cap,
+			const struct ieee80211_sta_uhr_cap *own_uhr_cap,
 			struct iwl_tlc_config_cmd *cmd)
 {
 	int i;
@@ -423,7 +431,16 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
 	cmd->non_ht_rates = cpu_to_le16(non_ht_rates);
 	cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
 
-	if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {
+	if (link_sta->uhr_cap.has_uhr && own_uhr_cap) {
+		cmd->mode = IWL_TLC_MNG_MODE_UHR;
+		/*
+		 * FIXME: spec currently inherits from EHT but has no
+		 * finer MCS bits. Once that's there, need to add them
+		 * to the bitmaps (and maybe copy this to UHR, or so.)
+		 */
+		iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
+				       own_eht_cap, cmd);
+	} else if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {
 		cmd->mode = IWL_TLC_MNG_MODE_EHT;
 		iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
 				       own_eht_cap, cmd);
@@ -519,13 +536,16 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
 		ieee80211_get_he_iftype_cap_vif(sband, vif);
 	const struct ieee80211_sta_eht_cap *own_eht_cap =
 		ieee80211_get_eht_iftype_cap_vif(sband, vif);
+	const struct ieee80211_sta_uhr_cap *own_uhr_cap =
+		ieee80211_get_uhr_iftype_cap_vif(sband, vif);
 	struct iwl_tlc_config_cmd cmd = {
 		/* For AP mode, use 20 MHz until the STA is authorized */
 		.max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
 			iwl_mld_fw_bw_from_sta_bw(link_sta) :
 			IWL_TLC_MNG_CH_WIDTH_20MHZ,
 		.flags = iwl_mld_get_tlc_cmd_flags(mld, vif, link_sta,
-						   own_he_cap, own_eht_cap),
+						   own_he_cap, own_eht_cap,
+						   own_uhr_cap),
 		.chains = iwl_mld_get_fw_chains(mld),
 		.sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta),
 		.max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len),
@@ -555,7 +575,7 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
 
 	iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,
 				own_he_cap, own_eht_cap,
-				&cmd);
+				own_uhr_cap, &cmd);
 
 	if (cmd_ver == 6) {
 		cmd_ptr = &cmd;
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 02/15] wifi: iwlwifi: mld: set UHR MCS in RX status
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260320080918.2567780-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Handle UHR MCSes in the RX status when receiving UHR frames.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/rx.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
index 214dcfde2fb4..ff6e71e3ff6e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
@@ -1407,6 +1407,7 @@ static void iwl_mld_set_rx_rate(struct iwl_mld *mld,
 	u32 rate_n_flags = phy_data->rate_n_flags;
 	u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
 	u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+	u32 he_type = u32_get_bits(rate_n_flags, RATE_MCS_HE_TYPE_MSK);
 	bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;
 
 	/* bandwidth may be overridden to RU by PHY ntfy */
@@ -1481,6 +1482,12 @@ static void iwl_mld_set_rx_rate(struct iwl_mld *mld,
 		rx_status->encoding = RX_ENC_EHT;
 		iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
 		break;
+	case RATE_MCS_MOD_TYPE_UHR:
+		rx_status->encoding = RX_ENC_UHR;
+		iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
+		if (he_type == RATE_MCS_HE_TYPE_UHR_ELR)
+			rx_status->uhr.elr = 1;
+		break;
 	default:
 		WARN_ON_ONCE(1);
 	}
-- 
2.34.1


^ permalink raw reply related

* [PATCH iwlwifi-next 00/15] wifi: iwlwifi: updates - 2026-03-20
From: Miri Korenblit @ 2026-03-20  8:09 UTC (permalink / raw)
  To: linux-wireless

Hi,

features and cleanups from our internal tree.

Thanks,
Miri
---

Avinash Bhatt (1):
  wifi: iwlwifi: add CQM event support for per-link RSSI changes

Emmanuel Grumbach (1):
  wifi: iwlwifi: add support for additional channels in NVM_GET_INFO

Johannes Berg (8):
  wifi: iwlwifi: mld: enable UHR in TLC
  wifi: iwlwifi: mld: set UHR MCS in RX status
  wifi: iwlwifi: advertise UHR capabilities for such devices
  wifi: iwlwifi: mld: support changing iftype at runtime
  wifi: iwlwifi: use IWL_FW_CHECK for sync timeout
  wifi: iwlwifi: pcie: don't dump on reset handshake in dump
  wifi: iwlwifi: mld: make iwl_mld_mac80211_iftype_to_fw() static
  wifi: iwlwifi: mld: remove type argument from iwl_mld_add_sta()

Miri Korenblit (2):
  wifi: iwlwifi: bump core version for BZ/SC/DR
  wifi: iwlwifi: validate the channels received in
    iwl_mcc_update_resp_v*

Pagadala Yesu Anjaneyulu (3):
  wifi: iwlwifi: fw: Add TLV support for BIOS revision of command
  wifi: iwlwifi: mld: eliminate duplicate WIDE_ID in PPAG command
    handling
  wifi: iwlwifi: mld: add BIOS revision compatibility check for PPAG
    command

 drivers/net/wireless/intel/iwlwifi/cfg/bz.c   |   2 +-
 drivers/net/wireless/intel/iwlwifi/cfg/dr.c   |   2 +-
 .../net/wireless/intel/iwlwifi/cfg/rf-pe.c    |  24 ++-
 drivers/net/wireless/intel/iwlwifi/cfg/sc.c   |   2 +-
 .../wireless/intel/iwlwifi/fw/api/nvm-reg.h   |  37 +++-
 drivers/net/wireless/intel/iwlwifi/fw/file.h  |  15 ++
 drivers/net/wireless/intel/iwlwifi/fw/img.c   |  32 +++-
 drivers/net/wireless/intel/iwlwifi/fw/img.h   |   8 +
 .../net/wireless/intel/iwlwifi/iwl-config.h   |   9 +-
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c  |  21 +++
 .../wireless/intel/iwlwifi/iwl-nvm-parse.c    | 158 ++++++++++++------
 .../wireless/intel/iwlwifi/iwl-nvm-parse.h    |   2 +
 .../wireless/intel/iwlwifi/iwl-nvm-utils.h    |   3 +-
 .../net/wireless/intel/iwlwifi/mld/iface.c    |   6 +-
 .../net/wireless/intel/iwlwifi/mld/iface.h    |   2 -
 drivers/net/wireless/intel/iwlwifi/mld/link.h |   2 +
 .../net/wireless/intel/iwlwifi/mld/mac80211.c |  27 ++-
 .../wireless/intel/iwlwifi/mld/regulatory.c   |  25 ++-
 drivers/net/wireless/intel/iwlwifi/mld/rx.c   |  12 +-
 drivers/net/wireless/intel/iwlwifi/mld/sta.c  |   4 +-
 drivers/net/wireless/intel/iwlwifi/mld/sta.h  |   2 +-
 .../net/wireless/intel/iwlwifi/mld/stats.c    |  26 ++-
 drivers/net/wireless/intel/iwlwifi/mld/tlc.c  |  28 +++-
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |   7 +-
 drivers/net/wireless/intel/iwlwifi/pcie/drv.c |   2 +-
 .../intel/iwlwifi/pcie/gen1_2/trans-gen2.c    |  13 +-
 26 files changed, 379 insertions(+), 92 deletions(-)

-- 
2.34.1


^ permalink raw reply

* RE: [PATCH net-next v3 04/13] net: move promiscuity handling into dev_rx_mode_work
From: Loktionov, Aleksandr @ 2026-03-20  8:01 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-5-sdf@fomichev.me>



> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 04/13] net: move promiscuity handling into
> dev_rx_mode_work
> 
> Move unicast promiscuity tracking into dev_rx_mode_work so it runs
> under netdev_ops_lock instead of under the addr_lock spinlock. This is
> required because __dev_set_promiscuity calls dev_change_rx_flags and
> __dev_notify_flags, both of which may need to sleep.
> 
> Change ASSERT_RTNL() to netdev_ops_assert_locked() in
> __dev_set_promiscuity, netif_set_allmulti and __dev_change_flags since
> these are now called from the work queue under the ops lock.
> 
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  Documentation/networking/netdevices.rst |  4 ++
>  net/core/dev.c                          | 79 +++++++++++++++++-------
> -
>  2 files changed, 57 insertions(+), 26 deletions(-)
> 
> diff --git a/Documentation/networking/netdevices.rst
> b/Documentation/networking/netdevices.rst
> index dc83d78d3b27..5cdaa1a3dcc8 100644
> --- a/Documentation/networking/netdevices.rst
> +++ b/Documentation/networking/netdevices.rst
> @@ -298,6 +298,10 @@ struct net_device synchronization rules
>  	Notes: Sleepable version of ndo_set_rx_mode. Receives snapshots
>  	of the unicast and multicast address lists.
> 
> +ndo_change_rx_flags:
> +	Synchronization: rtnl_lock() semaphore. In addition, netdev
> instance
> +	lock if the driver implements queue management or shaper API.
> +
>  ndo_setup_tc:
>  	``TC_SETUP_BLOCK`` and ``TC_SETUP_FT`` are running under NFT
> locks
>  	(i.e. no ``rtnl_lock`` and no device instance lock). The rest
> of diff --git a/net/core/dev.c b/net/core/dev.c index
> fedc423306fc..fc5c9b14faa0 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -9574,7 +9574,7 @@ static int __dev_set_promiscuity(struct
> net_device *dev, int inc, bool notify)
>  	kuid_t uid;
>  	kgid_t gid;
> 
> -	ASSERT_RTNL();
> +	netdev_ops_assert_locked(dev);
Can you explain why do you add new hard precondition of ops lock must be held?


> 
>  	promiscuity = dev->promiscuity + inc;
>  	if (promiscuity == 0) {
> @@ -9610,16 +9610,8 @@ static int __dev_set_promiscuity(struct
> net_device *dev, int inc, bool notify)
> 
>  		dev_change_rx_flags(dev, IFF_PROMISC);
>  	}

...

>  	__hw_addr_init(&uc_snap);
> @@ -9704,16 +9720,29 @@ static void dev_rx_mode_work(struct
> work_struct *work)
>  		if (!err)
>  			err = __hw_addr_list_snapshot(&mc_ref, &dev->mc,
>  						      dev->addr_len);
> -		netif_addr_unlock_bh(dev);
> 
>  		if (err) {
>  			netdev_WARN(dev, "failed to sync uc/mc
> addresses\n");
>  			__hw_addr_flush(&uc_snap);
>  			__hw_addr_flush(&uc_ref);
>  			__hw_addr_flush(&mc_snap);
> +			netif_addr_unlock_bh(dev);
>  			goto out;
>  		}
> 
> +		promisc_inc = dev_uc_promisc_update(dev);
> +
> +		netif_addr_unlock_bh(dev);
> +	} else {
> +		netif_addr_lock_bh(dev);
> +		promisc_inc = dev_uc_promisc_update(dev);
> +		netif_addr_unlock_bh(dev);
> +	}
> +
> +	if (promisc_inc)
> +		__dev_set_promiscuity(dev, promisc_inc, false);
But it's being called here without any netdev_lock_ops(dev) ?

> +
> +	if (ops->ndo_set_rx_mode_async) {
>  		ops->ndo_set_rx_mode_async(dev, &uc_snap, &mc_snap);
> 
>  		netif_addr_lock_bh(dev);
> @@ -9722,6 +9751,10 @@ static void dev_rx_mode_work(struct work_struct
> *work)
>  		__hw_addr_list_reconcile(&dev->mc, &mc_snap,
>  					 &mc_ref, dev->addr_len);
>  		netif_addr_unlock_bh(dev);
> +	} else if (ops->ndo_set_rx_mode) {
> +		netif_addr_lock_bh(dev);
> +		ops->ndo_set_rx_mode(dev);
> +		netif_addr_unlock_bh(dev);
>  	}

...

> --
> 2.53.0


^ permalink raw reply

* RE: [PATCH net-next v3 12/13] net: warn ops-locked drivers still using ndo_set_rx_mode
From: Loktionov, Aleksandr @ 2026-03-20  7:55 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-13-sdf@fomichev.me>



> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 12/13] net: warn ops-locked drivers still
> using ndo_set_rx_mode
> 
> Now that all in-tree ops-locked drivers have been converted to
> ndo_set_rx_mode_async, add a warning in register_netdevice to catch
> any remaining or newly added drivers that use ndo_set_rx_mode with ops
> locking. This ensures future driver authors are guided toward the
> async path.
> 
> Also route ops-locked devices through dev_rx_mode_work even if they
> lack rx_mode NDOs, to ensure netdev_ops_assert_locked() does not fire
> on the legacy path where only RTNL is held.
> 
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  net/core/dev.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/dev.c b/net/core/dev.c index
> fc5c9b14faa0..f38ab254708b 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -9779,7 +9779,8 @@ void __dev_set_rx_mode(struct net_device *dev)
>  	if (!netif_up_and_present(dev))
>  		return;
> 
> -	if (ops->ndo_set_rx_mode_async || ops->ndo_change_rx_flags) {
> +	if (ops->ndo_set_rx_mode_async || ops->ndo_change_rx_flags ||
> +	    netdev_need_ops_lock(dev)) {
>  		queue_work(rx_mode_wq, &dev->rx_mode_work);
>  		return;
>  	}
> @@ -11471,6 +11472,11 @@ int register_netdevice(struct net_device
> *dev)
>  		goto err_uninit;
>  	}
> 
> +	if (netdev_need_ops_lock(dev) &&
> +	    dev->netdev_ops->ndo_set_rx_mode &&
> +	    !dev->netdev_ops->ndo_set_rx_mode_async)
> +		netdev_WARN(dev, "ops-locked drivers should use
> +ndo_set_rx_mode_async\n");
> +
>  	ret = netdev_do_alloc_pcpu_stats(dev);
>  	if (ret)
>  		goto err_uninit;
> --
> 2.53.0


Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>


^ permalink raw reply

* RE: [PATCH net-next v3 11/13] dummy: convert to ndo_set_rx_mode_async
From: Loktionov, Aleksandr @ 2026-03-20  7:54 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-12-sdf@fomichev.me>



> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 11/13] dummy: convert to
> ndo_set_rx_mode_async
> 
> Convert dummy driver from ndo_set_rx_mode to ndo_set_rx_mode_async.
> The dummy driver's set_multicast_list is a no-op, so the conversion is
> straightforward: update the signature and the ops assignment.
> 
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  drivers/net/dummy.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index
> d6bdad4baadd..f8a4eb365c3d 100644
> --- a/drivers/net/dummy.c
> +++ b/drivers/net/dummy.c
> @@ -47,7 +47,9 @@
>  static int numdummies = 1;
> 
>  /* fake multicast ability */
> -static void set_multicast_list(struct net_device *dev)
> +static void set_multicast_list(struct net_device *dev,
> +			       struct netdev_hw_addr_list *uc,
> +			       struct netdev_hw_addr_list *mc)
>  {
>  }
> 
> @@ -87,7 +89,7 @@ static const struct net_device_ops dummy_netdev_ops
> = {
>  	.ndo_init		= dummy_dev_init,
>  	.ndo_start_xmit		= dummy_xmit,
>  	.ndo_validate_addr	= eth_validate_addr,
> -	.ndo_set_rx_mode	= set_multicast_list,
> +	.ndo_set_rx_mode_async	= set_multicast_list,
>  	.ndo_set_mac_address	= eth_mac_addr,
>  	.ndo_get_stats64	= dummy_get_stats64,
>  	.ndo_change_carrier	= dummy_change_carrier,
> --
> 2.53.0

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

^ permalink raw reply

* RE: [PATCH net-next v3 09/13] iavf: convert to ndo_set_rx_mode_async
From: Loktionov, Aleksandr @ 2026-03-20  7:53 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-10-sdf@fomichev.me>



> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 09/13] iavf: convert to
> ndo_set_rx_mode_async
> 
> Convert iavf from ndo_set_rx_mode to ndo_set_rx_mode_async.
> iavf_set_rx_mode now takes explicit uc/mc list parameters and uses
> __hw_addr_sync_dev on the snapshots instead of __dev_uc_sync and
> __dev_mc_sync.
> 
> The iavf_configure internal caller passes the real lists directly.
> 
> Cc: Tony Nguyen <anthony.l.nguyen@intel.com>
> Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  drivers/net/ethernet/intel/iavf/iavf_main.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c
> b/drivers/net/ethernet/intel/iavf/iavf_main.c
> index 7925ee152c76..6632d35ad0fe 100644
> --- a/drivers/net/ethernet/intel/iavf/iavf_main.c
> +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
> @@ -1147,14 +1147,18 @@ bool iavf_promiscuous_mode_changed(struct
> iavf_adapter *adapter)
>  /**
>   * iavf_set_rx_mode - NDO callback to set the netdev filters
>   * @netdev: network interface device structure
> + * @uc: snapshot of uc address list
> + * @mc: snapshot of mc address list
>   **/
> -static void iavf_set_rx_mode(struct net_device *netdev)
> +static void iavf_set_rx_mode(struct net_device *netdev,
> +			     struct netdev_hw_addr_list *uc,
> +			     struct netdev_hw_addr_list *mc)
>  {
>  	struct iavf_adapter *adapter = netdev_priv(netdev);
> 
>  	spin_lock_bh(&adapter->mac_vlan_list_lock);
> -	__dev_uc_sync(netdev, iavf_addr_sync, iavf_addr_unsync);
> -	__dev_mc_sync(netdev, iavf_addr_sync, iavf_addr_unsync);
> +	__hw_addr_sync_dev(uc, netdev, iavf_addr_sync,
> iavf_addr_unsync);
> +	__hw_addr_sync_dev(mc, netdev, iavf_addr_sync,
> iavf_addr_unsync);
>  	spin_unlock_bh(&adapter->mac_vlan_list_lock);
> 
>  	spin_lock_bh(&adapter->current_netdev_promisc_flags_lock);
> @@ -1207,7 +1211,7 @@ static void iavf_configure(struct iavf_adapter
> *adapter)
>  	struct net_device *netdev = adapter->netdev;
>  	int i;
> 
> -	iavf_set_rx_mode(netdev);
> +	iavf_set_rx_mode(netdev, &netdev->uc, &netdev->mc);
> 
>  	iavf_configure_tx(adapter);
>  	iavf_configure_rx(adapter);
> @@ -5150,7 +5154,7 @@ static const struct net_device_ops
> iavf_netdev_ops = {
>  	.ndo_open		= iavf_open,
>  	.ndo_stop		= iavf_close,
>  	.ndo_start_xmit		= iavf_xmit_frame,
> -	.ndo_set_rx_mode	= iavf_set_rx_mode,
> +	.ndo_set_rx_mode_async	= iavf_set_rx_mode,
>  	.ndo_validate_addr	= eth_validate_addr,
>  	.ndo_set_mac_address	= iavf_set_mac,
>  	.ndo_change_mtu		= iavf_change_mtu,
> --
> 2.53.0

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>


^ permalink raw reply

* RE: [PATCH net-next v3 08/13] bnxt: use snapshot in bnxt_cfg_rx_mode
From: Loktionov, Aleksandr @ 2026-03-20  7:51 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-9-sdf@fomichev.me>



> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 08/13] bnxt: use snapshot in
> bnxt_cfg_rx_mode
> 
> With the introduction of ndo_set_rx_mode_async (as discussed in [0])
> we can call bnxt_cfg_rx_mode directly. Convert bnxt_cfg_rx_mode to use
> uc/mc snapshots and move its call in bnxt_sp_task to the section that
> resets BNXT_STATE_IN_SP_TASK. Switch to direct call in
> bnxt_set_rx_mode.
> 
> 0:
> https://lore.kernel.org/netdev/CACKFLi=5vj8hPqEUKDd8RTw3au5G+zRgQEqjF+
> 6NZnyoNm90KA@mail.gmail.com/
> 
> Cc: Michael Chan <michael.chan@broadcom.com>
> Cc: Pavan Chebbi <pavan.chebbi@broadcom.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c | 26 ++++++++++++++--------
> -
>  1 file changed, 16 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index 225217b32e4b..12265bd7fda4 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -11039,7 +11039,8 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt
> *bp)
>  	return rc;
>  }
> 
> -static int bnxt_cfg_rx_mode(struct bnxt *);
> +static int bnxt_cfg_rx_mode(struct bnxt *, struct netdev_hw_addr_list
> *,
> +			    struct netdev_hw_addr_list *);
>  static bool bnxt_mc_list_updated(struct bnxt *, u32 *,
>  				 const struct netdev_hw_addr_list *);
> 
> @@ -11135,7 +11136,7 @@ static int bnxt_init_chip(struct bnxt *bp,
> bool irq_re_init)
>  		vnic->rx_mask |= mask;
>  	}
> 
> -	rc = bnxt_cfg_rx_mode(bp);
> +	rc = bnxt_cfg_rx_mode(bp, &bp->dev->uc, &bp->dev->mc);
>  	if (rc)
>  		goto err_out;
> 
> @@ -13610,11 +13611,12 @@ static void bnxt_set_rx_mode(struct
> net_device *dev,
>  	if (mask != vnic->rx_mask || uc_update || mc_update) {
>  		vnic->rx_mask = mask;
> 
> -		bnxt_queue_sp_work(bp, BNXT_RX_MASK_SP_EVENT);
> +		bnxt_cfg_rx_mode(bp, uc, mc);
>  	}
>  }
> 
> -static int bnxt_cfg_rx_mode(struct bnxt *bp)
> +static int bnxt_cfg_rx_mode(struct bnxt *bp, struct
> netdev_hw_addr_list *uc,
> +			    struct netdev_hw_addr_list *mc)
>  {
>  	struct net_device *dev = bp->dev;
>  	struct bnxt_vnic_info *vnic = &bp-
> >vnic_info[BNXT_VNIC_DEFAULT];
> @@ -13623,7 +13625,7 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
>  	bool uc_update;
> 
>  	netif_addr_lock_bh(dev);
> -	uc_update = bnxt_uc_list_updated(bp, &dev->uc);
> +	uc_update = bnxt_uc_list_updated(bp, uc);
>  	netif_addr_unlock_bh(dev);
> 
>  	if (!uc_update)
> @@ -13639,10 +13641,10 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
>  	vnic->uc_filter_count = 1;
> 
>  	netif_addr_lock_bh(dev);
> -	if (netdev_uc_count(dev) > (BNXT_MAX_UC_ADDRS - 1)) {
> +	if (netdev_hw_addr_list_count(uc) > (BNXT_MAX_UC_ADDRS - 1)) {
>  		vnic->rx_mask |=
> CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
>  	} else {
> -		netdev_for_each_uc_addr(ha, dev) {
> +		netdev_hw_addr_list_for_each(ha, uc) {
>  			memcpy(vnic->uc_list + off, ha->addr, ETH_ALEN);
>  			off += ETH_ALEN;
>  			vnic->uc_filter_count++;
> @@ -14600,6 +14602,7 @@ static void bnxt_ulp_restart(struct bnxt *bp)
> static void bnxt_sp_task(struct work_struct *work)  {
>  	struct bnxt *bp = container_of(work, struct bnxt, sp_task);
> +	struct net_device *dev = bp->dev;
> 
>  	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
>  	smp_mb__after_atomic();
> @@ -14613,9 +14616,6 @@ static void bnxt_sp_task(struct work_struct
> *work)
>  		bnxt_reenable_sriov(bp);
>  	}
> 
> -	if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
> -		bnxt_cfg_rx_mode(bp);
> -
>  	if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp-
> >sp_event))
>  		bnxt_cfg_ntp_filters(bp);
>  	if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp-
> >sp_event)) @@ -14680,6 +14680,12 @@ static void bnxt_sp_task(struct
> work_struct *work)
>  	/* These functions below will clear BNXT_STATE_IN_SP_TASK.
> They
>  	 * must be the last functions to be called before exiting.
>  	 */
> +	if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event)) {
> +		bnxt_lock_sp(bp);
> +		bnxt_cfg_rx_mode(bp, &dev->uc, &dev->mc);
> +		bnxt_unlock_sp(bp);
> +	}
> +
>  	if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp-
> >sp_event))
>  		bnxt_reset(bp, false);
> 
> --
> 2.53.0

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>


^ permalink raw reply

* Re: [PATCH wireless-next 14/35] wifi: mm81x: add mac.c
From: Johannes Berg @ 2026-03-20  7:18 UTC (permalink / raw)
  To: Lachlan Hodges
  Cc: Dan Callaghan, Arien Judge, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, ayman.grais, linux-wireless,
	linux-kernel
In-Reply-To: <x2c5mvplhtdfl7u2m54roosjtxjhzab2kq6tpqmehbmauiwvi2@gsktg3ztlhng>

On Fri, 2026-03-20 at 17:39 +1100, Lachlan Hodges wrote:
> > 
> Thinking about this a bit further, the initial items on the todo
> list are more or less as follows:
> 
> 1. hostapd support (mostly unrelated, some minor tweaks to hwsim)
> 2. Rx reporting - mainly mac and cfg with some minor driver changes
>    + usermode aswell
> 3. iw and iwinfo support (again, unrelated)
> 4. extend regulatory support - this will be a big challenge and once
>    again mostly cfg and mac
> 
> So most driver work would just be plumbing through any required
> changes for the above, no large features in the near future.
> 
> > which is probably simpler if I apply driver patches too,
> > otherwise you have to synchronise pull requests to when I apply patches
> > to my tree? OTOH, to pass the bot checks you already have to do that
> > anyway, unless sending cfg/mac/driver patches in one series, which also
> > isn't great since it ends to bury the cfg/mac patches.
> 
> Initially that works with us if you apply the patches :)

Works for me too :)

> I have made an account with the user "lhodges" on patchwork - no
> issues with that.

Nice, thanks, I'll go request you be added as admin, so I can delegate
the right patches to you automatically.

> We haven't got a public tree tracking wireless-next
> yet. Nothing necessarily blocking that except internal processes, I
> assume there's no issue adding it later?

Indeed, no problem at all.

I'd still somewhat prefer to have the initial commit as a pull request,
but if you really don't have a public git tree now you can also send a
big single commit with all the right things to me in private, and then
I'll put it somewhere and send it to the list. We can figure this out
either way, no big deal.

Thanks,
johannes

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce ndo_set_rx_mode_async and dev_rx_mode_work
From: Loktionov, Aleksandr @ 2026-03-20  7:13 UTC (permalink / raw)
  To: Stanislav Fomichev, netdev@vger.kernel.org
  Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
	skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
	michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
	kernel-team@meta.com, johannes@sipsolutions.net,
	sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
	mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
	skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
	linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
	leon@kernel.org
In-Reply-To: <20260320012501.2033548-4-sdf@fomichev.me>



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Stanislav Fomichev
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce
> ndo_set_rx_mode_async and dev_rx_mode_work
> 
> Add ndo_set_rx_mode_async callback that drivers can implement instead
> of the legacy ndo_set_rx_mode. The legacy callback runs under the
> netif_addr_lock spinlock with BHs disabled, preventing drivers from
> sleeping. The async variant runs from a work queue with rtnl_lock and
> netdev_lock_ops held, in fully sleepable context.
> 
> When __dev_set_rx_mode() sees ndo_set_rx_mode_async, it schedules
> dev_rx_mode_work instead of calling the driver inline. The work
> function takes two snapshots of each address list (uc/mc) under the
> addr_lock, then drops the lock and calls the driver with the work
> copies. After the driver returns, it reconciles the snapshots back to
> the real lists under the lock.
> 
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  Documentation/networking/netdevices.rst |  8 +++
>  include/linux/netdevice.h               | 20 ++++++
>  net/core/dev.c                          | 95 +++++++++++++++++++++++-
> -
>  3 files changed, 116 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/networking/netdevices.rst
> b/Documentation/networking/netdevices.rst
> index 35704d115312..dc83d78d3b27 100644
> --- a/Documentation/networking/netdevices.rst
> +++ b/Documentation/networking/netdevices.rst
> @@ -289,6 +289,14 @@ struct net_device synchronization rules
>  ndo_set_rx_mode:
>  	Synchronization: netif_addr_lock spinlock.
>  	Context: BHs disabled

...

> to
> +device
> + * and configure RX filtering.
> + * @dev: device
> + *
> + * When the device doesn't support unicast filtering it is put in
> +promiscuous
> + * mode while unicast addresses are present.
>   */
>  void __dev_set_rx_mode(struct net_device *dev)  {
>  	const struct net_device_ops *ops = dev->netdev_ops;
> 
>  	/* dev_open will call this function so the list will stay sane.
> */
> -	if (!(dev->flags&IFF_UP))
> +	if (!netif_up_and_present(dev))
>  		return;
> 
> -	if (!netif_device_present(dev))
> +	if (ops->ndo_set_rx_mode_async) {
> +		queue_work(rx_mode_wq, &dev->rx_mode_work);
>  		return;
This early return skips the legacy core fallback below.
Before this patch, __dev_set_rx_mode() continued into the
existing unicast-filter handling when the device did not
advertise IFF_UNICAST_FLT.

After this patch, any driver that implements
ndo_set_rx_mode_async but does not set IFF_UNICAST_FLT
will never hit that fallback path.

+	}
> 
>  	if (!(dev->priv_flags & IFF_UNICAST_FLT)) {
>  		/* Unicast addresses changes may only happen under the
> rtnl, @@ -11708,6 +11772,16 @@ void netdev_run_todo(void)
> 
>  	__rtnl_unlock();
> 

...

>  	open_softirq(NET_TX_SOFTIRQ, net_tx_action);
>  	open_softirq(NET_RX_SOFTIRQ, net_rx_action);
> 
> --
> 2.53.0


^ permalink raw reply

* Re: [PATCH wireless-next 14/35] wifi: mm81x: add mac.c
From: Lachlan Hodges @ 2026-03-20  6:39 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Dan Callaghan, Arien Judge, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, ayman.grais, linux-wireless,
	linux-kernel
In-Reply-To: <888ab7ed9c72d19765e87f00b17dd95963cbca18.camel@sipsolutions.net>

> > We expect to see some larger features - including monitor mode, and
> > mesh in the near to mid-term future within the driver itself, but the
> > core development will still remain in mac80211 & cfg80211 as we
> > extend the S1G implementation.
> 
> Sounds like there would be quite some co-development with cfg/mac and
> the driver

Thinking about this a bit further, the initial items on the todo
list are more or less as follows:

1. hostapd support (mostly unrelated, some minor tweaks to hwsim)
2. Rx reporting - mainly mac and cfg with some minor driver changes
   + usermode aswell
3. iw and iwinfo support (again, unrelated)
4. extend regulatory support - this will be a big challenge and once
   again mostly cfg and mac

So most driver work would just be plumbing through any required
changes for the above, no large features in the near future.

> which is probably simpler if I apply driver patches too,
> otherwise you have to synchronise pull requests to when I apply patches
> to my tree? OTOH, to pass the bot checks you already have to do that
> anyway, unless sending cfg/mac/driver patches in one series, which also
> isn't great since it ends to bury the cfg/mac patches.

Initially that works with us if you apply the patches :). Obviously,
once supports get a bit more mature and the work is deocupled the goal
would be to send you pull requests. Let's go with patches to you now,
and if that works out to not be ideal we can move to pull requests

> > As for workflows, we are still figuring that out for ourselves.
> 
> I'd prefer if you could create an account on patchwork.kernel.org, and
> then I can automatically delegate patches to this driver to you. Whether
> or not you then re-assign them to me in patchwork or collect them and
> send a pull request is somewhat secondary, but the latter obviously
> makes things a bit simpler for me. If you _are_ going to do that longer
> term than just the initial driver, probably should document a T: entry
> in the maintainers file too.

I have made an account with the user "lhodges" on patchwork - no
issues with that. We haven't got a public tree tracking wireless-next
yet. Nothing necessarily blocking that except internal processes, I
assume there's no issue adding it later?

lachlan

^ permalink raw reply

* Re: [PATCH v4] wifi: mt76: mt7921: fix txpower reporting from rate power configuration
From: Greg KH @ 2026-03-20  6:34 UTC (permalink / raw)
  To: Lucid Duck
  Cc: sean.wang, nbd, lorenzo, linux-wireless, linux-mediatek, morrownr,
	stable
In-Reply-To: <20260320011727.77939-1-lucid_duck@justthetip.ca>

On Thu, Mar 19, 2026 at 06:17:27PM -0700, Lucid Duck wrote:
> Note for stable backport: this patch uses mt76_tx_power_path_delta()
> which was introduced in commit 56e38675c5bd ("mt76: support power delta
> calculation for 5 TX paths"). That commit renamed the older
> mt76_tx_power_nss_delta() and is needed as a prerequisite for the
> backport to compile.
> 
> For stable kernels that don't have 56e3867, a trivial substitution of
> mt76_tx_power_nss_delta for mt76_tx_power_path_delta produces identical
> results for 1-4 chain devices (the lookup tables match exactly).
> 
> Reported-by: sam8641 (compile failure on 6.12.74)

This "note for stable backport" will get lost, sorry.  Can you provide
working backports to stable@vger.kernel.org when this lands in Linus's
tree?

thanks,

greg k-h

^ permalink raw reply

* [wireless:for-next] BUILD SUCCESS 7c46bd845d89ad4772573cfe0f2a56b93db75cc7
From: kernel test robot @ 2026-03-20  5:34 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: Johannes Berg, linux-wireless

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git for-next
branch HEAD: 7c46bd845d89ad4772573cfe0f2a56b93db75cc7  Merge tag 'wireless-2026-03-18' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

elapsed time: 1619m

configs tested: 227
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260319    gcc-11.5.0
arc                   randconfig-001-20260320    gcc-13.4.0
arc                   randconfig-002-20260319    gcc-11.5.0
arc                   randconfig-002-20260320    gcc-13.4.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                              allyesconfig    gcc-15.2.0
arm                        clps711x_defconfig    clang-23
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260319    gcc-11.5.0
arm                   randconfig-001-20260320    gcc-13.4.0
arm                   randconfig-002-20260319    gcc-11.5.0
arm                   randconfig-002-20260320    gcc-13.4.0
arm                   randconfig-003-20260319    gcc-11.5.0
arm                   randconfig-003-20260320    gcc-13.4.0
arm                   randconfig-004-20260319    gcc-11.5.0
arm                   randconfig-004-20260320    gcc-13.4.0
arm                       spear13xx_defconfig    gcc-15.2.0
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260320    clang-17
arm64                 randconfig-002-20260320    clang-17
arm64                 randconfig-003-20260320    clang-17
arm64                 randconfig-004-20260320    clang-17
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260320    clang-17
csky                  randconfig-002-20260320    clang-17
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260320    gcc-8.5.0
hexagon               randconfig-002-20260320    gcc-8.5.0
i386                             allmodconfig    clang-20
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260319    gcc-14
i386        buildonly-randconfig-001-20260320    gcc-14
i386        buildonly-randconfig-002-20260319    gcc-14
i386        buildonly-randconfig-002-20260320    gcc-14
i386        buildonly-randconfig-003-20260319    gcc-14
i386        buildonly-randconfig-003-20260320    gcc-14
i386        buildonly-randconfig-004-20260319    gcc-14
i386        buildonly-randconfig-004-20260320    gcc-14
i386        buildonly-randconfig-005-20260319    gcc-14
i386        buildonly-randconfig-005-20260320    gcc-14
i386        buildonly-randconfig-006-20260319    gcc-14
i386        buildonly-randconfig-006-20260320    gcc-14
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260319    gcc-14
i386                  randconfig-001-20260320    clang-20
i386                  randconfig-002-20260319    gcc-14
i386                  randconfig-002-20260320    clang-20
i386                  randconfig-003-20260319    gcc-14
i386                  randconfig-003-20260320    clang-20
i386                  randconfig-004-20260319    gcc-14
i386                  randconfig-004-20260320    clang-20
i386                  randconfig-005-20260319    gcc-14
i386                  randconfig-005-20260320    clang-20
i386                  randconfig-006-20260319    gcc-14
i386                  randconfig-006-20260320    clang-20
i386                  randconfig-007-20260319    gcc-14
i386                  randconfig-007-20260320    clang-20
i386                  randconfig-011-20260319    clang-20
i386                  randconfig-011-20260320    clang-20
i386                  randconfig-012-20260319    clang-20
i386                  randconfig-012-20260320    clang-20
i386                  randconfig-013-20260319    clang-20
i386                  randconfig-013-20260320    clang-20
i386                  randconfig-014-20260319    clang-20
i386                  randconfig-014-20260320    clang-20
i386                  randconfig-015-20260319    clang-20
i386                  randconfig-015-20260320    clang-20
i386                  randconfig-016-20260319    clang-20
i386                  randconfig-016-20260320    clang-20
i386                  randconfig-017-20260319    clang-20
i386                  randconfig-017-20260320    clang-20
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260320    gcc-8.5.0
loongarch             randconfig-002-20260320    gcc-8.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260320    gcc-8.5.0
nios2                 randconfig-002-20260320    gcc-8.5.0
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260320    gcc-10.5.0
parisc                randconfig-002-20260320    gcc-10.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc               randconfig-001-20260320    gcc-10.5.0
powerpc               randconfig-002-20260320    gcc-10.5.0
powerpc64             randconfig-001-20260320    gcc-10.5.0
powerpc64             randconfig-002-20260320    gcc-10.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260320    gcc-8.5.0
riscv                 randconfig-002-20260320    gcc-8.5.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260320    gcc-8.5.0
s390                  randconfig-002-20260320    gcc-8.5.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260320    gcc-8.5.0
sh                    randconfig-002-20260320    gcc-8.5.0
sparc                            alldefconfig    gcc-15.2.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260319    gcc-8.5.0
sparc                 randconfig-001-20260320    gcc-14
sparc                 randconfig-002-20260319    gcc-8.5.0
sparc                 randconfig-002-20260320    gcc-14
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260319    gcc-8.5.0
sparc64               randconfig-001-20260320    gcc-14
sparc64               randconfig-002-20260319    gcc-8.5.0
sparc64               randconfig-002-20260320    gcc-14
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260319    gcc-8.5.0
um                    randconfig-001-20260320    gcc-14
um                    randconfig-002-20260319    gcc-8.5.0
um                    randconfig-002-20260320    gcc-14
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260320    clang-20
x86_64      buildonly-randconfig-002-20260320    clang-20
x86_64      buildonly-randconfig-003-20260320    clang-20
x86_64      buildonly-randconfig-004-20260320    clang-20
x86_64      buildonly-randconfig-005-20260320    clang-20
x86_64      buildonly-randconfig-006-20260320    clang-20
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20260320    clang-20
x86_64                randconfig-002-20260320    clang-20
x86_64                randconfig-003-20260320    clang-20
x86_64                randconfig-004-20260320    clang-20
x86_64                randconfig-005-20260320    clang-20
x86_64                randconfig-006-20260320    clang-20
x86_64                randconfig-071-20260320    gcc-14
x86_64                randconfig-072-20260320    gcc-14
x86_64                randconfig-073-20260320    gcc-14
x86_64                randconfig-074-20260320    gcc-14
x86_64                randconfig-075-20260320    gcc-14
x86_64                randconfig-076-20260320    gcc-14
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                           allyesconfig    gcc-15.2.0
xtensa                randconfig-001-20260319    gcc-8.5.0
xtensa                randconfig-001-20260320    gcc-14
xtensa                randconfig-002-20260319    gcc-8.5.0
xtensa                randconfig-002-20260320    gcc-14

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* RE: [BUG] wifi: rtw88: Hard system freeze on RTL8821CE when power_save is enabled (LPS/ASPM conflict)
From: Ping-Ke Shih @ 2026-03-20  2:02 UTC (permalink / raw)
  To: LB F; +Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CALdGYqSd61wxNrPDui+m-S+Na_is-RM18-=L6xm-Jf4QQ+-DOg@mail.gmail.com>

LB F <goainwo@gmail.com> wrote:
> Ping-Ke Shih <pkshih@realtek.com> wrote:
> > Not sure what hardware get wrong. Let's validate rate when reading
> > from hardware. Since 1M rate can only 20MHz, I set it together.
> > Please help to test below. I suppose you can see "weird rate=xxx",
> > but "WARNING: net/mac80211/rx.c:5491" disappears.
> 
> Hi Ping-Ke,
> 
> I can confirm your patch works as expected. Here are the full results.
> 
> --- Test environment ---
> 
> Kernel:  6.19.7-1-cachyos
> Patch:   your rate validation patch applied to rtw_rx_query_rx_desc(),
>          on top of the v2 DMI quirk (ASPM + LPS Deep disabled)
> 
> --- Captured log (relevant excerpt) ---
> 
>   [  43.046] input: Soundcore Q10i (AVRCP)   <-- BT headset connected
>   [ 111.551] rtw_8821ce 0000:13:00.0: unused phy status page (13)
>   [ 111.635] weird rate=101
>   [ 111.635] rtw_8821ce 0000:13:00.0: unused phy status page (7)
>   [ 111.741] weird rate=102
>   [ 115.045] weird rate=98
>   [ 118.371] weird rate=104
> 
> --- Analysis ---
> 
> 1. Timing: the anomalous events began approximately 68 seconds after
>    the Bluetooth A2DP headset (Soundcore Q10i) established its
>    connection. No anomalies were observed before BT connected.
> 
> 2. Multiple invalid rate values were captured, not just 0x65:
> 
>      weird rate=101  (0x65)
>      weird rate=102  (0x66)
>      weird rate=98   (0x62)
>      weird rate=104  (0x68)
> 
>    All four values exceed DESC_RATE_MAX (0x53 = 83 decimal). This
>    suggests the hardware occasionally reports a range of out-of-bounds
>    rate values during BT/Wi-Fi coexistence, not a single fixed value.
> 
> 3. The "unused phy status page" messages (pages 13 and 7) appeared
>    immediately before and alongside the "weird rate" events. As noted
>    in my previous message, only pages 0 and 1 are expected. This
>    further suggests the firmware leaks internal coexistence state
>    into the RX ring during BT antenna arbitration.
> 
> 4. Most importantly: the WARNING: net/mac80211/rx.c:5491 did NOT
>    appear anywhere in the log. Your rate clamping patch successfully
>    intercepts the out-of-bounds values before they propagate to
>    mac80211, preventing the invalid VHT NSS=0 warning entirely.
> 
> --- Conclusion ---
> 
> Your patch achieves the intended result. The "weird rate" printk
> confirms the hardware is the source of the invalid values (occurring
> during BT coexistence), and the mac80211 WARNING is suppressed.
> 
> Please let me know if you need any additional data or further testing.

I'll send formal patch (Cc you) for the invalid VHT NSS=0, but not to
handle "unused phy status page". Please give me Tested-by tag on the
patch after I send it.

Ping-Ke


^ permalink raw reply

* [PATCH net-next v3 13/13] selftests: net: add team_bridge_macvlan rx_mode test
From: Stanislav Fomichev @ 2026-03-20  1:25 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, corbet, skhan,
	andrew+netdev, michael.chan, pavan.chebbi, anthony.l.nguyen,
	przemyslaw.kitszel, saeedm, tariqt, mbloch, alexanderduyck,
	kernel-team, johannes, sd, jianbol, dtatulea, sdf, mohsin.bashr,
	jacob.e.keller, willemb, skhawaja, bestswngs, aleksandr.loktionov,
	kees, linux-doc, linux-kernel, intel-wired-lan, linux-rdma,
	linux-wireless, linux-kselftest, leon
In-Reply-To: <20260320012501.2033548-1-sdf@fomichev.me>

Add a test that exercises the ndo_change_rx_flags path through a
macvlan -> bridge -> team -> dummy stack. This triggers dev_uc_add
under addr_list_lock which flips promiscuity on the lower device.
With the new work queue approach, this must not deadlock.

Link: https://lore.kernel.org/netdev/20260214033859.43857-1-jiayuan.chen@linux.dev/
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 tools/testing/selftests/net/config       |  1 +
 tools/testing/selftests/net/rtnetlink.sh | 44 ++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config
index 2a390cae41bf..94d722770420 100644
--- a/tools/testing/selftests/net/config
+++ b/tools/testing/selftests/net/config
@@ -101,6 +101,7 @@ CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_NETEM=y
 CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_TEAM=y
 CONFIG_NET_VRF=y
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_OVS=y
diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
index 5a5ff88321d5..c499953d4885 100755
--- a/tools/testing/selftests/net/rtnetlink.sh
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -23,6 +23,7 @@ ALL_TESTS="
 	kci_test_encap
 	kci_test_macsec
 	kci_test_macsec_vlan
+	kci_test_team_bridge_macvlan
 	kci_test_ipsec
 	kci_test_ipsec_offload
 	kci_test_fdb_get
@@ -636,6 +637,49 @@ kci_test_macsec_vlan()
 	end_test "PASS: macsec_vlan"
 }
 
+# Test ndo_change_rx_flags call from dev_uc_add under addr_list_lock spinlock.
+# When we are flipping the promisc, make sure it runs on the work queue.
+#
+# https://lore.kernel.org/netdev/20260214033859.43857-1-jiayuan.chen@linux.dev/
+# With (more conventional) macvlan instead of macsec.
+# macvlan -> bridge -> team -> dummy
+kci_test_team_bridge_macvlan()
+{
+	local vlan="test_macv1"
+	local bridge="test_br1"
+	local team="test_team1"
+	local dummy="test_dummy1"
+	local ret=0
+
+	run_cmd ip link add $team type team
+	if [ $ret -ne 0 ]; then
+		end_test "SKIP: team_bridge_macvlan: can't add team interface"
+		return $ksft_skip
+	fi
+
+	run_cmd ip link add $dummy type dummy
+	run_cmd ip link set $dummy master $team
+	run_cmd ip link set $team up
+	run_cmd ip link add $bridge type bridge vlan_filtering 1
+	run_cmd ip link set $bridge up
+	run_cmd ip link set $team master $bridge
+	run_cmd ip link add link $bridge name $vlan \
+		address 00:aa:bb:cc:dd:ee type macvlan mode bridge
+	run_cmd ip link set $vlan up
+
+	run_cmd ip link del $vlan
+	run_cmd ip link del $bridge
+	run_cmd ip link del $team
+	run_cmd ip link del $dummy
+
+	if [ $ret -ne 0 ]; then
+		end_test "FAIL: team_bridge_macvlan"
+		return 1
+	fi
+
+	end_test "PASS: team_bridge_macvlan"
+}
+
 #-------------------------------------------------------------------
 # Example commands
 #   ip x s add proto esp src 14.0.0.52 dst 14.0.0.70 \
-- 
2.53.0


^ permalink raw reply related

* [PATCH net-next v3 12/13] net: warn ops-locked drivers still using ndo_set_rx_mode
From: Stanislav Fomichev @ 2026-03-20  1:25 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, corbet, skhan,
	andrew+netdev, michael.chan, pavan.chebbi, anthony.l.nguyen,
	przemyslaw.kitszel, saeedm, tariqt, mbloch, alexanderduyck,
	kernel-team, johannes, sd, jianbol, dtatulea, sdf, mohsin.bashr,
	jacob.e.keller, willemb, skhawaja, bestswngs, aleksandr.loktionov,
	kees, linux-doc, linux-kernel, intel-wired-lan, linux-rdma,
	linux-wireless, linux-kselftest, leon
In-Reply-To: <20260320012501.2033548-1-sdf@fomichev.me>

Now that all in-tree ops-locked drivers have been converted to
ndo_set_rx_mode_async, add a warning in register_netdevice to catch
any remaining or newly added drivers that use ndo_set_rx_mode with
ops locking. This ensures future driver authors are guided toward
the async path.

Also route ops-locked devices through dev_rx_mode_work even if they
lack rx_mode NDOs, to ensure netdev_ops_assert_locked() does not fire
on the legacy path where only RTNL is held.

Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 net/core/dev.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index fc5c9b14faa0..f38ab254708b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9779,7 +9779,8 @@ void __dev_set_rx_mode(struct net_device *dev)
 	if (!netif_up_and_present(dev))
 		return;
 
-	if (ops->ndo_set_rx_mode_async || ops->ndo_change_rx_flags) {
+	if (ops->ndo_set_rx_mode_async || ops->ndo_change_rx_flags ||
+	    netdev_need_ops_lock(dev)) {
 		queue_work(rx_mode_wq, &dev->rx_mode_work);
 		return;
 	}
@@ -11471,6 +11472,11 @@ int register_netdevice(struct net_device *dev)
 		goto err_uninit;
 	}
 
+	if (netdev_need_ops_lock(dev) &&
+	    dev->netdev_ops->ndo_set_rx_mode &&
+	    !dev->netdev_ops->ndo_set_rx_mode_async)
+		netdev_WARN(dev, "ops-locked drivers should use ndo_set_rx_mode_async\n");
+
 	ret = netdev_do_alloc_pcpu_stats(dev);
 	if (ret)
 		goto err_uninit;
-- 
2.53.0


^ permalink raw reply related

* [PATCH net-next v3 11/13] dummy: convert to ndo_set_rx_mode_async
From: Stanislav Fomichev @ 2026-03-20  1:24 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, corbet, skhan,
	andrew+netdev, michael.chan, pavan.chebbi, anthony.l.nguyen,
	przemyslaw.kitszel, saeedm, tariqt, mbloch, alexanderduyck,
	kernel-team, johannes, sd, jianbol, dtatulea, sdf, mohsin.bashr,
	jacob.e.keller, willemb, skhawaja, bestswngs, aleksandr.loktionov,
	kees, linux-doc, linux-kernel, intel-wired-lan, linux-rdma,
	linux-wireless, linux-kselftest, leon
In-Reply-To: <20260320012501.2033548-1-sdf@fomichev.me>

Convert dummy driver from ndo_set_rx_mode to ndo_set_rx_mode_async.
The dummy driver's set_multicast_list is a no-op, so the conversion
is straightforward: update the signature and the ops assignment.

Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 drivers/net/dummy.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index d6bdad4baadd..f8a4eb365c3d 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -47,7 +47,9 @@
 static int numdummies = 1;
 
 /* fake multicast ability */
-static void set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *dev,
+			       struct netdev_hw_addr_list *uc,
+			       struct netdev_hw_addr_list *mc)
 {
 }
 
@@ -87,7 +89,7 @@ static const struct net_device_ops dummy_netdev_ops = {
 	.ndo_init		= dummy_dev_init,
 	.ndo_start_xmit		= dummy_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_set_rx_mode_async	= set_multicast_list,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_get_stats64	= dummy_get_stats64,
 	.ndo_change_carrier	= dummy_change_carrier,
-- 
2.53.0


^ permalink raw reply related

* [PATCH net-next v3 10/13] netdevsim: convert to ndo_set_rx_mode_async
From: Stanislav Fomichev @ 2026-03-20  1:24 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, corbet, skhan,
	andrew+netdev, michael.chan, pavan.chebbi, anthony.l.nguyen,
	przemyslaw.kitszel, saeedm, tariqt, mbloch, alexanderduyck,
	kernel-team, johannes, sd, jianbol, dtatulea, sdf, mohsin.bashr,
	jacob.e.keller, willemb, skhawaja, bestswngs, aleksandr.loktionov,
	kees, linux-doc, linux-kernel, intel-wired-lan, linux-rdma,
	linux-wireless, linux-kselftest, leon
In-Reply-To: <20260320012501.2033548-1-sdf@fomichev.me>

Convert netdevsim from ndo_set_rx_mode to ndo_set_rx_mode_async.
The callback is a no-op stub so just update the signature and
ops struct wiring.

Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 drivers/net/netdevsim/netdev.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 5ec028a00c62..9c9217792125 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -182,7 +182,9 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
-static void nsim_set_rx_mode(struct net_device *dev)
+static void nsim_set_rx_mode(struct net_device *dev,
+			     struct netdev_hw_addr_list *uc,
+			     struct netdev_hw_addr_list *mc)
 {
 }
 
@@ -641,7 +643,7 @@ static const struct net_shaper_ops nsim_shaper_ops = {
 
 static const struct net_device_ops nsim_netdev_ops = {
 	.ndo_start_xmit		= nsim_start_xmit,
-	.ndo_set_rx_mode	= nsim_set_rx_mode,
+	.ndo_set_rx_mode_async	= nsim_set_rx_mode,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= nsim_change_mtu,
@@ -664,7 +666,7 @@ static const struct net_device_ops nsim_netdev_ops = {
 
 static const struct net_device_ops nsim_vf_netdev_ops = {
 	.ndo_start_xmit		= nsim_start_xmit,
-	.ndo_set_rx_mode	= nsim_set_rx_mode,
+	.ndo_set_rx_mode_async	= nsim_set_rx_mode,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= nsim_change_mtu,
-- 
2.53.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox