From: Emmanuel Grumbach Keep that setting only for devices that use iwldvm. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 3 +-- drivers/net/wireless/intel/iwlwifi/cfg/7000.c | 3 +-- drivers/net/wireless/intel/iwlwifi/cfg/8000.c | 3 +-- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 3 +-- drivers/net/wireless/intel/iwlwifi/cfg/ax210.c | 3 +-- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 1 - 8 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index f0453f3f6ba6..5b2a5e254d6e 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation */ #include #include @@ -28,7 +28,6 @@ static const struct iwl_family_base_params iwl_22000_base = { .num_of_queues = 512, .max_tfd_queue_size = 256, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index f987ad3192c1..2936ccf1dbb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020, 2023, 2025 Intel Corporation + * Copyright (C) 2012-2014, 2018-2020, 2023, 2025-2026 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 Intel Deutschland GmbH */ @@ -54,7 +54,6 @@ static const struct iwl_family_base_params iwl7000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index 3c844cd419e8..3e936ba7f871 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2014, 2018-2020, 2023, 2025 Intel Corporation + * Copyright (C) 2014, 2018-2020, 2023, 2025-2026 Intel Corporation * Copyright (C) 2014-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -40,7 +40,6 @@ static const struct iwl_family_base_params iwl8000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 5872fc9b8caf..7194f681cec2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021, 2023, 2025 Intel Corporation + * Copyright (C) 2018-2021, 2023, 2025-2026 Intel Corporation */ #include #include @@ -31,7 +31,6 @@ static const struct iwl_family_base_params iwl9000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index 582f61661062..1f862748e33d 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation */ #include #include @@ -23,7 +23,6 @@ static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index c060b12cc952..7b3837b2a8e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -23,7 +23,6 @@ static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index 3ccbb21276c1..12feac3bc0a2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -24,7 +24,6 @@ static const struct iwl_family_base_params iwl_dr_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 04c726e8c283..f82ba1d64b63 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -29,7 +29,6 @@ static const struct iwl_family_base_params iwl_sc_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .shadow_ram_support = true, - .led_compensation = 57, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, -- 2.34.1 From: Emmanuel Grumbach Keep that setting only for devices that use iwldvm. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/7000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/8000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/ax210.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 5b2a5e254d6e..0ce8d6229bab 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -27,7 +27,6 @@ static const struct iwl_family_base_params iwl_22000_base = { .num_of_queues = 512, .max_tfd_queue_size = 256, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index 2936ccf1dbb2..c55995fdf1c7 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -53,7 +53,6 @@ static const struct iwl_family_base_params iwl7000_base = { .eeprom_size = OTP_LOW_IMAGE_SIZE_16K, .num_of_queues = 31, .max_tfd_queue_size = 256, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index 3e936ba7f871..182a8bf5bcf0 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -39,7 +39,6 @@ static const struct iwl_family_base_params iwl8000_base = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, .num_of_queues = 31, .max_tfd_queue_size = 256, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 7194f681cec2..55db225a02fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -30,7 +30,6 @@ static const struct iwl_family_base_params iwl9000_base = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, .num_of_queues = 31, .max_tfd_queue_size = 256, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index 1f862748e33d..b355384ee210 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -22,7 +22,6 @@ static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 7b3837b2a8e5..589bc88727a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -22,7 +22,6 @@ static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index 12feac3bc0a2..ecd48aac4e2a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -23,7 +23,6 @@ static const struct iwl_family_base_params iwl_dr_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index f82ba1d64b63..75a9a1c56dd3 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -28,7 +28,6 @@ static const struct iwl_family_base_params iwl_sc_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, - .shadow_ram_support = true, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, -- 2.34.1 From: Emmanuel Grumbach This is used to set init_evtlog_size and inst_evtlog_size in case those are not advertised by the firmware's TLVs. Those two fields are used only in iwldvm. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/7000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/8000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/ax210.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 1 - drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 0ce8d6229bab..563c596240b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -28,7 +28,6 @@ static const struct iwl_family_base_params iwl_22000_base = { .num_of_queues = 512, .max_tfd_queue_size = 256, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL_22000_SMEM_OFFSET, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index c55995fdf1c7..1be72d71fccf 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -54,7 +54,6 @@ static const struct iwl_family_base_params iwl7000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .apmg_wake_up_wa = true, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index 182a8bf5bcf0..834aa520ab0c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -40,7 +40,6 @@ static const struct iwl_family_base_params iwl8000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .nvm_hw_section_num = 10, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 55db225a02fc..2954434ce851 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -31,7 +31,6 @@ static const struct iwl_family_base_params iwl9000_base = { .num_of_queues = 31, .max_tfd_queue_size = 256, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL9000_SMEM_OFFSET, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index b355384ee210..ee24ded67069 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -23,7 +23,6 @@ static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL_AX210_SMEM_OFFSET, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 589bc88727a5..1b14ba5a09f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -23,7 +23,6 @@ static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL_BZ_SMEM_OFFSET, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index ecd48aac4e2a..afde84ad0493 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -24,7 +24,6 @@ static const struct iwl_family_base_params iwl_dr_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL_DR_SMEM_OFFSET, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 75a9a1c56dd3..52a08105d0c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -29,7 +29,6 @@ static const struct iwl_family_base_params iwl_sc_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, .shadow_reg_enable = true, .pcie_l1_allowed = true, .smem_offset = IWL_SC_SMEM_OFFSET, -- 2.34.1 From: Emmanuel Grumbach This was used for the old (pre-ini) debug mechanism which is now obsolete. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 6 ------ drivers/net/wireless/intel/iwlwifi/cfg/ax210.c | 6 ------ drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 6 ------ drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 6 ------ drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 6 ------ 5 files changed, 30 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 563c596240b2..e929a08e7585 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -15,10 +15,6 @@ /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 77 -/* Memory offsets and lengths */ -#define IWL_22000_SMEM_OFFSET 0x400000 -#define IWL_22000_SMEM_LEN 0xD0000 - #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0" #define IWL_CC_A_MODULE_FIRMWARE(api) \ @@ -30,8 +26,6 @@ static const struct iwl_family_base_params iwl_22000_base = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .shadow_reg_enable = true, .pcie_l1_allowed = true, - .smem_offset = IWL_22000_SMEM_OFFSET, - .smem_len = IWL_22000_SMEM_LEN, .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .apmg_not_supported = true, .mac_addr_from_csr = 0x380, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index ee24ded67069..ec1951a94e23 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -15,18 +15,12 @@ /* Lowest firmware API version supported */ #define IWL_AX210_UCODE_API_MIN 89 -/* Memory offsets and lengths */ -#define IWL_AX210_SMEM_OFFSET 0x400000 -#define IWL_AX210_SMEM_LEN 0xD0000 - static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, .shadow_reg_enable = true, .pcie_l1_allowed = true, - .smem_offset = IWL_AX210_SMEM_OFFSET, - .smem_len = IWL_AX210_SMEM_LEN, .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .apmg_not_supported = true, .mac_addr_from_csr = 0x380, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 1b14ba5a09f9..a70b356d9576 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -15,18 +15,12 @@ /* Lowest firmware core release supported */ #define IWL_BZ_UCODE_CORE_MIN 101 -/* Memory offsets and lengths */ -#define IWL_BZ_SMEM_OFFSET 0x400000 -#define IWL_BZ_SMEM_LEN 0xD0000 - static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, .wd_timeout = IWL_LONG_WD_TIMEOUT, .shadow_reg_enable = true, .pcie_l1_allowed = true, - .smem_offset = IWL_BZ_SMEM_OFFSET, - .smem_len = IWL_BZ_SMEM_LEN, .apmg_not_supported = true, .mac_addr_from_csr = 0x30, .d3_debug_data_base_addr = 0x401000, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index afde84ad0493..e95112fdc664 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -14,10 +14,6 @@ /* Lowest firmware core release supported */ #define IWL_DR_UCODE_CORE_MIN 101 -/* Memory offsets and lengths */ -#define IWL_DR_SMEM_OFFSET 0x400000 -#define IWL_DR_SMEM_LEN 0xD0000 - #define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0" static const struct iwl_family_base_params iwl_dr_base = { @@ -26,8 +22,6 @@ static const struct iwl_family_base_params iwl_dr_base = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .shadow_reg_enable = true, .pcie_l1_allowed = true, - .smem_offset = IWL_DR_SMEM_OFFSET, - .smem_len = IWL_DR_SMEM_LEN, .apmg_not_supported = true, .mac_addr_from_csr = 0x30, .d3_debug_data_base_addr = 0x401000, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 52a08105d0c4..d1e5cef42fff 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -15,10 +15,6 @@ /* Lowest firmware core release supported */ #define IWL_SC_UCODE_CORE_MIN 101 -/* Memory offsets and lengths */ -#define IWL_SC_SMEM_OFFSET 0x400000 -#define IWL_SC_SMEM_LEN 0xD0000 - #define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0" #define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0" #define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0" @@ -31,8 +27,6 @@ static const struct iwl_family_base_params iwl_sc_base = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .shadow_reg_enable = true, .pcie_l1_allowed = true, - .smem_offset = IWL_SC_SMEM_OFFSET, - .smem_len = IWL_SC_SMEM_LEN, .apmg_not_supported = true, .mac_addr_from_csr = 0x30, .d3_debug_data_base_addr = 0x401000, -- 2.34.1 From: Avraham Stern When a notification about a new ULW attribute arrives, send it to user space so the ULW attribute can be added to the relevant frames (e.g. SDF). Signed-off-by: Avraham Stern Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 20 +++++++++++ drivers/net/wireless/intel/iwlwifi/mld/mld.c | 1 + drivers/net/wireless/intel/iwlwifi/mld/nan.c | 33 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/nan.h | 5 +++ .../net/wireless/intel/iwlwifi/mld/notif.c | 3 ++ 5 files changed, 62 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 1df81df5830e..dde6cfd9d286 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -80,6 +80,10 @@ enum iwl_mac_conf_subcmd_ids { * @NAN_PEER_CMD: &struct iwl_nan_peer_cmd */ NAN_PEER_CMD = 0x14, + /** + * @NAN_ULW_ATTR_NOTIF: &struct iwl_nan_ulw_attr_notif + */ + NAN_ULW_ATTR_NOTIF = 0xf2, /** * @NAN_DW_END_NOTIF: &struct iwl_nan_dw_end_notif */ @@ -1393,4 +1397,20 @@ struct iwl_nan_dw_end_notif { u8 reserved[3]; } __packed; /* NAN_DW_END_NTF_API_S_VER_1 */ +#define IWL_NAN_MAX_ENDLESS_ULW_ATTR_LEN 48 + +/** + * struct iwl_nan_ulw_attr_notif - sent to notify the host of a change in the + * ULW attribute + * + * @attr_len: length of the ULW attribute in bytes + * @reserved: reserved + * @attr: the ULW attribute including the attribute header + */ +struct iwl_nan_ulw_attr_notif { + u8 attr_len; + u8 reserved[3]; + u8 attr[IWL_NAN_MAX_ENDLESS_ULW_ATTR_LEN]; +} __packed; /* NAN_ULW_ATTR_NOTIF_API_S_VER_1 */ + #endif /* __iwl_fw_api_mac_cfg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 3caa76b9b2cb..054bb1134425 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -237,6 +237,7 @@ static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = { HCMD_NAME(NAN_CFG_CMD), HCMD_NAME(NAN_SCHEDULE_CMD), HCMD_NAME(NAN_PEER_CMD), + HCMD_NAME(NAN_ULW_ATTR_NOTIF), HCMD_NAME(NAN_DW_END_NOTIF), HCMD_NAME(NAN_JOINED_CLUSTER_NOTIF), HCMD_NAME(MISSED_BEACONS_NOTIF), diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index 351c726be51f..8f35687c58b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -353,6 +353,39 @@ bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld, return true; } +bool iwl_mld_cancel_nan_ulw_attr_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt, + u32 obj_id) +{ + return true; +} + +void iwl_mld_handle_nan_ulw_attr_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt) +{ + struct iwl_nan_ulw_attr_notif *notif = (void *)pkt->data; + struct wireless_dev *wdev; + + IWL_DEBUG_INFO(mld, "NAN: ULW attr update: len=%u\n", notif->attr_len); + + if (IWL_FW_CHECK(mld, !mld->nan_device_vif, + "NAN: ULW attr update without NAN vif\n")) + return; + + if (IWL_FW_CHECK(mld, !ieee80211_vif_nan_started(mld->nan_device_vif), + "NAN: ULW attr update without NAN started\n")) + return; + + if (IWL_FW_CHECK(mld, + notif->attr_len > IWL_NAN_MAX_ENDLESS_ULW_ATTR_LEN, + "NAN: ULW attr update invalid len %u\n", + notif->attr_len)) + return; + + wdev = ieee80211_vif_to_wdev(mld->nan_device_vif); + cfg80211_nan_ulw_update(wdev, notif->attr, notif->attr_len, GFP_KERNEL); +} + void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.h b/drivers/net/wireless/intel/iwlwifi/mld/nan.h index caa98dbb4a75..40152dc7d906 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.h @@ -38,11 +38,16 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mld_handle_nan_cluster_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt); +void iwl_mld_handle_nan_ulw_attr_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt); void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt); bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt, u32 obj_id); +bool iwl_mld_cancel_nan_ulw_attr_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt, + u32 obj_id); bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt, u32 obj_id); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index 14834395de3a..75adc9651736 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -346,6 +346,7 @@ CMD_VERSIONS(time_sync_confirm_notif, CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy)) CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif)) CMD_VERSIONS(nan_cluster_notif, CMD_VER_ENTRY(1, iwl_nan_cluster_notif)) +CMD_VERSIONS(nan_ulw_attr_notif, CMD_VER_ENTRY(1, iwl_nan_ulw_attr_notif)) CMD_VERSIONS(nan_dw_end_notif, CMD_VER_ENTRY(1, iwl_nan_dw_end_notif)) DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id) @@ -463,6 +464,8 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = { ftm_resp_notif) RX_HANDLER_OF_NAN(MAC_CONF_GROUP, NAN_JOINED_CLUSTER_NOTIF, nan_cluster_notif) + RX_HANDLER_OF_NAN(MAC_CONF_GROUP, NAN_ULW_ATTR_NOTIF, + nan_ulw_attr_notif) RX_HANDLER_OF_NAN(MAC_CONF_GROUP, NAN_DW_END_NOTIF, nan_dw_end_notif) }; -- 2.34.1 From: Johannes Berg UHR devices have NPCA capability, so implement the necessary configuration and set the capability bit. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 4 +- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 3 ++ drivers/net/wireless/intel/iwlwifi/mld/link.c | 15 +++++++ .../net/wireless/intel/iwlwifi/mld/mac80211.c | 39 ++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mld/phy.c | 24 ++++++++++-- 5 files changed, 80 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index dde6cfd9d286..fa2fc6a92e60 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -549,12 +549,14 @@ enum iwl_link_ctx_protection_flags { * radar pulses). * @LINK_FLG_NDP_FEEDBACK_ENABLED: mark support for NDP feedback and change * of threshold + * @LINK_FLG_NPCA: NPCA enabled */ enum iwl_link_ctx_flags { LINK_FLG_BSS_COLOR_DIS = BIT(0), LINK_FLG_MU_EDCA_CW = BIT(1), LINK_FLG_RU_2MHZ_BLOCK = BIT(2), LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3), + LINK_FLG_NPCA = BIT(4), }; /* LINK_CONTEXT_FLAG_E_VER_1 */ /** @@ -591,7 +593,7 @@ enum iwl_npca_flags { * @initial_qsrc: Indicates the value that is used to initialize the * EDCAF QSRC[AC] variables * @min_dur_threshold: minimum PPDU time to switch to the non-primary - * NPCA channel (usec) + * NPCA channel (spec representation) * @flags: NPCA flags, see &enum iwl_npca_flags * @reserved: reserved for alignment purposes */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 38ff6f944add..4e8222ffe732 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -695,6 +695,9 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { .has_uhr = true, .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX | IEEE80211_UHR_PHY_CAP_ELR_TX, + .mac.mac_cap = { + [0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP, + }, }, }, { diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 805f2e2eac38..9ef39b03e67f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -374,6 +374,21 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link, if (WARN_ON(changes & LINK_CONTEXT_MODIFY_EHT_PARAMS)) changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS; + if (link->uhr_support && link->npca.enabled) { + flags |= LINK_FLG_NPCA; + if (link->npca.moplen) + cmd.npca_params.flags |= IWL_NPCA_FLAG_MAC_HDR_BASED; + cmd.npca_params.dis_subch_bmap = + cpu_to_le16(link->chanreq.oper.npca_punctured); + cmd.npca_params.initial_qsrc = link->npca.init_qsrc; + cmd.npca_params.min_dur_threshold = link->npca.min_dur_thresh; + /* spec/mac80211 have these in units of 4 usec */ + cmd.npca_params.switch_delay = + 4 * link->npca.switch_delay; + cmd.npca_params.switch_back_delay = + 4 * link->npca.switch_back_delay; + } + send_cmd: cmd.modify_mask = cpu_to_le32(changes); cmd.flags = cpu_to_le32(flags); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 41bc47e4e00c..1f2843af39c1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -981,6 +981,30 @@ void iwl_mld_remove_chanctx(struct ieee80211_hw *hw, mld->used_phy_ids &= ~BIT(phy->fw_id); } +static void +iwl_mld_update_link_npca_puncturing(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) +{ + struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); + struct ieee80211_vif *vif; + + for_each_active_interface(vif, hw) { + struct ieee80211_bss_conf *link; + int link_id; + + for_each_vif_active_link(vif, link, link_id) { + if (rcu_access_pointer(link->chanctx_conf) != ctx) + continue; + + if (!link->npca.enabled) + continue; + + iwl_mld_change_link_in_fw(mld, link, + LINK_CONTEXT_MODIFY_UHR_PARAMS); + } + } +} + static void iwl_mld_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) @@ -996,9 +1020,19 @@ void iwl_mld_change_chanctx(struct ieee80211_hw *hw, IEEE80211_CHANCTX_CHANGE_CHANNEL))) return; + /* NPCA puncturing is in link API for FW */ + if (changed & IEEE80211_CHANCTX_CHANGE_NPCA_PUNCT) { + iwl_mld_update_link_npca_puncturing(hw, ctx); + changed &= ~IEEE80211_CHANCTX_CHANGE_NPCA_PUNCT; + } + /* Check if a FW update is required */ - if (changed & IEEE80211_CHANCTX_CHANGE_AP) + if (!changed) + return; + + if (changed & IEEE80211_CHANCTX_CHANGE_AP || + changed & IEEE80211_CHANCTX_CHANGE_NPCA) goto update; if (chandef->chan == phy->chandef.chan && @@ -1255,6 +1289,9 @@ u32 iwl_mld_link_changed_mapping(struct iwl_mld *mld, link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS; } + if (changes & BSS_CHANGED_NPCA) + link_changes |= LINK_CONTEXT_MODIFY_UHR_PARAMS; + return link_changes; } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.c b/drivers/net/wireless/intel/iwlwifi/mld/phy.c index 1d93fb9e4dbf..59bf088ead84 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/phy.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include @@ -99,9 +99,9 @@ iwl_mld_nl80211_width_to_fw(enum nl80211_chan_width width) /* Maps the driver specific control channel position (relative to the center * freq) definitions to the fw values */ -u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef) +static u8 _iwl_mld_get_fw_ctrl_pos(u32 control, u32 cf1) { - int offs = chandef->chan->center_freq - chandef->center_freq1; + int offs = control - cf1; int abs_offs = abs(offs); u8 ret; @@ -127,6 +127,12 @@ u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef) return ret; } +u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef) +{ + return _iwl_mld_get_fw_ctrl_pos(chandef->chan->center_freq, + chandef->center_freq1); +} + int iwl_mld_phy_fw_action(struct iwl_mld *mld, struct ieee80211_chanctx_conf *ctx, u32 action) { @@ -150,6 +156,18 @@ int iwl_mld_phy_fw_action(struct iwl_mld *mld, cmd.sbb_ctrl_channel_loc = iwl_mld_get_fw_ctrl_pos(&ctx->ap); } + /* + * Set NPCA channel if NPCA is used; if not used, just set it to an + * arbitrary channel on the other side to help firmware. + */ + if (chandef->npca_chan) + cmd.secondary_ctrl_chnl_loc = + _iwl_mld_get_fw_ctrl_pos(chandef->npca_chan->center_freq, + chandef->center_freq1); + else + cmd.secondary_ctrl_chnl_loc = + cmd.ci.ctrl_pos ^ IWL_PHY_CTRL_POS_ABOVE; + ret = iwl_mld_send_cmd_pdu(mld, PHY_CONTEXT_CMD, &cmd); if (ret) IWL_ERR(mld, "Failed to send PHY_CONTEXT_CMD ret = %d\n", ret); -- 2.34.1 From: Johannes Berg For UHR, implement dynamic power save (DPS). Since the firmware handles most of it, simply advertise DPS capability and set the corresponding link flag when the AP has advertised that it is a DPS assisting AP. DPS assisting is currently not supported. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 2 ++ drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 3 ++- drivers/net/wireless/intel/iwlwifi/mld/link.c | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index fa2fc6a92e60..604281eb29c7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -550,6 +550,7 @@ enum iwl_link_ctx_protection_flags { * @LINK_FLG_NDP_FEEDBACK_ENABLED: mark support for NDP feedback and change * of threshold * @LINK_FLG_NPCA: NPCA enabled + * @LINK_FLG_DPS: AP is a DPS assisting AP */ enum iwl_link_ctx_flags { LINK_FLG_BSS_COLOR_DIS = BIT(0), @@ -557,6 +558,7 @@ enum iwl_link_ctx_flags { LINK_FLG_RU_2MHZ_BLOCK = BIT(2), LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3), LINK_FLG_NPCA = BIT(4), + LINK_FLG_DPS = BIT(6), }; /* LINK_CONTEXT_FLAG_E_VER_1 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 4e8222ffe732..f29de029c709 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -696,7 +696,8 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { .phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX | IEEE80211_UHR_PHY_CAP_ELR_TX, .mac.mac_cap = { - [0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP, + [0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP | + IEEE80211_UHR_MAC_CAP0_DPS_SUPP, }, }, }, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 9ef39b03e67f..785459937fbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -335,10 +335,18 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link, link_sta_dereference_check(mld_vif->ap_sta, link->link_id); - if (!WARN_ON(!link_sta) && link_sta->he_cap.has_he && + if (WARN_ON(!link_sta)) + return -EINVAL; + + if (link_sta->he_cap.has_he && link_sta->he_cap.he_cap_elem.mac_cap_info[5] & IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX) cmd.ul_mu_data_disable = 1; + + if (link_sta->uhr_cap.has_uhr && + link_sta->uhr_cap.mac.mac_cap[0] & + IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP) + flags |= LINK_FLG_DPS; } cmd.htc_trig_based_pkt_ext = link->htc_trig_based_pkt_ext; -- 2.34.1 From: Johannes Berg The generated data structures and function names used are just the debugfs filename, which is a shared namespace and could lead to confusion. Prefix these with "link_sta_" to disambiguate. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/mld/debugfs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index 9ec8ddce0c38..ba5a47519aa1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -1049,20 +1049,22 @@ static ssize_t _iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf, return ret ? : count; } -static ssize_t iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf, - size_t count, void *data) +static ssize_t +iwl_dbgfs_link_sta_fixed_rate_write(struct iwl_mld *mld, char *buf, + size_t count, void *data) { return _iwl_dbgfs_fixed_rate_write(mld, buf, count, data, false); } -static ssize_t iwl_dbgfs_fixed_rate_v3_write(struct iwl_mld *mld, char *buf, - size_t count, void *data) +static ssize_t +iwl_dbgfs_link_sta_fixed_rate_v3_write(struct iwl_mld *mld, char *buf, + size_t count, void *data) { return _iwl_dbgfs_fixed_rate_write(mld, buf, count, data, true); } -static ssize_t iwl_dbgfs_tlc_dhc_write(struct iwl_mld *mld, char *buf, - size_t count, void *data) +static ssize_t iwl_dbgfs_link_sta_tlc_dhc_write(struct iwl_mld *mld, char *buf, + size_t count, void *data) { struct ieee80211_link_sta *link_sta = data; struct iwl_mld_link_sta *mld_link_sta; @@ -1091,12 +1093,12 @@ static ssize_t iwl_dbgfs_tlc_dhc_write(struct iwl_mld *mld, char *buf, #define LINK_STA_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) \ debugfs_create_file(alias, mode, parent, link_sta, \ - &iwl_dbgfs_##name##_ops) + &iwl_dbgfs_link_sta_##name##_ops) #define LINK_STA_DEBUGFS_ADD_FILE(name, parent, mode) \ LINK_STA_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) #define LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(name, bufsz) \ - WIPHY_DEBUGFS_WRITE_FILE_OPS(name, bufsz, link_sta) + WIPHY_DEBUGFS_WRITE_FILE_OPS(link_sta_##name, bufsz, link_sta) LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(tlc_dhc, 64); LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(fixed_rate, 64); -- 2.34.1 From: Avinash Bhatt APs operating in PSD mode increase transmit power with bandwidth, requiring RSSI compensation for accurate link grading. Parse TPE elements to determine power mode and apply RSSI adjustment based on operational bandwidth and power constraints. Signed-off-by: Avinash Bhatt Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/link.c | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 785459937fbe..70965627e2dd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -972,6 +972,145 @@ iwl_mld_get_dup_beacon_rssi_adjust(struct iwl_mld *mld, } } +static s8 iwl_mld_get_primary_psd(const struct ieee80211_parsed_tpe_psd *psd, + const struct cfg80211_chan_def *chandef, + int bw_mhz) +{ + int start_freq, primary_idx; + + if (!psd->valid) + return S8_MAX; + + start_freq = chandef->center_freq1 - (bw_mhz / 2); + primary_idx = (chandef->chan->center_freq - start_freq - 10) / 20; + + if (primary_idx < 0 || primary_idx >= psd->count) + return S8_MAX; + + /* TPE element stores PSD limit as value * 2 */ + return psd->power[primary_idx] / 2; +} + +static s8 iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf) +{ + const struct ieee80211_parsed_tpe *tpe = &link_conf->tpe; + s8 psd_20mhz, psd_oper, psd_local, psd_reg, psd_boost; + s8 min_20mhz, min_oper, adjustment, ap_power_limit; + s8 psd_avg_local = S8_MAX, psd_avg_reg = S8_MAX; + s8 eirp_20mhz, eirp_oper, eirp_local, eirp_reg; + int bw_mhz, num_subchans; + u8 bw_index; + + /* PSD/EIRP adjustment is only specific to 6 GHz */ + if (WARN_ONCE(link_conf->chanreq.oper.chan->band != NL80211_BAND_6GHZ, + "PSD/EIRP adjustment called for non-6 GHz band %d\n", + link_conf->chanreq.oper.chan->band)) + return 0; + + bw_mhz = nl80211_chan_width_to_mhz(link_conf->chanreq.oper.width); + + switch (bw_mhz) { + case 20: + bw_index = 0; + break; + case 40: + bw_index = 1; + break; + case 80: + bw_index = 2; + break; + case 160: + bw_index = 3; + break; + case 320: + bw_index = 4; + break; + default: + WARN_ONCE(1, "Unexpected bandwidth: %d MHz\n", bw_mhz); + return 0; + } + + if (link_conf->power_type == IEEE80211_REG_VLP_AP) + ap_power_limit = 14; + else + ap_power_limit = 23; + + /* Primary 20 MHz PSD */ + psd_local = iwl_mld_get_primary_psd(&tpe->psd_local[0], + &link_conf->chanreq.oper, + bw_mhz); + psd_reg = iwl_mld_get_primary_psd(&tpe->psd_reg_client[0], + &link_conf->chanreq.oper, + bw_mhz); + psd_20mhz = min(psd_local, psd_reg); + + /* TPE element stores EIRP limit as value * 2 */ + eirp_local = (tpe->max_local[0].valid && tpe->max_local[0].count > 0) ? + tpe->max_local[0].power[0] / 2 : S8_MAX; + eirp_reg = (tpe->max_reg_client[0].valid && + tpe->max_reg_client[0].count > 0) ? + tpe->max_reg_client[0].power[0] / 2 : S8_MAX; + eirp_20mhz = min(eirp_local, eirp_reg); + + num_subchans = bw_mhz / 20; + + if (tpe->psd_local[0].valid) { + int sum_local = 0, valid_local = 0; + int count_local = min(num_subchans, tpe->psd_local[0].count); + + for (int i = 0; i < count_local; i++) { + if (tpe->psd_local[0].power[i] != S8_MIN) { + sum_local += tpe->psd_local[0].power[i]; + valid_local++; + } + } + /* TPE element stores PSD limit as value * 2 */ + if (valid_local > 0) + psd_avg_local = sum_local / valid_local / 2; + } + + if (tpe->psd_reg_client[0].valid) { + int sum_reg = 0, valid_reg = 0; + int count_reg = min(num_subchans, tpe->psd_reg_client[0].count); + + for (int i = 0; i < count_reg; i++) { + if (tpe->psd_reg_client[0].power[i] != S8_MIN) { + sum_reg += + tpe->psd_reg_client[0].power[i]; + valid_reg++; + } + } + /* TPE element stores PSD limit as value * 2 */ + if (valid_reg > 0) + psd_avg_reg = sum_reg / valid_reg / 2; + } + + psd_oper = min(psd_avg_local, psd_avg_reg); + + /* TPE element stores EIRP limit as value * 2 */ + eirp_local = (tpe->max_local[0].valid && + tpe->max_local[0].count > bw_index) ? + tpe->max_local[0].power[bw_index] / 2 : S8_MAX; + eirp_reg = (tpe->max_reg_client[0].valid && + tpe->max_reg_client[0].count > bw_index) ? + tpe->max_reg_client[0].power[bw_index] / 2 : S8_MAX; + eirp_oper = min(eirp_local, eirp_reg); + + min_20mhz = min(ap_power_limit, min(eirp_20mhz, psd_20mhz)); + + /* PSD boost: 10*log10(BW/20) approximated as 3*ilog2(BW/20) */ + psd_boost = 3 * ilog2(bw_mhz / 20); + + /* Use int for psd_oper + psd_boost to prevent s8 overflow */ + min_oper = min(ap_power_limit, + min(eirp_oper, + (s8)min_t(int, psd_oper + psd_boost, S8_MAX))); + + adjustment = max(min_oper - min_20mhz, 0); + + return adjustment; +} + /* This function calculates the grade of a link. Returns 0 in error case */ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, struct ieee80211_bss_conf *link_conf) @@ -1000,6 +1139,10 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, s8 rssi_adj_6g = iwl_mld_get_dup_beacon_rssi_adjust(mld, link_conf); + if (!rssi_adj_6g) + rssi_adj_6g = + iwl_mld_get_psd_eirp_rssi_adjust(link_conf); + if (!rssi_adj_6g) rssi_adj_6g = 4; -- 2.34.1 From: Avinash Bhatt Replace single RSSI-to-grade table with separate tables for each operational bandwidth. Grade selection now depends on both RSSI and the link's operational bandwidth. Improve puncturing penalty calculation to apply proportional reduction based on unusable spectrum percentage rather than absolute channel count. Update existing KUnit tests with RSSI values for new grading tables. Signed-off-by: Avinash Bhatt Tested-by: Miriam Rachel Korenblit Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/link.c | 228 ++++++++++++++---- .../intel/iwlwifi/mld/tests/link-selection.c | 6 +- 2 files changed, 183 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 70965627e2dd..3c1825ba2b86 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -696,35 +696,131 @@ struct iwl_mld_rssi_to_grade { u16 grade; }; -#define RSSI_TO_GRADE_LINE(_lb, _hb_uhb, _grade) \ +#define RSSI_TO_GRADE_LINE_WITH_LB(_lb, _hb_uhb, _grade) \ { \ .rssi = {_lb, _hb_uhb}, \ .grade = _grade \ } -/* - * This array must be sorted by increasing RSSI for proper functionality. - * The grades are actually estimated throughput, represented as fixed-point - * with a scale factor of 1/10. - */ -static const struct iwl_mld_rssi_to_grade rssi_to_grade_map[] = { - RSSI_TO_GRADE_LINE(-85, -89, 172), - RSSI_TO_GRADE_LINE(-83, -86, 344), - RSSI_TO_GRADE_LINE(-82, -85, 516), - RSSI_TO_GRADE_LINE(-80, -83, 688), - RSSI_TO_GRADE_LINE(-77, -79, 1032), - RSSI_TO_GRADE_LINE(-73, -76, 1376), - RSSI_TO_GRADE_LINE(-70, -74, 1548), - RSSI_TO_GRADE_LINE(-69, -72, 1720), - RSSI_TO_GRADE_LINE(-65, -68, 2064), - RSSI_TO_GRADE_LINE(-61, -66, 2294), - RSSI_TO_GRADE_LINE(-58, -61, 2580), - RSSI_TO_GRADE_LINE(-55, -58, 2868), - RSSI_TO_GRADE_LINE(-46, -55, 3098), - RSSI_TO_GRADE_LINE(-43, -54, 3442) +#define RSSI_TO_GRADE_LINE(_rssi, _grade) \ + RSSI_TO_GRADE_LINE_WITH_LB(_rssi, _rssi, _grade) + +/* Tables must be sorted by increasing RSSI */ + +/* 20 MHz Operational BW Grading Table */ +static const struct iwl_mld_rssi_to_grade rssi_to_grade_20mhz[] = { + RSSI_TO_GRADE_LINE_WITH_LB(-94, -95, 9), + RSSI_TO_GRADE_LINE_WITH_LB(-92, -93, 17), + RSSI_TO_GRADE_LINE_WITH_LB(-90, -90, 34), + RSSI_TO_GRADE_LINE_WITH_LB(-87, -87, 52), + RSSI_TO_GRADE_LINE_WITH_LB(-83, -84, 69), + RSSI_TO_GRADE_LINE_WITH_LB(-79, -80, 103), + RSSI_TO_GRADE_LINE_WITH_LB(-75, -75, 137), + RSSI_TO_GRADE_LINE_WITH_LB(-72, -73, 155), + RSSI_TO_GRADE_LINE_WITH_LB(-70, -71, 172), + RSSI_TO_GRADE_LINE_WITH_LB(-67, -68, 206), + RSSI_TO_GRADE_LINE_WITH_LB(-64, -65, 230), + RSSI_TO_GRADE_LINE_WITH_LB(-59, -60, 258), + RSSI_TO_GRADE_LINE_WITH_LB(-57, -58, 287), + RSSI_TO_GRADE_LINE_WITH_LB(-52, -53, 310), + RSSI_TO_GRADE_LINE_WITH_LB(-50, -50, 345), }; -#define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade) +/* 40 MHz Operational BW Grading Table */ +static const struct iwl_mld_rssi_to_grade rssi_to_grade_40mhz[] = { + RSSI_TO_GRADE_LINE_WITH_LB(-95, -95, 9), + RSSI_TO_GRADE_LINE_WITH_LB(-93, -93, 17), + RSSI_TO_GRADE_LINE_WITH_LB(-91, -92, 18), + RSSI_TO_GRADE_LINE_WITH_LB(-89, -90, 34), + RSSI_TO_GRADE_LINE_WITH_LB(-87, -87, 68), + RSSI_TO_GRADE_LINE_WITH_LB(-84, -84, 104), + RSSI_TO_GRADE_LINE_WITH_LB(-80, -81, 138), + RSSI_TO_GRADE_LINE_WITH_LB(-77, -77, 206), + RSSI_TO_GRADE_LINE_WITH_LB(-72, -72, 274), + RSSI_TO_GRADE_LINE_WITH_LB(-69, -70, 310), + RSSI_TO_GRADE_LINE_WITH_LB(-67, -68, 344), + RSSI_TO_GRADE_LINE_WITH_LB(-64, -65, 412), + RSSI_TO_GRADE_LINE_WITH_LB(-61, -62, 460), + RSSI_TO_GRADE_LINE_WITH_LB(-56, -57, 516), + RSSI_TO_GRADE_LINE_WITH_LB(-54, -55, 574), + RSSI_TO_GRADE_LINE_WITH_LB(-49, -50, 620), + RSSI_TO_GRADE_LINE_WITH_LB(-46, -47, 690), +}; + +/* 80 MHz Operational BW Grading Table */ +static const struct iwl_mld_rssi_to_grade rssi_to_grade_80mhz[] = { + RSSI_TO_GRADE_LINE(-95, 9), + RSSI_TO_GRADE_LINE(-93, 17), + RSSI_TO_GRADE_LINE(-92, 18), + RSSI_TO_GRADE_LINE(-90, 34), + RSSI_TO_GRADE_LINE(-89, 36), + RSSI_TO_GRADE_LINE(-87, 68), + RSSI_TO_GRADE_LINE(-83, 136), + RSSI_TO_GRADE_LINE(-80, 208), + RSSI_TO_GRADE_LINE(-77, 276), + RSSI_TO_GRADE_LINE(-74, 412), + RSSI_TO_GRADE_LINE(-69, 548), + RSSI_TO_GRADE_LINE(-67, 620), + RSSI_TO_GRADE_LINE(-66, 688), + RSSI_TO_GRADE_LINE(-61, 824), + RSSI_TO_GRADE_LINE(-59, 920), + RSSI_TO_GRADE_LINE(-54, 1032), + RSSI_TO_GRADE_LINE(-52, 1148), + RSSI_TO_GRADE_LINE(-47, 1240), + RSSI_TO_GRADE_LINE(-44, 1380), +}; + +/* 160 MHz Operational BW Grading Table */ +static const struct iwl_mld_rssi_to_grade rssi_to_grade_160mhz[] = { + RSSI_TO_GRADE_LINE(-95, 9), + RSSI_TO_GRADE_LINE(-93, 17), + RSSI_TO_GRADE_LINE(-92, 18), + RSSI_TO_GRADE_LINE(-90, 34), + RSSI_TO_GRADE_LINE(-89, 36), + RSSI_TO_GRADE_LINE(-87, 68), + RSSI_TO_GRADE_LINE(-86, 72), + RSSI_TO_GRADE_LINE(-84, 136), + RSSI_TO_GRADE_LINE(-81, 272), + RSSI_TO_GRADE_LINE(-78, 416), + RSSI_TO_GRADE_LINE(-75, 552), + RSSI_TO_GRADE_LINE(-71, 824), + RSSI_TO_GRADE_LINE(-67, 1096), + RSSI_TO_GRADE_LINE(-65, 1240), + RSSI_TO_GRADE_LINE(-63, 1376), + RSSI_TO_GRADE_LINE(-59, 1648), + RSSI_TO_GRADE_LINE(-57, 1840), + RSSI_TO_GRADE_LINE(-52, 2064), + RSSI_TO_GRADE_LINE(-50, 2296), + RSSI_TO_GRADE_LINE(-46, 2480), + RSSI_TO_GRADE_LINE(-42, 2760), +}; + +/* 320 MHz Operational BW Grading Table */ +static const struct iwl_mld_rssi_to_grade rssi_to_grade_320mhz[] = { + RSSI_TO_GRADE_LINE(-95, 9), + RSSI_TO_GRADE_LINE(-93, 17), + RSSI_TO_GRADE_LINE(-92, 18), + RSSI_TO_GRADE_LINE(-90, 34), + RSSI_TO_GRADE_LINE(-89, 36), + RSSI_TO_GRADE_LINE(-87, 68), + RSSI_TO_GRADE_LINE(-86, 72), + RSSI_TO_GRADE_LINE(-84, 136), + RSSI_TO_GRADE_LINE(-83, 144), + RSSI_TO_GRADE_LINE(-81, 272), + RSSI_TO_GRADE_LINE(-78, 544), + RSSI_TO_GRADE_LINE(-75, 832), + RSSI_TO_GRADE_LINE(-72, 1104), + RSSI_TO_GRADE_LINE(-69, 1648), + RSSI_TO_GRADE_LINE(-64, 2192), + RSSI_TO_GRADE_LINE(-62, 2480), + RSSI_TO_GRADE_LINE(-61, 2752), + RSSI_TO_GRADE_LINE(-57, 3296), + RSSI_TO_GRADE_LINE(-55, 3680), + RSSI_TO_GRADE_LINE(-50, 4128), + RSSI_TO_GRADE_LINE(-47, 4592), + RSSI_TO_GRADE_LINE(-43, 4960), + RSSI_TO_GRADE_LINE(-40, 5520), +}; #define DEFAULT_CHAN_LOAD_2GHZ 30 #define DEFAULT_CHAN_LOAD_5GHZ 15 @@ -734,26 +830,23 @@ static const struct iwl_mld_rssi_to_grade rssi_to_grade_map[] = { #define SCALE_FACTOR 256 #define MAX_CHAN_LOAD 256 -static unsigned int -iwl_mld_get_n_subchannels(const struct ieee80211_bss_conf *link_conf) +static void +iwl_mld_apply_puncturing_penalty(const struct ieee80211_bss_conf *link_conf, + unsigned int *grade, int bw_mhz) { - enum nl80211_chan_width chan_width = - link_conf->chanreq.oper.width; - int mhz = nl80211_chan_width_to_mhz(chan_width); - unsigned int n_subchannels; + unsigned int n_punctured, n_subchannels; - if (WARN_ONCE(mhz < 20 || mhz > 320, - "Invalid channel width : (%d)\n", mhz)) - return 1; + /* Puncturing only applicable for BW >= 80 MHz */ + if (bw_mhz < 80) + return; - /* total number of subchannels */ - n_subchannels = mhz / 20; + n_punctured = hweight16(link_conf->chanreq.oper.punctured); + if (n_punctured == 0) + return; - /* No puncturing if less than 80 MHz */ - if (mhz >= 80) - n_subchannels -= hweight16(link_conf->chanreq.oper.punctured); + n_subchannels = bw_mhz / 20; - return n_subchannels; + *grade = *grade * (n_subchannels - n_punctured) / n_subchannels; } static int @@ -1115,14 +1208,19 @@ static s8 iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf) unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, struct ieee80211_bss_conf *link_conf) { + const struct iwl_mld_rssi_to_grade *grade_table; enum nl80211_band band; - int rssi_idx; + int rssi_idx, table_size, bw_mhz; s32 link_rssi; - unsigned int grade = MAX_GRADE; + unsigned int grade; if (WARN_ON_ONCE(!link_conf || !link_conf->bss)) return 0; + bw_mhz = nl80211_chan_width_to_mhz(link_conf->chanreq.oper.width); + if (bw_mhz < 0) + return 0; + band = link_conf->chanreq.oper.chan->band; if (WARN_ONCE(band != NL80211_BAND_2GHZ && band != NL80211_BAND_5GHZ && @@ -1149,22 +1247,50 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, link_rssi += rssi_adj_6g; } + /* Select grading table based on operational bandwidth */ + switch (bw_mhz) { + case 20: + grade_table = rssi_to_grade_20mhz; + table_size = ARRAY_SIZE(rssi_to_grade_20mhz); + break; + case 40: + grade_table = rssi_to_grade_40mhz; + table_size = ARRAY_SIZE(rssi_to_grade_40mhz); + break; + case 80: + grade_table = rssi_to_grade_80mhz; + table_size = ARRAY_SIZE(rssi_to_grade_80mhz); + break; + case 160: + grade_table = rssi_to_grade_160mhz; + table_size = ARRAY_SIZE(rssi_to_grade_160mhz); + break; + case 320: + grade_table = rssi_to_grade_320mhz; + table_size = ARRAY_SIZE(rssi_to_grade_320mhz); + break; + default: + WARN_ONCE(1, "Invalid bandwidth: %d MHz\n", bw_mhz); + return 0; + } + + /* Initialize grade to maximum value from selected table */ + grade = grade_table[table_size - 1].grade; + rssi_idx = band == NL80211_BAND_2GHZ ? 0 : 1; - /* No valid RSSI - take the lowest grade */ + /* No valid RSSI - take the lowest grade from selected table */ if (!link_rssi) - link_rssi = rssi_to_grade_map[0].rssi[rssi_idx]; + link_rssi = grade_table[0].rssi[rssi_idx]; IWL_DEBUG_EHT(mld, - "Calculating grade of link %d: band = %d, bandwidth = %d, punctured subchannels =0x%x RSSI = %d\n", - link_conf->link_id, band, - link_conf->chanreq.oper.width, + "Calculating grade of link %d: band = %d, BW = %d, punct subchannels = 0x%x RSSI = %d\n", + link_conf->link_id, band, bw_mhz, link_conf->chanreq.oper.punctured, link_rssi); - /* Get grade based on RSSI */ - for (int i = 0; i < ARRAY_SIZE(rssi_to_grade_map); i++) { - const struct iwl_mld_rssi_to_grade *line = - &rssi_to_grade_map[i]; + /* Get grade based on RSSI from the bandwidth-specific table */ + for (int i = 0; i < table_size; i++) { + const struct iwl_mld_rssi_to_grade *line = &grade_table[i]; if (link_rssi > line->rssi[rssi_idx]) continue; @@ -1173,8 +1299,10 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, } /* Apply the channel load and puncturing factors */ - grade = grade * iwl_mld_get_avail_chan_load(mld, link_conf) / SCALE_FACTOR; - grade = grade * iwl_mld_get_n_subchannels(link_conf); + grade = grade * iwl_mld_get_avail_chan_load(mld, link_conf) / + SCALE_FACTOR; + + iwl_mld_apply_puncturing_penalty(link_conf, &grade, bw_mhz); IWL_DEBUG_EHT(mld, "Link %d's grade: %d\n", link_conf->link_id, grade); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c index 766c24db3613..69d222a8194c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c @@ -2,7 +2,7 @@ /* * KUnit tests for link selection functions * - * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2025-2026 Intel Corporation */ #include @@ -34,6 +34,7 @@ static const struct link_grading_test_case { .link_id = 0, .chandef = &chandef_2ghz_20mhz, .active = false, + .signal = -70, .has_chan_util_elem = true, .chan_util = 128, }, @@ -45,6 +46,7 @@ static const struct link_grading_test_case { .link_id = 0, .chandef = &chandef_2ghz_20mhz, .active = false, + .signal = -70, .has_chan_util_elem = true, .chan_util = 180, }, @@ -55,6 +57,7 @@ static const struct link_grading_test_case { .input.link = { .link_id = 0, .chandef = &chandef_2ghz_20mhz, + .signal = -70, .has_chan_util_elem = true, .chan_util = 180, .active = true, @@ -67,6 +70,7 @@ static const struct link_grading_test_case { .input.link = { .link_id = 0, .chandef = &chandef_2ghz_20mhz, + .signal = -70, .active = true, }, .expected_grade = 120, -- 2.34.1 Start supporting Core 104 FW on these devices. Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index a70b356d9576..51d7c599e998 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation */ #include #include @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_BZ_UCODE_CORE_MAX 103 +#define IWL_BZ_UCODE_CORE_MAX 104 /* Lowest firmware core release supported */ #define IWL_BZ_UCODE_CORE_MIN 101 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index e95112fdc664..76fbc120a092 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include #include @@ -9,7 +9,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_DR_UCODE_CORE_MAX 103 +#define IWL_DR_UCODE_CORE_MAX 104 /* Lowest firmware core release supported */ #define IWL_DR_UCODE_CORE_MIN 101 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index d1e5cef42fff..db7858b2cb74 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation */ #include #include @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_SC_UCODE_CORE_MAX 103 +#define IWL_SC_UCODE_CORE_MAX 104 /* Lowest firmware core release supported */ #define IWL_SC_UCODE_CORE_MIN 101 -- 2.34.1 A firmware API of a mix and match (MAC + RF) is the lower one of the two. But the MODULE_FIRMWARE of QU/QUZ/SO/MA/TY with GF/HR, was defined using the max API of GF/HR, which is 100, instead of the max API of QU/QUZ/SO/MA/TY, which are API 77/89. Therefore, the wrong firmware files were published in the modinfo, leading to missing firmware files. Fix this by using the right API when declaring MODULE_FIRMWARE. While at it, add a IWL_FW_AND_PNVM entry for SO and GF4, that was missing. Fixes: db35444d557f ("wifi: iwlwifi: assign a FW API range for HR") Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 12 ++++++++ .../net/wireless/intel/iwlwifi/cfg/ax210.c | 29 +++++++++++++++++++ .../net/wireless/intel/iwlwifi/cfg/rf-gf.c | 13 --------- .../net/wireless/intel/iwlwifi/cfg/rf-hr.c | 24 --------------- 4 files changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index e929a08e7585..01ca65eb5acd 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -16,9 +16,18 @@ #define IWL_22000_UCODE_API_MIN 77 #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0" +#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" +#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0" +#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" #define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \ + IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_family_base_params iwl_22000_base = { .num_of_queues = 512, @@ -104,4 +113,7 @@ const char iwl_ax201_killer_1650s_name[] = const char iwl_ax201_killer_1650i_name[] = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)"; +MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index ec1951a94e23..2519f577669e 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -15,6 +15,24 @@ /* Lowest firmware API version supported */ #define IWL_AX210_UCODE_API_MIN 89 +#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" +#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" +#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" +#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" +#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" +#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" +#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" +#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" +#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" +#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" + +#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_HR_B_MODULE_FIRMWARE(api) \ + IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" + static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -112,3 +130,14 @@ const struct iwl_mac_cfg iwl_ma_mac_cfg = { .integrated = true, .umac_prph_offset = 0x300000 }; + +IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_SO_A_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); +MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c index e6f7066f5c7c..8b63cdb3d66c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c @@ -11,13 +11,6 @@ /* Lowest firmware API version supported */ #define IWL_GF_UCODE_API_MIN 100 -#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" -#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" -#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" -#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" -#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" -#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" -#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" #define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0" #define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" #define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" @@ -70,12 +63,6 @@ const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6 AX231"; const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; -IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SC_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c index 3c3a8d5702d8..16b9075acdd8 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c @@ -11,28 +11,10 @@ /* Lowest firmware API version supported */ #define IWL_HR_UCODE_API_MIN 100 -#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" -#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0" -#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" -#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" -#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" -#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" #define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0" #define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0" #define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0" -#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \ @@ -74,12 +56,6 @@ const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203"; -MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); -- 2.34.1 From: Ilan Peer Replace static declarations of IWL_MLD_ALLOC_FN with a new macro IWL_MLD_ALLOC_FN_STATIC that declares the static. This is needed to resolve issues with spatch, which fails to handle functions after "static IWL_MLD_ALLOC_FN". Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/iface.c | 2 +- drivers/net/wireless/intel/iwlwifi/mld/mld.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mld/sta.c | 2 +- drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c | 6 +++--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c index 2a270d689de8..f7a0a8efe374 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c @@ -499,7 +499,7 @@ static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy, iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif)); } -static IWL_MLD_ALLOC_FN(vif, vif) +IWL_MLD_ALLOC_FN_STATIC(vif, vif) /* Constructor function for struct iwl_mld_vif */ static void diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index 1a59b3e4014d..922aa3dbff54 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -552,6 +552,9 @@ iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \ return -ENOSPC; \ } +#define IWL_MLD_ALLOC_FN_STATIC(_type, _mac80211_type) \ +static IWL_MLD_ALLOC_FN(_type, _mac80211_type) + static inline struct ieee80211_bss_conf * iwl_mld_fw_id_to_link_conf(struct iwl_mld *mld, u8 fw_link_id) { diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c index 1fae5a6ba8d4..4c168ad53b0f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c @@ -577,7 +577,7 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, return iwl_mld_send_sta_cmd(mld, &cmd); } -static IWL_MLD_ALLOC_FN(link_sta, link_sta) +IWL_MLD_ALLOC_FN_STATIC(link_sta, link_sta) static int iwl_mld_add_link_sta(struct iwl_mld *mld, struct ieee80211_link_sta *link_sta) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c index 0cdbbb86dbd9..cb1968b07452 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c @@ -2,7 +2,7 @@ /* * KUnit tests for channel helper functions * - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include #include @@ -92,7 +92,7 @@ static void iwlmld_kunit_init_link(struct ieee80211_vif *vif, rcu_assign_pointer(vif->link_conf[link_id], link); } -static IWL_MLD_ALLOC_FN(vif, vif) +IWL_MLD_ALLOC_FN_STATIC(vif, vif) /* Helper function to add and initialize a VIF for KUnit tests */ struct ieee80211_vif *iwlmld_kunit_add_vif(bool mlo, enum nl80211_iftype type) @@ -197,7 +197,7 @@ void iwlmld_kunit_assign_chanctx_to_link(struct ieee80211_vif *vif, vif->active_links |= BIT(link->link_id); } -static IWL_MLD_ALLOC_FN(link_sta, link_sta) +IWL_MLD_ALLOC_FN_STATIC(link_sta, link_sta) static void iwlmld_kunit_add_link_sta(struct ieee80211_sta *sta, struct ieee80211_link_sta *link_sta, -- 2.34.1 From: Ilan Peer The FW added a new station type to allow NAN multicast data to be transmitted. The queue of the station is opened by the firmware when all the NAN Peer NDI stations associated with the NDI are scheduled at the same time. Add the corresponding support in iwlmld: - When a NAN data interface is added, add a NAN multicast data station and allocate a queue to it. - When a NAN data interface is removed, remove the NAN multicast station. - On the Tx path, when a multicast data frame is received on a NAN data interface, direct it to the NAN multicast data queue. Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 6 +- .../net/wireless/intel/iwlwifi/mld/iface.c | 6 ++ .../net/wireless/intel/iwlwifi/mld/iface.h | 2 + .../net/wireless/intel/iwlwifi/mld/mac80211.c | 32 ++++++- drivers/net/wireless/intel/iwlwifi/mld/nan.c | 29 +++++- drivers/net/wireless/intel/iwlwifi/mld/nan.h | 2 + drivers/net/wireless/intel/iwlwifi/mld/sta.c | 94 ++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/mld/sta.h | 11 +++ drivers/net/wireless/intel/iwlwifi/mld/tx.c | 11 ++- 9 files changed, 172 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 604281eb29c7..d03a2bda4e68 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -747,6 +747,8 @@ struct iwl_link_config_cmd { * discovery. No queue is associated with this station. * @STATION_TYPE_NAN_MGMT: NAN station used for NAN management frames, e.g., * SDFs and NAFs. + * @STATION_TYPE_NAN_MCAST_DATA: NAN station used for multicast NAN data + * frames. * @STATION_TYPE_MAX: maximum number of FW station types * @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type * for the aux sta, so this type is only for driver - internal use. @@ -759,6 +761,7 @@ enum iwl_fw_sta_type { STATION_TYPE_NAN_PEER_NDI, STATION_TYPE_NAN_BCAST, STATION_TYPE_NAN_MGMT, + STATION_TYPE_NAN_MCAST_DATA, STATION_TYPE_MAX, STATION_TYPE_AUX = STATION_TYPE_MAX /* this doesn't exist in FW */ }; /* STATION_TYPE_E_VER_1, _VER_2 */ @@ -933,7 +936,8 @@ struct iwl_sta_cfg_cmd_v2 { * @mic_prep_pad_delay: MIC prep time padding * @mic_compute_pad_delay: MIC compute time padding * @nmi_sta_id: for an NDI peer STA, the NMI peer STA ID it relates to - * @ndi_local_addr: for an NDI peer STA, the local NDI interface MAC address + * @ndi_local_addr: for an NDI peer STA or NAN multicast data station, + * the local NDI interface MAC address * @reserved: Reserved for alignment */ struct iwl_sta_cfg_cmd { diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c index f7a0a8efe374..399efeb469f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c @@ -68,6 +68,10 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif) iwl_mld_free_internal_sta(mld, &mld_vif->nan.mgmt_sta); } + if (vif->type == NL80211_IFTYPE_NAN_DATA && + mld_vif->nan.mcast_data_sta.sta_id != IWL_INVALID_STA) + iwl_mld_free_internal_sta(mld, &mld_vif->nan.mcast_data_sta); + CLEANUP_STRUCT(mld_vif); } @@ -534,6 +538,8 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) iwl_mld_init_internal_sta(&mld_vif->nan.bcast_sta); iwl_mld_init_internal_sta(&mld_vif->nan.mgmt_sta); + } else if (vif->type == NL80211_IFTYPE_NAN_DATA) { + iwl_mld_init_internal_sta(&mld_vif->nan.mcast_data_sta); } iwl_mld_init_internal_sta(&mld_vif->aux_sta); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index 75b6727503d3..c6a7588df1fa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -159,6 +159,7 @@ struct iwl_mld_emlsr { * activities. No queue is associated with it. * @nan.mgmt_sta: internal station used for NAN management frames, e.g., SDFs * and NAFs. + * @nan.mcast_data_sta: internal station used for multicast NAN Data frames. */ struct iwl_mld_vif { /* Add here fields that need clean up on restart */ @@ -187,6 +188,7 @@ struct iwl_mld_vif { bool mac_added; struct iwl_mld_int_sta bcast_sta; struct iwl_mld_int_sta mgmt_sta; + struct iwl_mld_int_sta mcast_data_sta; } nan; struct iwl_mld_emlsr emlsr; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 1f2843af39c1..b6df09812dae 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -663,8 +663,27 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw, if (ret) return ret; - if (vif->type == NL80211_IFTYPE_NAN_DATA) + if (vif->type == NL80211_IFTYPE_NAN_DATA) { + if (WARN_ON(!mld->nan_device_vif)) { + ret = -EINVAL; + goto err; + } + + if (iwl_mld_nan_use_nan_stations(mld)) { + struct iwl_mld_vif *mld_vif = + iwl_mld_vif_from_mac80211(vif); + struct iwl_mld_int_sta *sta = + &mld_vif->nan.mcast_data_sta; + + ret = iwl_mld_add_nan_mcast_data_sta(mld, + vif->addr, + sta); + if (ret) + goto err; + } + return 0; + } /* * Add the default link, but not if this is an MLD vif as that implies @@ -732,10 +751,17 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_P2P_DEVICE) mld->p2p_device_vif = NULL; - if (vif->type == NL80211_IFTYPE_NAN) + if (vif->type == NL80211_IFTYPE_NAN) { mld->nan_device_vif = NULL; - else if (vif->type != NL80211_IFTYPE_NAN_DATA) + } else if (vif->type != NL80211_IFTYPE_NAN_DATA) { iwl_mld_remove_link(mld, &vif->bss_conf); + } else if (iwl_mld_nan_use_nan_stations(mld)) { + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); + struct iwl_mld_int_sta *sta = &mld_vif->nan.mcast_data_sta; + + if (sta->sta_id != IWL_INVALID_STA) + iwl_mld_remove_nan_mcast_data_sta(mld, sta); + } #ifdef CONFIG_IWLWIFI_DEBUGFS debugfs_remove(iwl_mld_vif_from_mac80211(vif)->dbgfs_slink); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index 8f35687c58b1..530ba263c5f0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -50,7 +50,7 @@ static int iwl_mld_nan_send_config_cmd(struct iwl_mld *mld, return iwl_mld_send_cmd(mld, &hcmd); } -static bool iwl_mld_nan_use_nan_stations(struct iwl_mld *mld) +bool iwl_mld_nan_use_nan_stations(struct iwl_mld *mld) { /* * If the FW supports version 1 of the NAN config command, it means that @@ -650,6 +650,20 @@ iwl_mld_nan_find_link(struct iwl_mld_vif *mld_vif, return NULL; } +static void iwl_mld_nan_set_mcast_data_links(struct ieee80211_vif *vif) +{ + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); + + if (vif->type != NL80211_IFTYPE_NAN_DATA) + return; + + /* Note that all errors are handled internally so nothing to do + * with the return value (used only to silence compilation warnings) + */ + iwl_mld_update_nan_mcast_data_sta(mld_vif->mld, vif->addr, + &mld_vif->nan.mcast_data_sta); +} + void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, struct ieee80211_vif *vif, u64 changes) @@ -807,6 +821,19 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI) iwl_mld_add_modify_sta_cmd(mld, &sta->deflink); } + + /* + * Iterate over all the NAN Data interfaces and update the links + * for the internal multicast data station. + * In recovery - the station will be added later in + * drv_add_interface + */ + if (iwl_mld_nan_use_nan_stations(mld) && !mld->fw_status.in_hw_restart) { + struct ieee80211_vif *iter; + + for_each_active_interface(iter, mld->hw) + iwl_mld_nan_set_mcast_data_links(iter); + } } /* delete unused links */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.h b/drivers/net/wireless/intel/iwlwifi/mld/nan.h index 40152dc7d906..f4e4cd4b4e8d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.h @@ -60,4 +60,6 @@ int iwl_mld_mac802111_nan_peer_sched_changed(struct ieee80211_hw *hw, int iwl_mld_nan_get_mgmt_queue(struct iwl_mld *mld, struct ieee80211_vif *vif); +bool iwl_mld_nan_use_nan_stations(struct iwl_mld *mld); + #endif /* __iwl_mld_nan_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c index 4c168ad53b0f..cd13238ed613 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c @@ -428,6 +428,10 @@ static int iwl_mld_send_sta_cmd(struct iwl_mld *mld, len = sizeof(struct iwl_sta_cfg_cmd_v2); cmd_v2->link_id = cpu_to_le32(__ffs(le32_to_cpu(cmd->link_mask))); + } else if (cmd->station_type == + cpu_to_le32(STATION_TYPE_NAN_MCAST_DATA)) { + if (WARN_ON(!hweight32(le32_to_cpu(cmd->link_mask)))) + return -EINVAL; } else if (WARN_ON(cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NMI) && cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NDI) && cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_BCAST) && @@ -442,6 +446,19 @@ static int iwl_mld_send_sta_cmd(struct iwl_mld *mld, return ret; } +static u32 iwl_mld_get_nan_link_mask(struct iwl_mld *mld) +{ + struct iwl_mld_vif *nan_dev = + iwl_mld_vif_from_mac80211(mld->nan_device_vif); + struct iwl_mld_nan_link *nan_link; + u32 link_mask = 0; + + for_each_mld_nan_valid_link(nan_dev, nan_link) + link_mask |= BIT(nan_link->fw_id); + + return link_mask; +} + int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, struct ieee80211_link_sta *link_sta) { @@ -459,21 +476,13 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, if (mld_sta->sta_type == STATION_TYPE_NAN_PEER_NMI || mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI) { - struct iwl_mld_nan_link *nan_link; - struct iwl_mld_vif *nan_dev; - - is_6ghz = false; - uora_exists = false; - if (WARN_ON(!mld->nan_device_vif)) return -EINVAL; - nan_dev = iwl_mld_vif_from_mac80211(mld->nan_device_vif); - - link_mask = 0; + is_6ghz = false; + uora_exists = false; - for_each_mld_nan_valid_link(nan_dev, nan_link) - link_mask |= BIT(nan_link->fw_id); + link_mask = iwl_mld_get_nan_link_mask(mld); } else { struct ieee80211_bss_conf *link; struct iwl_mld_link *mld_link; @@ -1063,7 +1072,7 @@ static int iwl_mld_send_aux_sta_cmd(struct iwl_mld *mld, } static int -iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld, +iwl_mld_set_internal_sta_to_fw(struct iwl_mld *mld, const struct iwl_mld_int_sta *internal_sta, u32 link_mask, const u8 *addr) { @@ -1085,8 +1094,12 @@ iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld, cmd.mfp = cpu_to_le32(1); if (addr) { - memcpy(cmd.peer_mld_address, addr, ETH_ALEN); - memcpy(cmd.peer_link_address, addr, ETH_ALEN); + if (internal_sta->sta_type == STATION_TYPE_NAN_MCAST_DATA) { + ether_addr_copy(cmd.ndi_local_addr, addr); + } else { + memcpy(cmd.peer_mld_address, addr, ETH_ALEN); + memcpy(cmd.peer_link_address, addr, ETH_ALEN); + } } return iwl_mld_send_sta_cmd(mld, &cmd); @@ -1108,7 +1121,7 @@ static int iwl_mld_add_internal_sta(struct iwl_mld *mld, internal_sta->sta_type = sta_type; - ret = iwl_mld_add_internal_sta_to_fw(mld, internal_sta, link_mask, + ret = iwl_mld_set_internal_sta_to_fw(mld, internal_sta, link_mask, addr); if (ret) goto err; @@ -1432,6 +1445,51 @@ int iwl_mld_add_nan_mgmt_sta(struct iwl_mld *mld, 0, NULL, IWL_MAX_TID_COUNT, true); } +int iwl_mld_add_nan_mcast_data_sta(struct iwl_mld *mld, + const u8 *ndi_addr, + struct iwl_mld_int_sta *sta) +{ + u32 link_mask = iwl_mld_get_nan_link_mask(mld); + + /* In case that there are no NAN links, nothing to do */ + if (!link_mask) + return 0; + + return iwl_mld_add_internal_sta(mld, sta, + STATION_TYPE_NAN_MCAST_DATA, + link_mask, ndi_addr, + 0, true); +} + +int iwl_mld_update_nan_mcast_data_sta(struct iwl_mld *mld, + const u8 *ndi_addr, + struct iwl_mld_int_sta *sta) +{ + u32 link_mask; + + if (WARN_ON(!mld->nan_device_vif)) + return -EINVAL; + + /* If the sta doesn't exist, add it */ + if (sta->sta_id == IWL_INVALID_STA) + return iwl_mld_add_nan_mcast_data_sta(mld, ndi_addr, sta); + + /* The station was already added */ + if (WARN_ON(sta->sta_type != STATION_TYPE_NAN_MCAST_DATA)) + return -EINVAL; + + link_mask = iwl_mld_get_nan_link_mask(mld); + if (link_mask) + return iwl_mld_set_internal_sta_to_fw(mld, + sta, link_mask, + ndi_addr); + + /* If no links are associated with NAN, remove the station */ + iwl_mld_remove_nan_mcast_data_sta(mld, sta); + + return 0; +} + void iwl_mld_remove_nan_bcast_sta(struct iwl_mld *mld, struct iwl_mld_int_sta *sta) { @@ -1443,3 +1501,9 @@ void iwl_mld_remove_nan_mgmt_sta(struct iwl_mld *mld, { iwl_mld_remove_internal_sta(mld, sta, true, IWL_MAX_TID_COUNT); } + +void iwl_mld_remove_nan_mcast_data_sta(struct iwl_mld *mld, + struct iwl_mld_int_sta *sta) +{ + iwl_mld_remove_internal_sta(mld, sta, true, 0); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.h b/drivers/net/wireless/intel/iwlwifi/mld/sta.h index df859a9e5230..98d693235c66 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.h @@ -283,10 +283,21 @@ int iwl_mld_add_nan_bcast_sta(struct iwl_mld *mld, int iwl_mld_add_nan_mgmt_sta(struct iwl_mld *mld, struct iwl_mld_int_sta *sta); +int iwl_mld_add_nan_mcast_data_sta(struct iwl_mld *mld, + const u8 *ndi_addr, + struct iwl_mld_int_sta *sta); + +int iwl_mld_update_nan_mcast_data_sta(struct iwl_mld *mld, + const u8 *ndi_addr, + struct iwl_mld_int_sta *sta); + void iwl_mld_remove_nan_bcast_sta(struct iwl_mld *mld, struct iwl_mld_int_sta *sta); void iwl_mld_remove_nan_mgmt_sta(struct iwl_mld *mld, struct iwl_mld_int_sta *sta); +void iwl_mld_remove_nan_mcast_data_sta(struct iwl_mld *mld, + struct iwl_mld_int_sta *sta); + #endif /* __iwl_mld_sta_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c index 39e1d959e42c..1100f7f1e76f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c @@ -351,7 +351,8 @@ u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld, iwl_mld_get_basic_rates_and_band(mld, vif, info, &basic_rates, &band); if (band >= NUM_NL80211_BANDS) { - WARN_ON(vif->type != NL80211_IFTYPE_NAN); + WARN_ON(vif->type != NL80211_IFTYPE_NAN && + vif->type != NL80211_IFTYPE_NAN_DATA); return IWL_FIRST_OFDM_RATE; } @@ -682,6 +683,14 @@ iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq, case NL80211_IFTYPE_NAN: WARN_ON(!ieee80211_is_mgmt(fc)); return iwl_mld_nan_get_mgmt_queue(mld, info->control.vif); + case NL80211_IFTYPE_NAN_DATA: + WARN_ON(!ieee80211_is_data(fc)); + + if (!iwl_mld_nan_use_nan_stations(mld)) + break; + + mld_vif = iwl_mld_vif_from_mac80211(info->control.vif); + return mld_vif->nan.mcast_data_sta.queue_id; default: WARN_ONCE(1, "Unsupported vif type\n"); break; -- 2.34.1 From: Johannes Berg For NAN data, the supplicant may derive and install GTKs to transmit with. As multicast data encryption is supported only with firmware versions that support adding NAN multicast data station, allow GTK installation only with such FW versions. Otherwise, do not install the GTK to the device. For NAN management, there are no GTKs, but there are IGTKs and BIGTKs, which need to be installed for the NAN broadcast and NAN management stations. This is supported only with firmware versions that allow adding NAN broadcast station and NAN management station. Handle both of these cases by adjusting the station mask appropriately, returning a zero station mask for the GTK and allowing that to not be an error/warning message. Signed-off-by: Johannes Berg Co-developed-by: Ilan Peer Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/mld/iface.c | 2 + .../net/wireless/intel/iwlwifi/mld/iface.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mld/key.c | 50 +++++++++++++++++-- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 1 - drivers/net/wireless/intel/iwlwifi/mld/sta.c | 8 ++- 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c index 399efeb469f6..2b837c6fa5fe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c @@ -66,6 +66,8 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif) iwl_mld_free_internal_sta(mld, &mld_vif->nan.bcast_sta); if (mld_vif->nan.mgmt_sta.sta_id != IWL_INVALID_STA) iwl_mld_free_internal_sta(mld, &mld_vif->nan.mgmt_sta); + + mld_vif->nan.tx_igtk = NULL; } if (vif->type == NL80211_IFTYPE_NAN_DATA && diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index c6a7588df1fa..bc6f45ff76f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -160,6 +160,8 @@ struct iwl_mld_emlsr { * @nan.mgmt_sta: internal station used for NAN management frames, e.g., SDFs * and NAFs. * @nan.mcast_data_sta: internal station used for multicast NAN Data frames. + * @nan.tx_igtk: TX IGTK key for NAN, tracked separately since NAN does not + * use the vif links. */ struct iwl_mld_vif { /* Add here fields that need clean up on restart */ @@ -189,6 +191,7 @@ struct iwl_mld_vif { struct iwl_mld_int_sta bcast_sta; struct iwl_mld_int_sta mgmt_sta; struct iwl_mld_int_sta mcast_data_sta; + struct ieee80211_key_conf *tx_igtk; } nan; struct iwl_mld_emlsr emlsr; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.c b/drivers/net/wireless/intel/iwlwifi/mld/key.c index 151e35b851f7..a6454d90d0e3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/key.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/key.c @@ -63,6 +63,40 @@ static u32 iwl_mld_get_key_sta_mask(struct iwl_mld *mld, lockdep_assert_wiphy(mld->wiphy); + if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta) { + /* Older firmware versions do not support transmission of + * multicast data frames. + */ + if (!iwl_mld_nan_use_nan_stations(mld)) + return 0; + + if (WARN_ON(mld_vif->nan.mcast_data_sta.sta_id == + IWL_INVALID_STA)) + return 0; + + return BIT(mld_vif->nan.mcast_data_sta.sta_id); + } + + if (vif->type == NL80211_IFTYPE_NAN && !sta) { + /* Older firmware versions do not support installation of + * IGTK/BIGTK keys. + */ + if (!iwl_mld_nan_use_nan_stations(mld)) + return 0; + + if (WARN_ON(mld_vif->nan.bcast_sta.sta_id == IWL_INVALID_STA || + mld_vif->nan.mgmt_sta.sta_id == IWL_INVALID_STA)) + return 0; + + if (key->keyidx >= 4 && key->keyidx <= 5) + return BIT(mld_vif->nan.mgmt_sta.sta_id); + + if (key->keyidx >= 6 && key->keyidx <= 7) + return BIT(mld_vif->nan.bcast_sta.sta_id); + + return 0; + } + /* AP group keys are per link and should be on the mcast/bcast STA */ if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { @@ -204,7 +238,7 @@ iwl_mld_get_igtk_ptr(struct ieee80211_vif *vif, return &mld_sta->deflink.rx_igtk; } - return &mld_vif->deflink.tx_igtk; + return &mld_vif->nan.tx_igtk; case NL80211_IFTYPE_AP: mld_link = iwl_mld_link_dereference_check(mld_vif, link_id); if (WARN_ON(!mld_link)) @@ -254,8 +288,16 @@ int iwl_mld_add_key(struct iwl_mld *mld, lockdep_assert_wiphy(mld->wiphy); - if (!sta_mask) + if (!sta_mask) { + /* for NAN (GTK) indicate SW-only, it's not used at all */ + if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta && + !iwl_mld_nan_use_nan_stations(mld)) + return 1; + + /* otherwise that's not valid */ + IWL_WARN(mld, "empty STA mask for key %d\n", key->keyidx); return -EINVAL; + } igtk_ptr = iwl_mld_get_igtk_ptr(vif, sta, key); if (igtk_ptr) { @@ -270,8 +312,10 @@ int iwl_mld_add_key(struct iwl_mld *mld, } ret = iwl_mld_add_key_to_fw(mld, sta_mask, key_flags, key); - if (ret) + if (ret) { + IWL_WARN(mld, "failed to add key to FW (%d)\n", ret); return ret; + } if (igtk_ptr) { WARN_ON(*igtk_ptr); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index b6df09812dae..9736b43155d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -2248,7 +2248,6 @@ static int iwl_mld_set_key_add(struct iwl_mld *mld, ret = iwl_mld_add_key(mld, vif, sta, key); if (ret) { - IWL_WARN(mld, "set key failed (%d)\n", ret); if (ptk_pn) { RCU_INIT_POINTER(mld_sta->ptk_pn[keyidx], NULL); kfree(ptk_pn); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c index cd13238ed613..77eeeed66116 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c @@ -1089,8 +1089,14 @@ iwl_mld_set_internal_sta_to_fw(struct iwl_mld *mld, * On the other hand, FW will never check this flag during RX since * an AP/GO doesn't receive protected broadcast management frames. * So, we can set it unconditionally. + * + * For NAN stations associated with a NAN Device, the MFP bit must be + * set to 1, as otherwise the FW will assert when a key associated with + * these stations would be added. */ - if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT) + if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT || + internal_sta->sta_type == STATION_TYPE_NAN_BCAST || + internal_sta->sta_type == STATION_TYPE_NAN_MGMT) cmd.mfp = cpu_to_le32(1); if (addr) { -- 2.34.1