From 6fdd41b25fb4154bcde7a38ca1c98e072fa1177c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:29 +0300 Subject: [PATCH 01/64] wifi: iwlwifi: handle non-overlapping API ranges The option to set an api_version_min/max also to the RF was added. In the case that both the MAC and the RF has a range defined, we take the narrower range of both. This doesn't work for non-overlapping ranges. In this case, we should just take the lower range of both. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709200543.1628666-2-miriam.rachel.korenblit@intel.com --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index f62f7c7ee7f3..2dff87c07512 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -301,13 +301,17 @@ static void iwl_get_ucode_api_versions(struct iwl_trans *trans, const struct iwl_family_base_params *base = trans->mac_cfg->base; const struct iwl_rf_cfg *cfg = trans->cfg; - if (!base->ucode_api_max) { + /* if the MAC doesn't have range or if its range it higher than the RF's */ + if (!base->ucode_api_max || + (cfg->ucode_api_max && base->ucode_api_min > cfg->ucode_api_max)) { *api_min = cfg->ucode_api_min; *api_max = cfg->ucode_api_max; return; } - if (!cfg->ucode_api_max) { + /* if the RF doesn't have range or if its range it higher than the MAC's */ + if (!cfg->ucode_api_max || + (base->ucode_api_max && cfg->ucode_api_min > base->ucode_api_max)) { *api_min = base->ucode_api_min; *api_max = base->ucode_api_max; return; From e9901c6a6057426d8682eeb776f0fe9c325318e9 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:30 +0300 Subject: [PATCH 02/64] wifi: iwlwifi: assign a FW API range for JF JF device is frozen on API 77. This prevented us from bumping the minimum FW API of SO (and get rid of older FWs). This is because SO can be combined with JF and then FW API 77 should be used. Now as we have separate FW API ranges for the mac and the crf, we can define for JF its own FW API range. This will allow bumping the minimum FW API of SO Independently. Do that now. Signed-off-by: Miri Korenblit Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20250709200543.1628666-3-miriam.rachel.korenblit@intel.com --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 12 -------- .../net/wireless/intel/iwlwifi/cfg/ax210.c | 4 --- .../net/wireless/intel/iwlwifi/cfg/rf-jf.c | 29 ++++++++++++++++++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 52e0beebf9ce..57af51a3ee0b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -21,24 +21,15 @@ #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_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0" -#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0" #define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" -#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0" #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_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_JF_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_QU_B_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode" @@ -134,8 +125,5 @@ const char iwl_ax201_killer_1650i_name[] = 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_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_C_JF_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_QUZ_A_JF_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 3bf9fdbe01c6..5158ccbd1fc4 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -19,7 +19,6 @@ #define IWL_AX210_SMEM_OFFSET 0x400000 #define IWL_AX210_SMEM_LEN 0xD0000 -#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0" #define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" #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" @@ -31,8 +30,6 @@ #define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" #define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" -#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_JF_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) \ @@ -144,7 +141,6 @@ const struct iwl_mac_cfg iwl_ma_mac_cfg = { .umac_prph_offset = 0x300000 }; -MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); 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); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c index 467eaeae6deb..0a074e0a3bc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c @@ -5,6 +5,26 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_JF_UCODE_API_MAX 77 + +/* Lowest firmware API version supported */ +#define IWL_JF_UCODE_API_MIN 77 + +#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0" +#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0" +#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0" +#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0" + +#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \ + IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" + /* NVM versions */ #define IWL_JF_NVM_VERSION 0x0a1d @@ -56,7 +76,9 @@ static const struct iwl_tt_params iwl_jf_tt_params = { BIT(NL80211_BAND_5GHZ), \ }, \ .nvm_ver = IWL_JF_NVM_VERSION, \ - .nvm_type = IWL_NVM_EXT + .nvm_type = IWL_NVM_EXT, \ + .ucode_api_min = IWL_JF_UCODE_API_MIN, \ + .ucode_api_max = IWL_JF_UCODE_API_MAX const struct iwl_rf_cfg iwl_rf_jf = { IWL_DEVICE_JF, @@ -82,3 +104,8 @@ const char iwl9560_killer_1550i_name[] = "Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz"; const char iwl9560_killer_1550s_name[] = "Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz"; + +MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); From 35a13ce4820f8294740dfab8f8b0fba50e298920 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:31 +0300 Subject: [PATCH 03/64] wifi: iwlwifi: bump minimum API version for SO/MA/TY Stop supporting older FWs. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.64f504f3690d.Idc95ca09101e52b4980b292945abe944c24fc5d1@changeid --- drivers/net/wireless/intel/iwlwifi/cfg/ax210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index 5158ccbd1fc4..467c45ed9af2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -13,7 +13,7 @@ #define IWL_AX210_UCODE_API_MAX 89 /* Lowest firmware API version supported */ -#define IWL_AX210_UCODE_API_MIN 77 +#define IWL_AX210_UCODE_API_MIN 89 /* Memory offsets and lengths */ #define IWL_AX210_SMEM_OFFSET 0x400000 From 51c6b2857ea3204dd5096e95139901328d782294 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:32 +0300 Subject: [PATCH 04/64] wifi: iwlwifi: mvm: remove support for iwl_wowlan_info_notif_v2 FWs with this version are no longer supported on any device. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.d92f63207232.I8961ffbe04d0d9439d48a17840497ac926967914@changeid --- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 33 ------------------- .../wireless/intel/iwlwifi/fw/api/offload.h | 5 ++- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 26 +++------------ 3 files changed, 6 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 99554496300a..3fd1a1b64b07 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -832,39 +832,6 @@ struct iwl_wowlan_info_notif_v1 { u8 reserved2[2]; } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */ -/** - * struct iwl_wowlan_info_notif_v2 - WoWLAN information notification - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched patterns - * @reserved1: reserved - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @station_id: station id - * @reserved2: reserved - */ -struct iwl_wowlan_info_notif_v2 { - struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 reserved1; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - u8 tid_tear_down; - u8 station_id; - u8 reserved2[2]; -} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */ - /* MAX MLO keys of non-active links that can arrive in the notification */ #define WOWLAN_MAX_MLO_KEYS 18 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index 9b09b835560b..7d9aa8363f90 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -3,7 +3,7 @@ * Copyright (C) 2012-2014 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2021-2024 Intel Corporation + * Copyright (C) 2021-2025 Intel Corporation */ #ifndef __iwl_fw_api_offload_h__ #define __iwl_fw_api_offload_h__ @@ -19,8 +19,7 @@ enum iwl_prot_offload_subcmd_ids { /** * @WOWLAN_INFO_NOTIFICATION: Notification in - * &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2, - * or &struct iwl_wowlan_info_notif + * &struct iwl_wowlan_info_notif_v1, or &struct iwl_wowlan_info_notif */ WOWLAN_INFO_NOTIFICATION = 0xFD, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 66749dc38fc5..bc5f70f04d2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2380,8 +2380,8 @@ iwl_mvm_parse_wowlan_info_notif_v3(struct iwl_mvm *mvm, } static void -iwl_mvm_parse_wowlan_info_notif_v2(struct iwl_mvm *mvm, - struct iwl_wowlan_info_notif_v2 *data, +iwl_mvm_parse_wowlan_info_notif_v1(struct iwl_mvm *mvm, + struct iwl_wowlan_info_notif_v1 *data, struct iwl_wowlan_status_data *status, u32 len) { @@ -3097,29 +3097,11 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait, break; } - if (wowlan_info_ver < 2) { + if (wowlan_info_ver == 1) { struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data; - struct iwl_wowlan_info_notif_v2 *notif_v2; - notif_v2 = kmemdup(notif_v1, sizeof(*notif_v2), GFP_ATOMIC); - - if (!notif_v2) - return false; - - notif_v2->tid_tear_down = notif_v1->tid_tear_down; - notif_v2->station_id = notif_v1->station_id; - memset_after(notif_v2, 0, station_id); - iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2, - d3_data->status, - len); - kfree(notif_v2); - - } else if (wowlan_info_ver == 2) { - struct iwl_wowlan_info_notif_v2 *notif_v2 = - (void *)pkt->data; - - iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2, + iwl_mvm_parse_wowlan_info_notif_v1(mvm, notif_v1, d3_data->status, len); } else if (wowlan_info_ver == 3) { From 8f30c98440d22ae77a702bda8197f74368dd5ce9 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:33 +0300 Subject: [PATCH 05/64] wifi: iwlwifi: add a reference to iwl_wowlan_info_notif_v3 Mark this structure as one of the structures that represent WOWLAN_INFO_NOTIFICATION Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.19ebfa430c5c.Ie5aca3f0af11cc3137c6b6862a13777bae0cb06b@changeid --- drivers/net/wireless/intel/iwlwifi/fw/api/offload.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index 7d9aa8363f90..2a1c2b0f19e4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -19,7 +19,8 @@ enum iwl_prot_offload_subcmd_ids { /** * @WOWLAN_INFO_NOTIFICATION: Notification in - * &struct iwl_wowlan_info_notif_v1, or &struct iwl_wowlan_info_notif + * &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3, + * or &struct iwl_wowlan_info_notif */ WOWLAN_INFO_NOTIFICATION = 0xFD, From 762ee87417794b6720b8b55b26c066d0995a7836 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:34 +0300 Subject: [PATCH 06/64] wifi: iwlwifi: mvm: remove support for iwl_wowlan_status_v12 FWs with this version are no longer supported on any device. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.1b9177bfbe1d.I53c1527cc5097f05df352b6f2f99282b00a5d7ac@changeid --- .../wireless/intel/iwlwifi/fw/api/commands.h | 3 +- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 38 ------------------- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 13 ------- 3 files changed, 1 insertion(+), 53 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 1c86a858aaab..3f8f9e3fcba8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -574,8 +574,7 @@ enum iwl_legacy_cmds { /** * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6, - * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or - * &struct iwl_wowlan_status_v12 + * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 */ WOWLAN_GET_STATUSES = 0xe5, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 3fd1a1b64b07..a73b1f63da1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -757,44 +757,6 @@ struct iwl_wowlan_status_v9 { u8 wake_packet[]; /* can be truncated from _length to _bufsize */ } __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */ -/** - * struct iwl_wowlan_status_v12 - WoWLAN status - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next. - * Reserved if the struct has version >= 10. - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @wake_packet_length: wakeup packet length - * @wake_packet_bufsize: wakeup packet buffer size - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @reserved: unused - * @wake_packet: wakeup packet - */ -struct iwl_wowlan_status_v12 { - struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 non_qos_seq_ctr; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - __le32 wake_packet_length; - __le32 wake_packet_bufsize; - u8 tid_tear_down; - u8 reserved[3]; - u8 wake_packet[]; /* can be truncated from _length to _bufsize */ -} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */ - /** * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification * @gtk: GTK data diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index bc5f70f04d2c..36890e9c7a2f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2467,7 +2467,6 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \ iwl_mvm_parse_wowlan_status_common(v6) iwl_mvm_parse_wowlan_status_common(v7) iwl_mvm_parse_wowlan_status_common(v9) -iwl_mvm_parse_wowlan_status_common(v12) static struct iwl_wowlan_status_data * iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) @@ -2559,18 +2558,6 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) iwl_mvm_convert_igtk(status, &v9->igtk[0]); status->tid_tear_down = v9->tid_tear_down; - } else if (notif_ver == 12) { - struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data; - - status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len); - if (!status) - goto out_free_resp; - - iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc); - iwl_mvm_convert_gtk_v3(status, v12->gtk); - iwl_mvm_convert_igtk(status, &v12->igtk[0]); - - status->tid_tear_down = v12->tid_tear_down; } else { IWL_ERR(mvm, "Firmware advertises unknown WoWLAN status response %d!\n", From adf382eac0b5555fe01f8aeb08f9a6873be02586 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:35 +0300 Subject: [PATCH 07/64] wifi: iwlwifi: mvm: remove support for iwl_wowlan_status_v9 FWs with this version are no longer supported on any device. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.22864efb5074.I51f270f8848970fd2ca1078c14ad31f4a8853e7d@changeid --- .../wireless/intel/iwlwifi/fw/api/commands.h | 4 +- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 38 ------------------- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 16 -------- 3 files changed, 2 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 3f8f9e3fcba8..997b0c9ce984 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -573,8 +573,8 @@ enum iwl_legacy_cmds { WOWLAN_KEK_KCK_MATERIAL = 0xe4, /** - * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6, - * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 + * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6 or + * &struct iwl_wowlan_status_v7 */ WOWLAN_GET_STATUSES = 0xe5, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index a73b1f63da1c..b16bd8aa136a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -719,44 +719,6 @@ struct iwl_wowlan_status_v7 { u8 wake_packet[]; /* can be truncated from _length to _bufsize */ } __packed; /* WOWLAN_STATUSES_API_S_VER_7 */ -/** - * struct iwl_wowlan_status_v9 - WoWLAN status (versions 9 and 10) - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next. - * Reserved if the struct has version >= 10. - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @wake_packet_length: wakeup packet length - * @wake_packet_bufsize: wakeup packet buffer size - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @reserved: unused - * @wake_packet: wakeup packet - */ -struct iwl_wowlan_status_v9 { - struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 non_qos_seq_ctr; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - __le32 wake_packet_length; - __le32 wake_packet_bufsize; - u8 tid_tear_down; - u8 reserved[3]; - u8 wake_packet[]; /* can be truncated from _length to _bufsize */ -} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */ - /** * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification * @gtk: GTK data diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 36890e9c7a2f..d9d678fbdaab 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2466,7 +2466,6 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \ iwl_mvm_parse_wowlan_status_common(v6) iwl_mvm_parse_wowlan_status_common(v7) -iwl_mvm_parse_wowlan_status_common(v9) static struct iwl_wowlan_status_data * iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) @@ -2543,21 +2542,6 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc); iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]); iwl_mvm_convert_igtk(status, &v7->igtk[0]); - } else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) { - struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data; - - /* these three command versions have same layout and size, the - * difference is only in a few not used (reserved) fields. - */ - status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len); - if (!status) - goto out_free_resp; - - iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc); - iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]); - iwl_mvm_convert_igtk(status, &v9->igtk[0]); - - status->tid_tear_down = v9->tid_tear_down; } else { IWL_ERR(mvm, "Firmware advertises unknown WoWLAN status response %d!\n", From 48d41b73316c801423ede39ed1eafef7d6eef391 Mon Sep 17 00:00:00 2001 From: Itamar Shalev Date: Wed, 9 Jul 2025 23:05:36 +0300 Subject: [PATCH 08/64] wifi: iwlwifi: simplify iwl_poll_bits_mask return value Update iwl_poll_bits_mask to return 0 on success or an error code. Remove timing information from the return value, as it is unused. Signed-off-by: Itamar Shalev Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.f77b9f484a78.Iae8ef99a94e25c23044e2c36244cda2b55328447@changeid --- drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c | 12 ++++++------ drivers/net/wireless/intel/iwlwifi/iwl-io.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 12 ++++++------ drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c index 8087aee03d1c..9f8cdb027839 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c @@ -679,11 +679,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM, IWL_EEPROM_SEM_TIMEOUT); - if (ret >= 0) { + if (!ret) { IWL_DEBUG_EEPROM(trans->dev, "Acquired semaphore after %d tries.\n", count+1); - return ret; + return 0; } } @@ -799,7 +799,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); return ret; } @@ -941,14 +941,14 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) return -ENOMEM; ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); goto err_free; } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = iwl_eeprom_acquire_semaphore(trans); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); goto err_free; } @@ -994,7 +994,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Time out reading EEPROM[%d]\n", addr); goto err_unlock; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 47ad447b6226..ad857a05d3c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -54,7 +54,7 @@ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, do { if ((iwl_read32(trans, addr) & mask) == (bits & mask)) - return t; + return 0; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; } while (t < timeout); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 585d845b53fa..327366bf87de 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -392,7 +392,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); } - if (ret < 0) + if (ret) IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); IWL_DEBUG_INFO(trans, "stop master\n"); @@ -495,10 +495,10 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans) CSR_HW_IF_CONFIG_REG_PCI_OWN_SET, HW_READY_TIMEOUT); - if (ret >= 0) + if (!ret) iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE); - IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret ? " not" : ""); return ret; } @@ -512,7 +512,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) ret = iwl_pcie_set_hw_ready(trans); /* If the card is ready, exit 0 */ - if (ret >= 0) { + if (!ret) { trans->csme_own = false; return 0; } @@ -530,7 +530,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) do { ret = iwl_pcie_set_hw_ready(trans); - if (ret >= 0) { + if (!ret) { trans->csme_own = false; return 0; } @@ -2353,7 +2353,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) * and do not save/restore SRAM when power cycling. */ ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000); - if (unlikely(ret < 0)) { + if (unlikely(ret)) { u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL); if (silent) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index 3af6e3b3640d..224f4a68c7a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -591,7 +591,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) /* Wait for DMA channels to be idle */ ret = iwl_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000); - if (ret < 0) + if (ret) IWL_ERR(trans, "Failing on timeout while stopping DMA channel %d [0x%08x]\n", ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG)); From be27286f91f7c92dd7d54ae257e528cf8a526924 Mon Sep 17 00:00:00 2001 From: Itamar Shalev Date: Wed, 9 Jul 2025 23:05:37 +0300 Subject: [PATCH 09/64] wifi: iwlwifi: pcie: inform me when op mode leaving Transport gen2 didn't inform ME when the op mode is leaving. Signed-off-by: Itamar Shalev Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.abd840f5e998.I3a3fe174ea55a30daa04a0a3e9a6264913677045@changeid --- .../net/wireless/intel/iwlwifi/iwl-trans.c | 5 ++++- .../intel/iwlwifi/pcie/gen1_2/internal.h | 1 + .../intel/iwlwifi/pcie/gen1_2/trans-gen2.c | 20 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 9604781dd0b7..b6e71c172e7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -419,7 +419,10 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans) { might_sleep(); - iwl_trans_pcie_op_mode_leave(trans); + if (trans->mac_cfg->gen2) + iwl_trans_pcie_gen2_op_mode_leave(trans); + else + iwl_trans_pcie_op_mode_leave(trans); cancel_delayed_work_sync(&trans->restart.wk); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index 7dd11891ccfe..f48aeebb151c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1091,6 +1091,7 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, void iwl_trans_pcie_stop_device(struct iwl_trans *trans); /* common functions that are used by gen2 transport */ +void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans); int iwl_pcie_gen2_apm_init(struct iwl_trans *trans); void iwl_pcie_apm_config(struct iwl_trans *trans); int iwl_pcie_prepare_card_hw(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c index 0df8522ca410..035048e0e8f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c @@ -630,3 +630,23 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, mutex_unlock(&trans_pcie->mutex); return ret; } + +void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + mutex_lock(&trans_pcie->mutex); + + /* disable interrupts - don't enable HW RF kill interrupt */ + iwl_disable_interrupts(trans); + + iwl_pcie_gen2_apm_stop(trans, true); + + iwl_disable_interrupts(trans); + + iwl_pcie_disable_ict(trans); + + mutex_unlock(&trans_pcie->mutex); + + iwl_pcie_synchronize_irqs(trans); +} From 320b2da0288733df03d1771d079b93fac83ed8f2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:05:38 +0300 Subject: [PATCH 10/64] wifi: iwlwifi: pcie: accept new devices for MVM-only configs For newer MACs, the MVM opmode may be used for older firmware images or when the RF isn't EHT/WiFi7 capable. List such devices in the PCI device list when MLD isn't built. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.483c8112f655.Ic05530048fc0b67b1cd8772882a595d56b204e65@changeid --- drivers/net/wireless/intel/iwlwifi/Makefile | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index b82392978b76..941257b811b4 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -22,6 +22,7 @@ iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o # MAC configurations iwlwifi-$(CONFIG_IWLMVM) += cfg/9000.o cfg/22000.o iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o +iwlwifi-$(CONFIG_IWLMVM) += cfg/bz.o cfg/sc.o iwlwifi-$(CONFIG_IWLMLD) += cfg/bz.o cfg/sc.o cfg/dr.o # RF configurations iwlwifi-$(CONFIG_IWLMVM) += cfg/rf-jf.o cfg/rf-hr.o cfg/rf-gf.o diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 0bd9b44d295b..b7add05f7a85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -501,7 +501,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_mac_cfg)}, {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_mac_cfg)}, #endif /* CONFIG_IWLMVM */ -#if IS_ENABLED(CONFIG_IWLMLD) +#if IS_ENABLED(CONFIG_IWLMVM) || IS_ENABLED(CONFIG_IWLMLD) /* Bz devices */ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_gl_mac_cfg)}, {IWL_PCI_DEVICE(0xA840, 0x0000, iwl_bz_mac_cfg)}, @@ -546,7 +546,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_mac_cfg)}, {IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_mac_cfg)}, {IWL_PCI_DEVICE(0xD240, PCI_ANY_ID, iwl_sc_mac_cfg)}, -#endif /* CONFIG_IWLMLD */ +#endif /* CONFIG_IWLMVM || CONFIG_IWLMLD */ {0} }; From db35444d557fe7f481bd649f7c5a75f8103e87f3 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:39 +0300 Subject: [PATCH 11/64] wifi: iwlwifi: assign a FW API range for HR HR device is frozen on API 100, so it is not allowed to use FW APIs higher than that. Make sure of that by assigning a MIN and MAX API range for HR. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.ea54c00de44d.I47340ecaefbf40bb0bd254485d242b7f39df85b1@changeid --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 12 ----- .../net/wireless/intel/iwlwifi/cfg/ax210.c | 13 ----- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 5 -- .../net/wireless/intel/iwlwifi/cfg/rf-hr.c | 49 ++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 9 ---- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 57af51a3ee0b..ca488931a33c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -19,17 +19,8 @@ #define IWL_22000_SMEM_OFFSET 0x400000 #define IWL_22000_SMEM_LEN 0xD0000 -#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_FW_PRE "iwlwifi-cc-a0" -#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_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode" @@ -123,7 +114,4 @@ 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 467c45ed9af2..cf7d91894ab9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -19,24 +19,14 @@ #define IWL_AX210_SMEM_OFFSET 0x400000 #define IWL_AX210_SMEM_LEN 0xD0000 -#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" #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_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" -#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" #define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" #define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" -#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" #define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" #define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" -#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" - static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -141,12 +131,9 @@ const struct iwl_mac_cfg iwl_ma_mac_cfg = { .umac_prph_offset = 0x300000 }; -MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); 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); -MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(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_A_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(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_MA_B_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 50d454514fe5..02d6df7fa7a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -19,7 +19,6 @@ #define IWL_BZ_SMEM_OFFSET 0x400000 #define IWL_BZ_SMEM_LEN 0xD0000 -#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0" #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_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0" @@ -28,9 +27,6 @@ #define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0" #define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0" -#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" - static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -107,7 +103,6 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = { .low_latency_xtal = true, }; -MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_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 db02664e3917..9f408d276ce9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c @@ -5,6 +5,41 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_HR_UCODE_API_MAX 100 + +/* Lowest firmware API version supported */ +#define IWL_HR_UCODE_API_MIN 98 + +#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) \ + IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" + /* NVM versions */ #define IWL_HR_NVM_VERSION 0x0a1d @@ -20,7 +55,9 @@ }, \ .num_rbds = IWL_NUM_RBDS_HE, \ .nvm_ver = IWL_HR_NVM_VERSION, \ - .nvm_type = IWL_NVM_EXT + .nvm_type = IWL_NVM_EXT, \ + .ucode_api_min = IWL_HR_UCODE_API_MIN, \ + .ucode_api_max = IWL_HR_UCODE_API_MAX const struct iwl_rf_cfg iwl_rf_hr1 = { IWL_DEVICE_HR, @@ -40,3 +77,13 @@ const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; 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)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 97e503a25eae..ab44298d421e 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -24,8 +24,6 @@ #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_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0" -#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0" #define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" #define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" #define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0" @@ -34,11 +32,6 @@ #define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0" #define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0" -#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \ - IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" - static const struct iwl_family_base_params iwl_sc_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -107,8 +100,6 @@ const struct iwl_mac_cfg iwl_sc_mac_cfg = { IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); -MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); From 617b19600d1c2eb9834c7f372ae55b9b26c1e4c8 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:40 +0300 Subject: [PATCH 12/64] wifi: iwlwifi: assign a FW API range for GF GF device is frozen on API 100, so it is not allowed to use FW APIs higher than that. Make sure of that by assigning a MIN and MAX API range for GF. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.3409de06db40.I2110ee6c0a2f5ff1e16156c5875f83d7a1723857@changeid --- .../net/wireless/intel/iwlwifi/cfg/ax210.c | 15 --------- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 4 --- .../net/wireless/intel/iwlwifi/cfg/rf-gf.c | 31 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 4 --- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index cf7d91894ab9..ddf3d313da5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -19,14 +19,6 @@ #define IWL_AX210_SMEM_OFFSET 0x400000 #define IWL_AX210_SMEM_LEN 0xD0000 -#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_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" -#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" -#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" -#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" -#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" - static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -130,10 +122,3 @@ 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_A_GF4_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_MA_B_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 02d6df7fa7a8..9f543946b285 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -19,8 +19,6 @@ #define IWL_BZ_SMEM_OFFSET 0x400000 #define IWL_BZ_SMEM_LEN 0xD0000 -#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_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0" #define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0" #define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0" @@ -103,8 +101,6 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = { .low_latency_xtal = true, }; -IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_BZ_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_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 f55c286e83be..7ff5170faaa9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c @@ -5,6 +5,24 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_GF_UCODE_API_MAX 100 + +/* Lowest firmware API version supported */ +#define IWL_GF_UCODE_API_MIN 98 + +#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" +#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" + /* NVM versions */ #define IWL_GF_NVM_VERSION 0x0a1d @@ -22,6 +40,8 @@ const struct iwl_rf_cfg iwl_rf_gf = { .nvm_ver = IWL_GF_NVM_VERSION, .nvm_type = IWL_NVM_EXT, .num_rbds = IWL_NUM_RBDS_HE, + .ucode_api_min = IWL_GF_UCODE_API_MIN, + .ucode_api_max = IWL_GF_UCODE_API_MAX, }; const char iwl_ax210_killer_1675w_name[] = @@ -40,3 +60,14 @@ const char iwl_ax411_killer_1690i_name[] = const char iwl_ax210_name[] = "Intel(R) Wi-Fi 6E AX210 160MHz"; const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; 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); +IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index ab44298d421e..7b70640abf53 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -24,8 +24,6 @@ #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_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" -#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" #define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0" #define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0" #define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0" @@ -100,8 +98,6 @@ const struct iwl_mac_cfg iwl_sc_mac_cfg = { IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_SC_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); From b6b7b33e5acfb942415eb6f5adc4af3b13f1251a Mon Sep 17 00:00:00 2001 From: Itamar Shalev Date: Wed, 9 Jul 2025 23:05:41 +0300 Subject: [PATCH 13/64] wifi: iwlwifi: trans: remove retake_ownership parameter from sw_reset Remove the retake_ownership parameter from the sw_reset function, as it was always set to true and is not needed by other opmodes. Simplify the sw_reset API function. Signed-off-by: Itamar Shalev Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.0a103d021815.I2a3da6f83aa691496a53a548bd73bddd4d4d2db8@changeid --- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 3ec42a4ea801..4e1ef165f058 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -199,7 +199,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu IWL_ERR(trans, "HW error, resetting before reading\n"); /* reset the device */ - err = iwl_trans_sw_reset(trans, true); + err = iwl_trans_sw_reset(trans); if (err) return; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index b6e71c172e7b..810923053053 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -498,9 +498,9 @@ void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) } IWL_EXPORT_SYMBOL(iwl_trans_set_pmi); -int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership) +int iwl_trans_sw_reset(struct iwl_trans *trans) { - return iwl_trans_pcie_sw_reset(trans, retake_ownership); + return iwl_trans_pcie_sw_reset(trans, true); } IWL_EXPORT_SYMBOL(iwl_trans_sw_reset); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 103a36d8ee30..ac37d9613ade 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1096,7 +1096,7 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr, void iwl_trans_set_pmi(struct iwl_trans *trans, bool state); -int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership); +int iwl_trans_sw_reset(struct iwl_trans *trans); void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); From 65d4df4ebeedfc12277cad1230dff3fe0bc6cde4 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:05:42 +0300 Subject: [PATCH 14/64] wifi: iwlwifi: pcie: add a missing include pcie/utils.h needs to include iwl-io.h for the iwl_read/iwl_write calls. Add it. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.716e8b54ebcb.If75c28a85b5ba4c2661bdf4ce20b97dbe7d2abb2@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 031dfdf4bba4..27437d5e099b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -6,6 +6,8 @@ #ifndef __iwl_pcie_utils_h__ #define __iwl_pcie_utils_h__ +#include "iwl-io.h" + void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, From 7c2f3ec7707188d8d5269ae2dce97d7be3e9f261 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Wed, 9 Jul 2025 23:05:43 +0300 Subject: [PATCH 15/64] wifi: iwlwifi: mvm: fix scan request validation The scan request validation function uses bitwise and instead of logical and. Fix it. Signed-off-by: Avraham Stern Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709230308.3fbc1f27871b.I7a8ee91f463c1a2d9d8561c8232e196885d02c43@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 5f30109ca18f..79660138ae97 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -836,7 +836,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, int n_channels) { return ((n_ssids <= PROBE_OPTION_MAX) && - (n_channels <= mvm->fw->ucode_capa.n_scan_channels) & + (n_channels <= mvm->fw->ucode_capa.n_scan_channels) && (ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <= From d1f5f881ac2c5dc185a88c7bfe47d2b3ecbbc501 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 10 Jul 2025 21:28:18 +0300 Subject: [PATCH 16/64] wifi: iwlwifi: mld: fix scan request validation The scan request validation function uses bitwise and instead of logical and. Fix it. Signed-off-by: Avraham Stern Reviewed-by: Daniel Gabay Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.ec7d665f56a4.I416816b491fafa5d3efdf0a4be78356eedf2bd95@changeid --- drivers/net/wireless/intel/iwlwifi/mld/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 63d5d39bb083..479a76a94aa8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -359,7 +359,7 @@ iwl_mld_scan_fits(struct iwl_mld *mld, int n_ssids, struct ieee80211_scan_ies *ies, int n_channels) { return ((n_ssids <= PROBE_OPTION_MAX) && - (n_channels <= mld->fw->ucode_capa.n_scan_channels) & + (n_channels <= mld->fw->ucode_capa.n_scan_channels) && (ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <= iwl_mld_scan_max_template_size())); From 0d17b0c1ab8f18648f66ad17c1b1cc6ceb740a02 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 10 Jul 2025 21:28:19 +0300 Subject: [PATCH 17/64] wifi: iwlwifi: mld: update the P2P device mac before starting the GO When a GO is started, the P2P device mac is updated to indicate that frames for the P2P device mac should be filtered in while the GO is active. However, this configuration is done after the GO is already started so it doesn't take effect. Fix it by updating the P2P device mac before adding the broadcast station, which actually starts the GO. Signed-off-by: Avraham Stern Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.463a0ad545f9.I85a25484d787b65f6a27e794285911e319df0b2d@changeid --- drivers/net/wireless/intel/iwlwifi/mld/ap.c | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ap.c b/drivers/net/wireless/intel/iwlwifi/mld/ap.c index 26511b49d89a..5c59acc8c4c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ap.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ap.c @@ -294,9 +294,20 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, if (ret) return ret; + mld_vif->ap_ibss_active = true; + + if (vif->p2p && mld->p2p_device_vif) { + ret = iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, + FW_CTXT_ACTION_MODIFY); + if (ret) { + mld_vif->ap_ibss_active = false; + goto rm_mcast; + } + } + ret = iwl_mld_add_bcast_sta(mld, vif, link); if (ret) - goto rm_mcast; + goto update_p2p_dev; /* Those keys were configured by the upper layers before starting the * AP. Now that it is started and the bcast and mcast sta were added to @@ -310,12 +321,6 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, iwl_mld_vif_update_low_latency(mld, vif, true, LOW_LATENCY_VIF_TYPE); - mld_vif->ap_ibss_active = true; - - if (vif->p2p && mld->p2p_device_vif) - return iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, - FW_CTXT_ACTION_MODIFY); - /* When the channel context was added, the link is not yet active, so * min_def is always used. Update the PHY again here in case def should * actually be used. @@ -326,6 +331,11 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, return 0; rm_bcast: iwl_mld_remove_bcast_sta(mld, vif, link); +update_p2p_dev: + mld_vif->ap_ibss_active = false; + if (vif->p2p && mld->p2p_device_vif) + iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, + FW_CTXT_ACTION_MODIFY); rm_mcast: iwl_mld_remove_mcast_sta(mld, vif, link); return ret; From 589bc6ec069fd0bb71765a3e4b0257c2ba0984f0 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 10 Jul 2025 21:28:20 +0300 Subject: [PATCH 18/64] wifi: iwlwifi: mld: update expected range response notification version The last version for the range response notification is 10. Update the expected version accordingly. Signed-off-by: Avraham Stern Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.377d24e29ac6.I44119a4e793bba35b46e1d35e2c378ce6f901bfd@changeid --- drivers/net/wireless/intel/iwlwifi/mld/notif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index c0e62d46aba6..ff1a3b9079e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -350,7 +350,7 @@ CMD_VERSIONS(time_sync_confirm_notif, CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify)) CMD_VERSIONS(omi_status_notif, CMD_VER_ENTRY(1, iwl_omi_send_status_notif)) -CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(9, iwl_tof_range_rsp_ntfy)) +CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy)) DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id) DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id) From 0ac7a266c3232dc68ddf03c366c21b5b16975d7e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2025 21:28:21 +0300 Subject: [PATCH 19/64] wifi: iwlwifi: mvm: remove regulatory puncturing setup We don't have puncturing before EHT, and EHT devices aren't supported in iwlmvm, so remove the regulatory puncturing setup code. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.b2a28a99725b.I72ba276cb705c02cea8f68e27ef3935d5120cfee@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ------ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 -- 3 files changed, 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index b28c21c20371..c16946950a8a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -165,12 +165,6 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, mvm->lar_regdom_set = true; mvm->mcc_src = src_id; - if (!iwl_puncturing_is_allowed_in_bios(mvm->bios_enable_puncturing, - le16_to_cpu(resp->mcc))) - ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING); - else - __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags); - iwl_mei_set_country_code(__le16_to_cpu(resp->mcc)); out: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f0d459766365..cf6177b43262 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1372,7 +1372,6 @@ struct iwl_mvm { struct iwl_mvm_acs_survey *acs_survey; bool statistics_clear; - u32 bios_enable_puncturing; }; /* Extract MVM priv from op_mode and _hw */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 1c05a3d8e424..7dfae8b1a43e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1397,8 +1397,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, } } - mvm->bios_enable_puncturing = iwl_uefi_get_puncturing(&mvm->fwrt); - if (iwl_mvm_has_new_tx_api(mvm)) { /* * If we have the new TX/queue allocation API initialize them From 278881748143186d7839c0cc1aa9f3d8d90a755f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2025 21:28:22 +0300 Subject: [PATCH 20/64] wifi: iwlwifi: mld: restrict puncturing disable to FM Later RFs will always do puncturing, regardless of BIOS configuration, and earlier RFs aren't supported in MLD. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.6fa9c44964c1.I46a4cd744a769ec2ac3c8f9a04882140449394b8@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mcc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c index 19cb562e7a73..680abda95adb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c @@ -177,11 +177,15 @@ iwl_mld_get_regdomain(struct iwl_mld *mld, mld->mcc_src = resp->source_id; - if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing, - le16_to_cpu(resp->mcc))) - ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING); - else - __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mld->hw->flags); + /* FM is the earliest supported and later always do puncturing */ + if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM) { + if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing, + le16_to_cpu(resp->mcc))) + ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING); + else + __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, + mld->hw->flags); + } out: kfree(resp); From 200945e6a6837b33386a8c9233950046170f36c3 Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 10 Jul 2025 21:28:23 +0300 Subject: [PATCH 21/64] wifi: iwlwifi: add suppress_cmd_error_once() API Add iwl_trans_suppress_cmd_error_once() function to be called by the op modes instead of directly checking the trans status bits. This hides the trans internal implementation details from callers. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.e061ae241fd3.Ie2043c4e237196ebcfe195006d3d76371de48a55@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 +++++ drivers/net/wireless/intel/iwlwifi/mld/debugfs.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index ac37d9613ade..aa0c8ca82805 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1230,6 +1230,11 @@ static inline u16 iwl_trans_get_num_rbds(struct iwl_trans *trans) return result; } +static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans) +{ + set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status); +} + /***************************************************** * PCIe handling *****************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index 75cc1d8bb90c..cc052b0aa53f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -86,7 +86,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mld *mld, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) { mld->fw_status.do_not_dump_once = true; - set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mld->trans->status); + iwl_trans_suppress_cmd_error_once(mld->trans); } /* take the return value to make compiler happy - it will diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 86a87ea89916..f0e184c8a81a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1134,7 +1134,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) { set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); - set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status); + iwl_trans_suppress_cmd_error_once(mvm->trans); } /* take the return value to make compiler happy - it will fail anyway */ From c7236b1f5ac42e475f2413b76ff24936c6c96c95 Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 10 Jul 2025 21:28:24 +0300 Subject: [PATCH 22/64] wifi: iwlwifi: add iwl_trans_device_enabled() API add iwl_trans_device_enabled() function to be called by the op modes instead of directly checking the trans status bits. This hides the trans internal implementation details. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.bb957ba9e130.I6ab825caf41308fb0f7aa1c266f50457fd0c496e@changeid --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 +++++ drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index fd60a6816150..ed72199c0b21 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2978,7 +2978,7 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig_type) { - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) + if (!iwl_trans_device_enabled(fwrt->trans)) return -EIO; if (iwl_trans_dbg_ini_valid(fwrt->trans)) { @@ -3180,7 +3180,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) goto out; } - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) { + if (!iwl_trans_device_enabled(fwrt->trans)) { IWL_ERR(fwrt, "Device is not enabled - cannot dump error\n"); goto out; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 4e1ef165f058..f633124979ab 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -490,7 +490,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) struct iwl_pc_data *pc_data; u8 count; - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) { + if (!iwl_trans_device_enabled(fwrt->trans)) { IWL_ERR(fwrt, "DEVICE_ENABLED bit is not set. Aborting dump.\n"); return; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index aa0c8ca82805..200a8d5d5bb6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1235,6 +1235,11 @@ static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans) set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status); } +static inline bool iwl_trans_device_enabled(struct iwl_trans *trans) +{ + return test_bit(STATUS_DEVICE_ENABLED, &trans->status); +} + /***************************************************** * PCIe handling *****************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 79660138ae97..9ce1ce0dab34 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -3547,7 +3547,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify) if (!(mvm->scan_status & type)) return 0; - if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) { + if (!iwl_trans_device_enabled(mvm->trans)) { ret = 0; goto out; } From 11c5cc9ec6d9e09cd052f5a75574f5989b37f16c Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 10 Jul 2025 21:28:25 +0300 Subject: [PATCH 23/64] wifi: iwlwifi: add iwl_trans_is_dead() API Add iwl_trans_is_dead() function to be called by the op modes instead of directly checking the trans status bits. This hides the trans internal implementation details from callers. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.cd89d8013261.I214b7ffbabc393593fb57831d61d1a9ffa318a1e@changeid --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 +++++ drivers/net/wireless/intel/iwlwifi/mld/mld.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index ed72199c0b21..2879be4b8fcb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -3186,7 +3186,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) } /* there's no point in fw dump if the bus is dead */ - if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { + if (iwl_trans_is_dead(fwrt->trans)) { IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); goto out; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 2dff87c07512..6d983fe2ee44 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1545,7 +1545,7 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) if (!IS_ERR(op_mode)) return op_mode; - if (test_bit(STATUS_TRANS_DEAD, &drv->trans->status)) + if (iwl_trans_is_dead(drv->trans)) break; #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 200a8d5d5bb6..d0e658801c2e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1240,6 +1240,11 @@ static inline bool iwl_trans_device_enabled(struct iwl_trans *trans) return test_bit(STATUS_DEVICE_ENABLED, &trans->status); } +static inline bool iwl_trans_is_dead(struct iwl_trans *trans) +{ + return test_bit(STATUS_TRANS_DEAD, &trans->status); +} + /***************************************************** * PCIe handling *****************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 7ade5b714457..12682396bdc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -630,7 +630,7 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode, enum iwl_fw_error_type type) { struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); - bool trans_dead = test_bit(STATUS_TRANS_DEAD, &mld->trans->status); + bool trans_dead = iwl_trans_is_dead(mld->trans); if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) IWL_ERR(mld, "Command queue full!\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 7dfae8b1a43e..eb1b2f182be5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -2053,7 +2053,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) IWL_ERR(mvm, "Command queue full!\n"); - else if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) && + else if (!iwl_trans_is_dead(mvm->trans) && !test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status)) iwl_mvm_dump_nic_error_log(mvm); From 5bc741e1b1d580fe73d48b14c5b111c413de2acf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2025 21:28:26 +0300 Subject: [PATCH 24/64] wifi: iwlwifi: fix HE/EHT capabilities The default capabilities were set to much more than the hardware currently is intended to support, and then masked off for only the GL MAC type. However, this was due to some miscommunication and is incorrect, it should've been masked off for all current and planned MACs/RFs. Instead of doing this removing and adding of capabilities, simply list the ones that currently apply to all devices. If this changes for a new device type we can change the code, but at least the driver won't erroneously advertise some capabilities that aren't actually implemented in hardware. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.69b9dac7d906.I7885499bc80453d5a84285ec927f5e89f9adfb21@changeid --- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 78 ++++--------------- 1 file changed, 15 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 1e4162f1bb44..4424443d2328 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -663,6 +663,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | (IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED << IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS), .phy_cap_info[10] = @@ -691,44 +693,26 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .has_eht = true, .eht_cap_elem = { .mac_cap_info[0] = - IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 | - IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC, - .mac_cap_info[1] = - IEEE80211_EHT_MAC_CAP1_UNSOL_EPCS_PRIO_ACCESS, + IEEE80211_EHT_MAC_CAP0_OM_CONTROL, .phy_cap_info[0] = IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | - IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, .phy_cap_info[1] = IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK, .phy_cap_info[3] = - IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, + IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK, .phy_cap_info[4] = - IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | - IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI, .phy_cap_info[5] = FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK, IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US) | - IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | - IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP, - .phy_cap_info[6] = - IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | - IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP, + IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF, .phy_cap_info[8] = IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA | IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA, @@ -796,6 +780,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242, .phy_cap_info[9] = + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED << IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS, }, @@ -822,9 +807,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .has_eht = true, .eht_cap_elem = { .mac_cap_info[0] = - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2, + IEEE80211_EHT_MAC_CAP0_OM_CONTROL, .phy_cap_info[0] = IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI, @@ -1039,48 +1022,17 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2); } + /* prior RFs don't have HE, HR RF doesn't have this, later have it */ + if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR1 || + CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR2) + iftype_data->he_cap.he_cap_elem.phy_cap_info[9] &= + ~(IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU); + if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap) iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; - switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) { - case IWL_CFG_RF_TYPE_GF: - case IWL_CFG_RF_TYPE_FM: - case IWL_CFG_RF_TYPE_WH: - case IWL_CFG_RF_TYPE_PE: - iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; - if (!is_ap) - iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; - break; - } - - if (CSR_HW_REV_TYPE(trans->info.hw_rev) == IWL_CFG_MAC_TYPE_GL && - iftype_data->eht_cap.has_eht) { - iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &= - ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &= - ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | - IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &= - ~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | - IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] &= - ~IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK; - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &= - ~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | - IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |= - IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF; - } - if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_BCAST_TWT; From 61be9803f322ab46f31ba944c6ef7de195891f64 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 10 Jul 2025 21:28:27 +0300 Subject: [PATCH 25/64] wifi: iwlwifi: mvm: set gtk id also in older FWs We use gtk[i].id, but it is not even set in older FW APIs (iwl_wowlan_status_v6 and iwl_wowlan_status_v7). Set it also in older FWs. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.e91e49590414.I27d2fdbed1c54aee59929fa11ec169f07e159406@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index d9d678fbdaab..546fda8de5de 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2210,6 +2210,7 @@ static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status, status->gtk[0].len = data->key_len; status->gtk[0].flags = data->key_flags; + status->gtk[0].id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK; memcpy(status->gtk[0].key, data->key, sizeof(data->key)); @@ -2532,6 +2533,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) * currently used key. */ status->gtk[0].flags = v6->gtk.key_index | BIT(7); + status->gtk[0].id = v6->gtk.key_index; } else if (notif_ver == 7) { struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; From 5bb88e36cf13b18510f837a25580a518687566d4 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 10 Jul 2025 21:28:28 +0300 Subject: [PATCH 26/64] wifi: iwlwifi: mvm: always set the key idx in gtk_seq For older APIs, gtk_seq[0].key_id will be set to -1, while other code assumes that it will always be a valid gtk key idx. Since the FW does provide the idx for those APIs, simply set it. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.2a5a5e4d7b19.Ib795751119070495c0c95526cd36bd7f87594f56@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 546fda8de5de..e6806ef56e73 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1689,7 +1689,7 @@ static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm, } static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status, - union iwl_all_tsc_rsc *sc) + union iwl_all_tsc_rsc *sc, u8 key_idx) { int i; @@ -1704,7 +1704,7 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status, &status->gtk_seq[0].aes.seq[i]); } status->gtk_seq[0].valid = true; - status->gtk_seq[0].key_id = -1; + status->gtk_seq[0].key_id = key_idx; /* PTK TX counter */ status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) | @@ -1795,7 +1795,6 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, if (!status->gtk_seq[i].valid) continue; - /* Handle the case where we know the key ID */ if (status->gtk_seq[i].key_id == key->keyidx) { s8 new_key_id = -1; @@ -1806,13 +1805,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, /* Don't install a new key's value to an old key */ if (new_key_id != key->keyidx) iwl_mvm_set_key_rx_seq_idx(key, status, i); - continue; } - - /* handle the case where we didn't, last key only */ - if (status->gtk_seq[i].key_id == -1 && - (!status->num_of_gtk_rekeys)) - iwl_mvm_set_key_rx_seq_idx(key, status, i); } } @@ -2522,7 +2515,8 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) v6->gtk.tkip_mic_key, sizeof(v6->gtk.tkip_mic_key)); - iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc); + iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc, + v6->gtk.key_index); /* hardcode the key length to 16 since v6 only supports 16 */ status->gtk[0].len = 16; @@ -2541,7 +2535,8 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) if (!status) goto out_free_resp; - iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc); + iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc, + v7->gtk[0].key_flags & IWL_WOWLAN_GTK_IDX_MASK); iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]); iwl_mvm_convert_igtk(status, &v7->igtk[0]); } else { From 50dc4270ba606085de1d209b0e714b78872c9098 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 10 Jul 2025 21:28:29 +0300 Subject: [PATCH 27/64] wifi: iwlwifi: mvm: don't remove all keys in mcast rekey In the current code, if there was a rekey, we remove all the existing keys from mac80211, then re-add the ones that the FW sent with ieee80211_gtk_rekey_add, (newer FW will send also the existing GTKs/BIGTKs) and then update the sequence number. Instead of removing and re-adding the existing keys for no good reason, we can just update the sequence of all keys, also of the ones that are going to be replaced, and update again after the replace. This change is required because ieee80211_gtk_rekey_add is going to be changed to lookup the cipher from the old key instead of receiving it as an argument, and for this it will need the old key(s), so we can't remove all keys. Note that with this change, in case that a key that existed before wowlan is replaced, mac80211 will now call the driver to remove the old key and add the new one (as opposed the previous behaviour, in which the key was removed by the driver itself). Of course we don't want to run the set_key callbacks in this case, so just return early. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.10091484e38e.I45daf089189f606f3879ca4538fb46303d761710@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 68 ++++++++----------- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++ 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index e6806ef56e73..8930f8e3c0de 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1795,17 +1795,8 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, if (!status->gtk_seq[i].valid) continue; - if (status->gtk_seq[i].key_id == key->keyidx) { - s8 new_key_id = -1; - - if (status->num_of_gtk_rekeys) - new_key_id = status->gtk[0].flags & - IWL_WOWLAN_GTK_IDX_MASK; - - /* Don't install a new key's value to an old key */ - if (new_key_id != key->keyidx) - iwl_mvm_set_key_rx_seq_idx(key, status, i); - } + if (status->gtk_seq[i].key_id == key->keyidx) + iwl_mvm_set_key_rx_seq_idx(key, status, i); } } @@ -1894,17 +1885,10 @@ iwl_mvm_d3_update_igtk_bigtk(struct iwl_wowlan_status_data *status, struct ieee80211_key_conf *key, struct iwl_multicast_key_data *key_data) { - if (status->num_of_gtk_rekeys && key_data->len) { - /* remove rekeyed key */ - ieee80211_remove_key(key); - } else { - struct ieee80211_key_seq seq; + struct ieee80211_key_seq seq; - iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, - &seq, - key->cipher); - ieee80211_set_key_rx_seq(key, 0, &seq); - } + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key->cipher); + ieee80211_set_key_rx_seq(key, 0, &seq); } static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, @@ -1945,18 +1929,13 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, return; } keyidx = key->keyidx; - /* The current key is always sent by the FW, even if it wasn't - * rekeyed during D3. - * We remove an existing key if it has the same index as - * a new key + /* + * Update the seq even if there was a rekey. If there was a + * rekey, we will update again after replacing the key */ - if (status->num_of_gtk_rekeys && - ((status->gtk[0].len && keyidx == status->gtk[0].id) || - (status->gtk[1].len && keyidx == status->gtk[1].id))) { - ieee80211_remove_key(key); - } else { - iwl_mvm_set_key_rx_seq(key, data->status); - } + if ((status->gtk[0].len && keyidx == status->gtk[0].id) || + (status->gtk[1].len && keyidx == status->gtk[1].id)) + iwl_mvm_set_key_rx_seq(key, status); break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -2020,8 +1999,12 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, sizeof(status->gtk[i].key)); key = ieee80211_gtk_rekey_add(vif, conf, link_id); - if (IS_ERR(key)) + if (IS_ERR(key)) { + /* FW may send also the old keys */ + if (PTR_ERR(key) == -EALREADY) + continue; return false; + } for (j = 0; j < ARRAY_SIZE(status->gtk_seq); j++) { if (!status->gtk_seq[j].valid || @@ -2041,14 +2024,16 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, struct ieee80211_vif *vif, u32 cipher, struct iwl_multicast_key_data *key_data) { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, WOWLAN_KEY_MAX_SIZE); struct ieee80211_key_conf *key_config; struct ieee80211_key_seq seq; int link_id = vif->active_links ? __ffs(vif->active_links) : -1; + s8 keyidx = key_data->id; conf->cipher = cipher; - conf->keyidx = key_data->id; + conf->keyidx = keyidx; if (!key_data->len) return true; @@ -2075,19 +2060,26 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, memcpy(conf->key, key_data->key, conf->keylen); key_config = ieee80211_gtk_rekey_add(vif, conf, link_id); - if (IS_ERR(key_config)) - return false; + if (IS_ERR(key_config)) { + /* FW may send also the old keys */ + return PTR_ERR(key_config) == -EALREADY; + } ieee80211_set_key_rx_seq(key_config, 0, &seq); - if (key_config->keyidx == 4 || key_config->keyidx == 5) { - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + if (keyidx == 4 || keyidx == 5) { struct iwl_mvm_vif_link_info *mvm_link; link_id = link_id < 0 ? 0 : link_id; mvm_link = mvmvif->link[link_id]; + if (mvm_link->igtk) + mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; mvm_link->igtk = key_config; } + if (vif->type == NL80211_IFTYPE_STATION && (keyidx == 6 || keyidx == 7)) + rcu_assign_pointer(mvmvif->bcn_prot.keys[keyidx - 6], + key_config); + return true; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index c16946950a8a..28a4630964d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4612,6 +4612,10 @@ int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + /* When resuming from wowlan, FW already knows about the newest keys */ + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) + return 0; + guard(mvm)(mvm); return __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key); } From 8580be27e2cd9cbfa754e884c8bb705776204d18 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 10 Jul 2025 21:28:30 +0300 Subject: [PATCH 28/64] wifi: iwlwifi: mld: don't remove all keys in mcast rekey In the current code, if there was a rekey, we remove all the existing keys from mac80211, then re-add the ones that the FW sent with ieee80211_gtk_rekey_add, (newer FW will send also the existing GTKs/BIGTKs) and then update the sequence number. Instead of removing and re-adding the existing keys for no good reason, we can just update the sequence of all keys, also of the ones that are going to be replaced, and update again after the replace. This change is required because ieee80211_gtk_rekey_add is going to be changed to lookup the cipher from the old key instead of receiving it as an argument, and for this it will need the old key(s), so we can't remove all keys. Note that with this change, in case that a key that existed before wowlan is replaced, mac80211 will now call the driver to remove the old key and add the new one (as opposed the previous behaviour, in which the key was removed by the driver itself). Of course we don't want to run the set_key callbacks in this case, so just return early. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.f0b5e19f77f5.I958f4926f168cdad6d4d7720ebde2f5e812b297d@changeid --- drivers/net/wireless/intel/iwlwifi/mld/d3.c | 112 +++++++------------ drivers/net/wireless/intel/iwlwifi/mld/key.c | 12 ++ drivers/net/wireless/intel/iwlwifi/mld/mld.h | 2 + 3 files changed, 53 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index af12b3d81899..26255246a320 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -646,51 +646,6 @@ iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key, } } -static void -iwl_mld_d3_update_mcast_key(struct iwl_mld *mld, - struct ieee80211_vif *vif, - struct iwl_mld_wowlan_status *wowlan_status, - struct ieee80211_key_conf *key, - struct iwl_mld_mcast_key_data *key_data) -{ - if (key->keyidx != key_data->id && - (key->keyidx < 4 || key->keyidx > 5)) { - IWL_ERR(mld, - "Unexpected keyId mismatch. Old keyId:%d, New keyId:%d\n", - key->keyidx, key_data->id); - return; - } - - /* All installed keys are sent by the FW, even weren't - * rekeyed during D3. - * We remove an existing key if it has the same index as - * a new key and a rekey has occurred during d3 - */ - if (wowlan_status->num_of_gtk_rekeys && key_data->len) { - if (key->keyidx == 4 || key->keyidx == 5) { - struct iwl_mld_vif *mld_vif = - iwl_mld_vif_from_mac80211(vif); - struct iwl_mld_link *mld_link; - int link_id = vif->active_links ? - __ffs(vif->active_links) : 0; - - mld_link = iwl_mld_link_dereference_check(mld_vif, - link_id); - if (WARN_ON(!mld_link)) - return; - - if (mld_link->igtk == key) - mld_link->igtk = NULL; - mld->num_igtks--; - } - - ieee80211_remove_key(key); - return; - } - - iwl_mld_set_key_rx_seq(key, key_data); -} - static void iwl_mld_update_ptk_rx_seq(struct iwl_mld *mld, struct iwl_mld_wowlan_status *wowlan_status, @@ -759,8 +714,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->gtk_cipher = key->cipher; status_idx = key->keyidx == wowlan_status->gtk[1].id; - iwl_mld_d3_update_mcast_key(data->mld, vif, wowlan_status, key, - &wowlan_status->gtk[status_idx]); + iwl_mld_set_key_rx_seq(key, &wowlan_status->gtk[status_idx]); break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -772,9 +726,8 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, return; data->igtk_cipher = key->cipher; - iwl_mld_d3_update_mcast_key(data->mld, vif, - wowlan_status, - key, &wowlan_status->igtk); + if (key->keyidx == wowlan_status->igtk.id) + iwl_mld_set_key_rx_seq(key, &wowlan_status->igtk); } if (key->keyidx == 6 || key->keyidx == 7) { if (WARN_ON(data->bigtk_cipher && @@ -783,9 +736,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->bigtk_cipher = key->cipher; status_idx = key->keyidx == wowlan_status->bigtk[1].id; - iwl_mld_d3_update_mcast_key(data->mld, vif, - wowlan_status, key, - &wowlan_status->bigtk[status_idx]); + iwl_mld_set_key_rx_seq(key, &wowlan_status->bigtk[status_idx]); } break; default: @@ -795,7 +746,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->num_keys++; } -static bool +static void iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, struct iwl_mld *mld, struct iwl_mld_mcast_key_data *key_data, @@ -822,7 +773,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); if (!key_data->len) - return true; + return; switch (cipher) { case WLAN_CIPHER_SUITE_CCMP: @@ -854,7 +805,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, memcpy(conf.conf.key, key_data->key, conf.conf.keylen); key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id); if (IS_ERR(key_config)) - return false; + return; iwl_mld_set_key_rx_seq(key_config, key_data); @@ -862,10 +813,25 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, if (key_config->keyidx == 4 || key_config->keyidx == 5) { struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link_conf); - mld_link->igtk = key_config; - mld->num_igtks++; + + /* If we had more than one rekey, mac80211 will tell us to + * remove the old and add the new so we will update the IGTK in + * drv_set_key + */ + if (mld_link->igtk && mld_link->igtk != key_config) { + /* mark the old IGTK as not in FW */ + mld_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; + mld_link->igtk = key_config; + } + } + + /* Also keep track of the new BIGTK */ + if ((key_config->keyidx == 6 || key_config->keyidx == 7) && + vif->type == NL80211_IFTYPE_STATION) { + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); + + rcu_assign_pointer(mld_vif->bigtks[key_config->keyidx - 6], key_config); } - return true; } static void @@ -877,23 +843,20 @@ iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, int i; for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++) - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->gtk[i], - link_conf, - key_iter_data->gtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->gtk[i], + link_conf, + key_iter_data->gtk_cipher); - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->igtk, - link_conf, key_iter_data->igtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->igtk, + link_conf, key_iter_data->igtk_cipher); for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++) - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->bigtk[i], - link_conf, - key_iter_data->bigtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->bigtk[i], + link_conf, + key_iter_data->bigtk_cipher); } static bool @@ -1851,6 +1814,7 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld) goto err; } + mld->fw_status.resuming = true; mld->fw_status.in_d3 = false; mld->scan.last_start_time_jiffies = jiffies; @@ -1926,6 +1890,8 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld) mld->fw_status.in_hw_restart = true; ret = 1; out: + mld->fw_status.resuming = false; + if (resume_data.wowlan_status) { kfree(resume_data.wowlan_status->wake_packet); kfree(resume_data.wowlan_status); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.c b/drivers/net/wireless/intel/iwlwifi/mld/key.c index 0eff13e5ffd5..13462a5ad79a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/key.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/key.c @@ -129,6 +129,12 @@ static int iwl_mld_add_key_to_fw(struct iwl_mld *mld, u32 sta_mask, bool tkip = key->cipher == WLAN_CIPHER_SUITE_TKIP; int max_key_len = sizeof(cmd.u.add.key); +#ifdef CONFIG_PM_SLEEP + /* If there was a rekey in wowlan, FW already has the key */ + if (mld->fw_status.resuming) + return 0; +#endif + if (WARN_ON(!sta_mask)) return -EINVAL; @@ -160,6 +166,12 @@ static void iwl_mld_remove_key_from_fw(struct iwl_mld *mld, u32 sta_mask, .u.remove.key_flags = cpu_to_le32(key_flags), }; +#ifdef CONFIG_PM_SLEEP + /* If there was a rekey in wowlan, FW already removed the key */ + if (mld->fw_status.resuming) + return; +#endif + if (WARN_ON(!sta_mask)) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index 241ab3a00e56..a9e59378f142 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -149,6 +149,7 @@ * @running: true if the firmware is running * @do_not_dump_once: true if firmware dump must be prevented once * @in_d3: indicates FW is in suspend mode and should be resumed + * @resuming: indicates the driver is resuming from wowlan * @in_hw_restart: indicates that we are currently in restart flow. * rather than restarted. Should be unset upon restart. * @radio_kill: bitmap of radio kill status @@ -237,6 +238,7 @@ struct iwl_mld { do_not_dump_once:1, #ifdef CONFIG_PM_SLEEP in_d3:1, + resuming:1, #endif in_hw_restart:1; From 8513096a3457374dba0b39782923b1e80f88a5ae Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2025 21:28:31 +0300 Subject: [PATCH 29/64] wifi: iwlwifi: pcie: don't WARN on bad firmware input Don't WARN, which results in a useless backtrace, but just use IWL_FW_CHECK() instead. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.4aedc0979beb.I3bd4d4296c7245261651603708456b7c67f55539@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index 224f4a68c7a8..b38ec90f8342 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -25,6 +25,7 @@ #include "iwl-op-mode.h" #include "internal.h" #include "fw/api/tx.h" +#include "fw/dbg.h" #include "pcie/utils.h" /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** @@ -1638,13 +1639,11 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != trans->conf.cmd_queue, - "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, trans->conf.cmd_queue, sequence, txq->read_ptr, - txq->write_ptr)) { - iwl_print_hex_error(trans, pkt, 32); + if (IWL_FW_CHECK(trans, txq_id != trans->conf.cmd_queue, + "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d pkt=%*phN\n", + txq_id, trans->conf.cmd_queue, sequence, txq->read_ptr, + txq->write_ptr, 32, pkt)) return; - } spin_lock_bh(&txq->lock); From ea045a0de3b9de8f917f0149783bae8dc14fcbb2 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Thu, 10 Jul 2025 21:28:32 +0300 Subject: [PATCH 30/64] wifi: iwlwifi: add support for accepting raw DSM tables by firmware Firmware would assert on undefined bits in DSM-originated DWs. With this change, Firmware introduces a fail-safe mechanism and removes the assert behavior. This ensures robustness when handling raw DSM table data. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250710212632.eee871df03c9.I2be2eaa16437e84aa1be0c6c95ec334034ce7e50@changeid --- .../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 1 + .../net/wireless/intel/iwlwifi/fw/debugfs.c | 6 ++++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 ++ .../wireless/intel/iwlwifi/fw/regulatory.c | 35 ++++++++++++++----- .../wireless/intel/iwlwifi/fw/regulatory.h | 4 +++ .../wireless/intel/iwlwifi/mld/regulatory.c | 30 ++++++++++++---- 6 files changed, 63 insertions(+), 16 deletions(-) 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 5cdc09d465d4..28ccac7d2142 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -787,6 +787,7 @@ struct iwl_lari_config_change_cmd { /* Activate UNII-1 (5.2GHz) for World Wide */ #define ACTIVATE_5G2_IN_WW_MASK BIT(4) #define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F +#define CHAN_STATE_ACTIVE_BITMAP_CMD_V12 0x7F /** * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 803ba35e7501..3b0e8c43ba4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -389,6 +389,12 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v) " %d: %d\n", IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT, has_capa); + has_capa = fw_has_capa(&fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE) ? 1 : 0; + seq_printf(seq, + " %d: %d\n", + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE, + has_capa); seq_puts(seq, "fw_api_ver:\n"); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index dc1db563c5eb..b7c1ab7a3006 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -407,6 +407,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * for CA from BIOS. * @IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT: supports %TAS_UHB_ALLOWED_CANADA * @IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT: external FSEQ image support + * @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of + * handling raw DSM table data. * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -517,6 +519,7 @@ enum iwl_ucode_tlv_capa { * during assert handling even if the dump isn't split */ IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0), + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1), NUM_IWL_UCODE_TLV_CAPA /* * This construction make both sparse (which cannot increment the previous diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 74b90bd92c48..3d6d1a85bb51 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -579,6 +579,8 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, { int ret; u32 value; + bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE); u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw, WIDE_ID(REGULATORY_AND_NVM_GROUP, LARI_CONFIG_CHANGE), 1); @@ -593,17 +595,22 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_11AX_ALLOW_BITMAP; cmd->oem_11ax_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); if (!ret) { - value &= DSM_UNII4_ALLOW_BITMAP; + if (!has_raw_dsm_capa) + value &= DSM_UNII4_ALLOW_BITMAP; /* Since version 9, bits 4 and 5 are supported - * regardless of this capability. + * regardless of this capability, By pass this masking + * if firmware has capability of accepting raw DSM table. */ - if (cmd_ver < 9 && + if (!has_raw_dsm_capa && cmd_ver < 9 && !fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA)) value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | @@ -614,13 +621,17 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); if (!ret) { - if (cmd_ver < 8) + if (!has_raw_dsm_capa) + value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; + + if (!has_raw_dsm_capa && cmd_ver < 8) value &= ~ACTIVATE_5G2_IN_WW_MASK; /* Since version 12, bits 5 and 6 are supported - * regardless of this capability. + * regardless of this capability, By pass this masking + * if firmware has capability of accepting raw DSM table. */ - if (cmd_ver < 12 && + if (!has_raw_dsm_capa && cmd_ver < 12 && !fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA)) value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11; @@ -633,13 +644,19 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, cmd->oem_uhb_allow_bitmap = cpu_to_le32(value); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP; cmd->force_disable_channels_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_EDT_ALLOWED_BITMAP; cmd->edt_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_wbem(fwrt, &value); if (!ret) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 9bed3d573b1e..a07c512b6ed4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -159,6 +159,10 @@ enum iwl_dsm_unii4_bitmap { DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |\ DSM_VALUE_UNII4_CANADA_EN_MSK) +#define DSM_11AX_ALLOW_BITMAP 0xF +#define DSM_EDT_ALLOWED_BITMAP 0x7ffff0 +#define DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP 0x7FF + enum iwl_dsm_values_rfi { DSM_VALUE_RFI_DLVR_DISABLE = BIT(0), DSM_VALUE_RFI_DDR_DISABLE = BIT(1), diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 326c300470ea..887f1fb2f926 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -238,34 +238,50 @@ void iwl_mld_configure_lari(struct iwl_mld *mld) struct iwl_lari_config_change_cmd cmd = { .config_bitmap = iwl_get_lari_config_bitmap(fwrt), }; + bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE); int ret; u32 value; ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_11AX_ALLOW_BITMAP; cmd.oem_11ax_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); - if (!ret) - cmd.oem_unii4_allow_bitmap = - cpu_to_le32(value &= DSM_UNII4_ALLOW_BITMAP); + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_UNII4_ALLOW_BITMAP; + cmd.oem_unii4_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; cmd.chan_state_active_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value); if (!ret) cmd.oem_uhb_allow_bitmap = cpu_to_le32(value); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP; cmd.force_disable_channels_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_EDT_ALLOWED_BITMAP; cmd.edt_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_wbem(fwrt, &value); if (!ret) From 9f9c762705d937a1284c3289583351d549746c02 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Fri, 11 Jul 2025 18:34:15 +0300 Subject: [PATCH 31/64] wifi: iwlwifi: mvm: remove IWL_MVM_ESR_EXIT_FAIL_ENTRY EHT capable devices will only use iwlmld. So we can remove EMLSR code from iwlmvm. As part of removal, remove IWL_MVM_ESR_EXIT_FAIL_ENTRY EMLSR state. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.a69dc9c6ba49.I7f9fbc1f954b4c118625a4b8d51c72f3c84936da@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/link.c | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 - drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 42 ------------------- 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 851869c0bd50..9e46ac3e573a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -18,8 +18,7 @@ HOW(EXIT_COEX) \ HOW(EXIT_BANDWIDTH) \ HOW(EXIT_CSA) \ - HOW(EXIT_LINK_USAGE) \ - HOW(EXIT_FAIL_ENTRY) + HOW(EXIT_LINK_USAGE) static const char *const iwl_mvm_esr_states_names[] = { #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index cf6177b43262..5754e83c6fcd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -374,7 +374,6 @@ struct iwl_mvm_vif_link_info { * preventing the enablement of EMLSR * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link - * @IWL_MVM_ESR_EXIT_FAIL_ENTRY: Exit EMLSR due to entry failure */ enum iwl_mvm_esr_state { IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1, @@ -390,7 +389,6 @@ enum iwl_mvm_esr_state { IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000, IWL_MVM_ESR_EXIT_CSA = 0x100000, IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000, - IWL_MVM_ESR_EXIT_FAIL_ENTRY = 0x400000, }; #define IWL_MVM_BLOCK_ESR_REASONS 0xffff diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index eb1b2f182be5..c7a3fbc49b59 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -161,43 +161,6 @@ static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm, iwl_mvm_get_primary_link(vif)); } -static void iwl_mvm_rx_esr_trans_fail_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_esr_trans_fail_notif *notif = (void *)pkt->data; - struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm); - u8 fw_link_id = le32_to_cpu(notif->link_id); - struct ieee80211_bss_conf *bss_conf; - - if (IS_ERR_OR_NULL(vif)) - return; - - IWL_DEBUG_INFO(mvm, "Failed to %s eSR on link %d, reason %d\n", - le32_to_cpu(notif->activation) ? "enter" : "exit", - le32_to_cpu(notif->link_id), - le32_to_cpu(notif->err_code)); - - /* we couldn't go back to single link, disconnect */ - if (!le32_to_cpu(notif->activation)) { - iwl_mvm_connection_loss(mvm, vif, "emlsr exit failed"); - return; - } - - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, false); - if (IWL_FW_CHECK(mvm, !bss_conf, - "FW reported failure to activate EMLSR on a non-existing link: %d\n", - fw_link_id)) - return; - - /* - * We failed to activate the second link and enter EMLSR, we need to go - * back to single link. - */ - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_FAIL_ENTRY, - bss_conf->link_id); -} - static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { @@ -526,10 +489,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF, iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED, struct iwl_umac_scan_channel_survey_notif), - RX_HANDLER_GRP(MAC_CONF_GROUP, EMLSR_TRANS_FAIL_NOTIF, - iwl_mvm_rx_esr_trans_fail_notif, - RX_HANDLER_ASYNC_LOCKED_WIPHY, - struct iwl_esr_trans_fail_notif), }; #undef RX_HANDLER #undef RX_HANDLER_GRP @@ -660,7 +619,6 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { HCMD_NAME(STA_REMOVE_CMD), HCMD_NAME(STA_DISABLE_TX_CMD), HCMD_NAME(ROC_CMD), - HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF), HCMD_NAME(ROC_NOTIF), HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF), HCMD_NAME(MISSED_VAP_NOTIF), From 91b9f31d5c88789e29733369eec92408ce6e97ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Jul 2025 18:34:16 +0300 Subject: [PATCH 32/64] wifi: iwlwifi: mvm: remove extra link ID Since the iwlmvm driver now only supports pre-MLO devices, we no longer need to maintain an extra explicit link ID; valid MAC IDs and link IDs are both in the range 0-3 and the driver always has a 1:1 MAC/link correspondence. Thus, simply use the MAC ID as the link ID as well. This simplifies some further work because on RX the ID is given but there is some confusion about which versions of the firmware report MAC and which report link ID. While at it, clarify iwl_mvm_handle_missed_beacons_notif() code a bit so it doesn't look like an invalid vif pointer is being used. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.005aa5fe34fe.Ib0c1187453f46ce49dc0f9f58907ee21f5b52634@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 - drivers/net/wireless/intel/iwlwifi/mvm/link.c | 59 ++----------------- .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 34 ++++------- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 22 +------ drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 24 ++++---- .../wireless/intel/iwlwifi/mvm/time-event.c | 25 +------- 7 files changed, 34 insertions(+), 138 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index ab3d78c1e20c..4c2d0a4098cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1462,9 +1462,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm) RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL); } - for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++) - RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL); - mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA; /* reset quota debouncing buffer - 0xff will yield invalid data */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 9e46ac3e573a..2269acc55c0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -49,20 +49,6 @@ static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask) #undef NAME_PR } -static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvm_vif) -{ - u32 i; - - lockdep_assert_held(&mvm->mutex); - - for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++) - if (!rcu_access_pointer(mvm->link_id_to_link_conf[i])) - return i; - - return IWL_MVM_FW_LINK_ID_INVALID; -} - static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, struct iwl_link_config_cmd *cmd, enum iwl_ctxt_action action) @@ -79,25 +65,15 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, return ret; } -int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf) +void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_conf->link_id]; - if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { - link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, - mvmvif); - if (link_info->fw_link_id >= - ARRAY_SIZE(mvm->link_id_to_link_conf)) - return -EINVAL; - - rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], - link_conf); - } - - return 0; + if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) + link_info->fw_link_id = mvmvif->id; } int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -109,14 +85,11 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_link_config_cmd cmd = {}; unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); - int ret; if (WARN_ON_ONCE(!link_info)) return -EINVAL; - ret = iwl_mvm_set_link_mapping(mvm, vif, link_conf); - if (ret) - return ret; + iwl_mvm_set_link_fw_id(mvm, vif, link_conf); /* Update SF - Disable if needed. if this fails, SF might still be on * while many macs are bound, which is forbidden - so fail the binding. @@ -373,24 +346,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return ret; } -int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm_vif_link_info *link_info = - mvmvif->link[link_conf->link_id]; - - /* mac80211 thought we have the link, but it was never configured */ - if (WARN_ON(!link_info || - link_info->fw_link_id >= - ARRAY_SIZE(mvm->link_id_to_link_conf))) - return -EINVAL; - - RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], - NULL); - return 0; -} - int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { @@ -400,10 +355,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_link_config_cmd cmd = {}; int ret; - ret = iwl_mvm_unset_link_mapping(mvm, vif, link_conf); - if (ret) - return 0; - cmd.link_id = cpu_to_le32(link_info->fw_link_id); link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; cmd.spec_link_id = link_conf->link_id; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 9098a36530cc..d9d61e25807a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1586,7 +1586,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, u32 id = le32_to_cpu(mb->link_id); union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; u32 mac_type; - int link_id = -1; + int link_id; u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, MISSED_BEACONS_NOTIFICATION, 0); @@ -1602,20 +1602,6 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, if (new_notif_ver) notif_ver = new_notif_ver; - /* before version four the ID in the notification refers to mac ID */ - if (notif_ver < 4) { - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); - bss_conf = &vif->bss_conf; - } else { - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false); - - if (!bss_conf) - return; - - vif = bss_conf->vif; - link_id = bss_conf->link_id; - } - IWL_DEBUG_INFO(mvm, "missed bcn %s_id=%u, consecutive=%u (%u)\n", notif_ver < 4 ? "mac" : "link", @@ -1623,9 +1609,16 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, le32_to_cpu(mb->consec_missed_beacons), le32_to_cpu(mb->consec_missed_beacons_since_last_rx)); + /* + * starting from version 4 the ID is link ID, but driver + * uses link ID == MAC ID, so always treat as MAC ID + */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); if (!vif) return; + bss_conf = &vif->bss_conf; + link_id = bss_conf->link_id; mac_type = iwl_mvm_get_mac_type(vif); IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type); @@ -1875,16 +1868,15 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, } else { struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; u32 link_id = le32_to_cpu(notif->link_id); - struct ieee80211_bss_conf *bss_conf = - iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true); - if (!bss_conf) + /* we use link ID == MAC ID */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, link_id, true); + if (!vif) goto out_unlock; id = link_id; - mac_link_id = bss_conf->link_id; - vif = bss_conf->vif; - csa_active = bss_conf->csa_active; + mac_link_id = vif->bss_conf.link_id; + csa_active = vif->bss_conf.csa_active; } mvmvif = iwl_mvm_vif_from_mac80211(vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 28a4630964d6..448492d94926 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1806,9 +1806,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, vif->driver_flags = IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC; - ret = iwl_mvm_set_link_mapping(mvm, vif, &vif->bss_conf); - if (ret) - goto out; + iwl_mvm_set_link_fw_id(mvm, vif, &vif->bss_conf); /* * Not much to do here. The stack will not allow interface @@ -2009,7 +2007,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->monitor_on = false; out: - iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf); if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) { iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5754e83c6fcd..6c024a681508 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1177,8 +1177,6 @@ struct iwl_mvm { struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; - struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_FW_MAX_LINK_ID + 1]; - u8 *error_recovery_buf; #ifdef CONFIG_IWLWIFI_LEDS @@ -1485,20 +1483,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu) lockdep_is_held(&mvm->mutex)); } -static inline struct ieee80211_bss_conf * -iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu) -{ - if (IWL_FW_CHECK(mvm, link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf), - "erroneous FW link ID: %d\n", link_id)) - return NULL; - - if (rcu) - return rcu_dereference(mvm->link_id_to_link_conf[link_id]); - - return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id], - lockdep_is_held(&mvm->mutex)); -} - static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, @@ -2097,15 +2081,13 @@ u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band); /* Links */ void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link); -int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf); +void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf, u32 changes, bool active); -int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf); int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 8eb0aa448c85..8fae0d41b119 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -877,28 +877,28 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, u32 rx_bytes[MAC_INDEX_AUX] = {}; int fw_link_id; - for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf); + /* driver uses link ID == MAC ID */ + for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->vif_id_to_mac); fw_link_id++) { struct iwl_stats_ntfy_per_link *link_stats; - struct ieee80211_bss_conf *bss_conf; - struct iwl_mvm_vif *mvmvif; struct iwl_mvm_vif_link_info *link_info; + struct iwl_mvm_vif *mvmvif; + struct ieee80211_vif *vif; int link_id; int sig; - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, - false); - if (!bss_conf) + vif = iwl_mvm_rcu_dereference_vif_id(mvm, fw_link_id, false); + if (!vif) continue; - if (bss_conf->vif->type != NL80211_IFTYPE_STATION) + if (vif->type != NL80211_IFTYPE_STATION) continue; - link_id = bss_conf->link_id; + link_id = vif->bss_conf.link_id; if (link_id >= ARRAY_SIZE(mvmvif->link)) continue; - mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif); + mvmvif = iwl_mvm_vif_from_mac80211(vif); link_info = mvmvif->link[link_id]; if (!link_info) continue; @@ -916,8 +916,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, if (link_info->phy_ctxt && link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) - iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif, - link_id); + iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); /* make sure that beacon statistics don't go backwards with TCM * request to clear statistics @@ -927,8 +926,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, mvmvif->link[link_id]->beacon_stats.num_beacons; sig = -le32_to_cpu(link_stats->beacon_filter_average_energy); - iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info, - bss_conf); + iwl_mvm_update_link_sig(vif, sig, link_info, &vif->bss_conf); if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX, "invalid mvmvif id: %d", mvmvif->id)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 478408f802d9..aa653782d6d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -958,40 +958,19 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_session_prot_notif *notif = (void *)pkt->data; - unsigned int ver = - iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, - SESSION_PROTECTION_NOTIF, 2); int id = le32_to_cpu(notif->mac_link_id); struct ieee80211_vif *vif; struct iwl_mvm_vif *mvmvif; - unsigned int notif_link_id; rcu_read_lock(); - if (ver <= 2) { - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); - } else { - struct ieee80211_bss_conf *link_conf = - iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true); - - if (!link_conf) - goto out_unlock; - - notif_link_id = link_conf->link_id; - vif = link_conf->vif; - } - + /* note we use link ID == MAC ID */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); if (!vif) goto out_unlock; mvmvif = iwl_mvm_vif_from_mac80211(vif); - if (WARN(ver > 2 && mvmvif->time_event_data.link_id >= 0 && - mvmvif->time_event_data.link_id != notif_link_id, - "SESSION_PROTECTION_NOTIF was received for link %u, while the current time event is on link %u\n", - notif_link_id, mvmvif->time_event_data.link_id)) - goto out_unlock; - /* The vif is not a P2P_DEVICE, maintain its time_event_data */ if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { struct iwl_mvm_time_event_data *te_data = From f2829c89e296005ba1dbd95515d5b95790b9be0c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Jul 2025 18:34:17 +0300 Subject: [PATCH 33/64] wifi: iwlwifi: mvm/mld: use average RSSI for beacons When connected to an AP, the PHY will typically be tuned to a higher bandwidth than the beacons are transmitted on, as they are normally only transmitted on 20 MHz. This can mean that another STA is simultaneously transmitting on another channel of the higher bandwidth, and apparently this energy may be taken into account by the PHY, resulting in elevated energy readings. To work around this, track the firmware's corrected beacon energy data and replace the RSSI in beacons by that. The replacement happens for all beacons received in the context of the current MAC or link (depending on FW version), in which case the filters will drop all else. For a scan, which is only tuning to 20 MHz channels, the MAC/link ID will be one that isn't found (the AUX ID 4), and no correction will be done (nor is it needed.) Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.324bfe7027ff.I160f947e7aab30e0110a7019ed46186e57c3de14@changeid --- .../wireless/intel/iwlwifi/fw/api/datapath.h | 5 + .../net/wireless/intel/iwlwifi/fw/api/rx.h | 24 ++++- drivers/net/wireless/intel/iwlwifi/mld/link.c | 20 ++++ drivers/net/wireless/intel/iwlwifi/mld/link.h | 6 ++ drivers/net/wireless/intel/iwlwifi/mld/mld.c | 1 + .../net/wireless/intel/iwlwifi/mld/notif.c | 4 + drivers/net/wireless/intel/iwlwifi/mld/rx.c | 73 +++++++++++++-- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 ++ drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 91 +++++++++++++++++-- 11 files changed, 223 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 9c88bb280609..6c8e6874a5e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -124,6 +124,11 @@ enum iwl_data_path_subcmd_ids { */ TLC_MNG_UPDATE_NOTIF = 0xF7, + /** + * @BEACON_FILTER_IN_NOTIF: &struct iwl_beacon_filter_notif + */ + BEACON_FILTER_IN_NOTIF = 0xF8, + /** * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 7cf6d6ac7430..d751789998ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -194,7 +194,9 @@ enum iwl_rx_mpdu_amsdu_info { }; enum iwl_rx_mpdu_mac_phy_band { + /* whether or not this is MAC or LINK depends on the API */ IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK = 0x0f, + IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK = 0x0f, IWL_RX_MPDU_MAC_PHY_BAND_PHY_MASK = 0x30, IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK = 0xc0, }; @@ -671,7 +673,7 @@ struct iwl_rx_mpdu_desc { */ __le16 phy_info; /** - * @mac_phy_band: MAC ID, PHY ID, band; + * @mac_phy_band: MAC/link ID, PHY ID, band; * see &enum iwl_rx_mpdu_mac_phy_band */ u8 mac_phy_band; @@ -1019,4 +1021,24 @@ struct iwl_rfh_queue_config { struct iwl_rfh_queue_data data[]; } __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */ +/** + * struct iwl_beacon_filter_notif_v1 - beacon filter notification + * @average_energy: average energy for the received beacon + * @mac_id: MAC ID the beacon was received for + */ +struct iwl_beacon_filter_notif_v1 { + __le32 average_energy; + __le32 mac_id; +} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_1 */ + +/** + * struct iwl_beacon_filter_notif - beacon filter notification + * @average_energy: average energy for the received beacon + * @link_id: link ID the beacon was received for + */ +struct iwl_beacon_filter_notif { + __le32 average_energy; + __le32 link_id; +} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_2 */ + #endif /* __iwl_fw_api_rx_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index c65ac6ecbd1d..ff237f78a468 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -783,6 +783,7 @@ iwl_mld_init_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link, { mld_link->vif = link->vif; mld_link->link_id = link->link_id; + mld_link->average_beacon_energy = 0; iwl_mld_init_internal_sta(&mld_link->bcast_sta); iwl_mld_init_internal_sta(&mld_link->mcast_sta); @@ -1216,3 +1217,22 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, return grade; } EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_link_grade); + +void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt) +{ + const struct iwl_beacon_filter_notif *notif = (const void *)pkt->data; + u32 link_id = le32_to_cpu(notif->link_id); + struct ieee80211_bss_conf *link_conf = + iwl_mld_fw_id_to_link_conf(mld, link_id); + struct iwl_mld_link *mld_link; + + if (IWL_FW_CHECK(mld, !link_conf, "invalid link ID %d\n", link_id)) + return; + + mld_link = iwl_mld_link_from_mac80211(link_conf); + if (WARN_ON_ONCE(!mld_link)) + return; + + mld_link->average_beacon_energy = le32_to_cpu(notif->average_energy); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h index 39f04aae5579..881823be07ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h @@ -41,6 +41,8 @@ struct iwl_probe_resp_data { * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS. * @mon_sta: station used for TX injection in monitor interface. * @link_id: over the air link ID + * @average_beacon_energy: average beacon energy for beacons received during + * client connections * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs, * but higher layers work differently, so we store the keys here for * later installation. @@ -85,6 +87,7 @@ struct iwl_mld_link { /* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */ struct ieee80211_key_conf *ap_early_keys[6]; + u32 average_beacon_energy; bool silent_deactivation; struct iwl_probe_resp_data __rcu *probe_resp_data; }; @@ -150,4 +153,7 @@ void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld, struct ieee80211_bss_conf *link_conf, enum ieee80211_sta_rx_bandwidth bw); +void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt); + #endif /* __iwl_mld_link_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 12682396bdc3..e7cbfb9009af 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -255,6 +255,7 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = { HCMD_NAME(ESR_MODE_NOTIF), HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(TLC_MNG_UPDATE_NOTIF), + HCMD_NAME(BEACON_FILTER_IN_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), }; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index ff1a3b9079e2..4bfed90c30c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -351,6 +351,7 @@ CMD_VERSIONS(time_sync_confirm_notif, CMD_VERSIONS(omi_status_notif, CMD_VER_ENTRY(1, iwl_omi_send_status_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)) DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id) DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id) @@ -368,6 +369,7 @@ DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif, mac_id) #define iwl_mld_cancel_omi_status_notif iwl_mld_always_cancel DEFINE_SIMPLE_CANCELLATION(ftm_resp, iwl_tof_range_rsp_ntfy, request_id) +DEFINE_SIMPLE_CANCELLATION(beacon_filter, iwl_beacon_filter_notif, link_id) /** * DOC: Handlers for fw notifications @@ -460,6 +462,8 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = { time_sync_confirm_notif, RX_HANDLER_ASYNC) RX_HANDLER_OF_LINK(DATA_PATH_GROUP, OMI_SEND_STATUS_NOTIF, omi_status_notif) + RX_HANDLER_OF_LINK(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF, + beacon_filter_notif) RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, ftm_resp_notif) }; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index ce0093d5c638..3d19cec3f696 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -143,7 +143,55 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld, } EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_pass_packet_to_mac80211); -static void iwl_mld_fill_signal(struct iwl_mld *mld, +static bool iwl_mld_used_average_energy(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_bss_conf *link_conf; + struct iwl_mld_link *mld_link; + + if (unlikely(!hdr || link_id < 0)) + return false; + + if (likely(!ieee80211_is_beacon(hdr->frame_control))) + return false; + + /* + * if link ID is >= valid ones then that means the RX + * was on the AUX link and no correction is needed + */ + if (link_id >= mld->fw->ucode_capa.num_links) + return false; + + /* for the link conf lookup */ + guard(rcu)(); + + link_conf = rcu_dereference(mld->fw_id_to_bss_conf[link_id]); + if (!link_conf) + return false; + + mld_link = iwl_mld_link_from_mac80211(link_conf); + if (!mld_link) + return false; + + /* + * If we know the link by link ID then the frame was + * received for the link, so by filtering it means it + * was from the AP the link is connected to. + */ + + /* skip also in case we don't have it (yet) */ + if (!mld_link->average_beacon_energy) + return false; + + IWL_DEBUG_STATS(mld, "energy override by average %d\n", + mld_link->average_beacon_energy); + rx_status->signal = -mld_link->average_beacon_energy; + return true; +} + +static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, struct ieee80211_rx_status *rx_status, struct iwl_mld_rx_phy_data *phy_data) { @@ -159,9 +207,11 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld, IWL_DEBUG_STATS(mld, "energy in A %d B %d, and max %d\n", energy_a, energy_b, max_energy); + if (iwl_mld_used_average_energy(mld, link_id, hdr, rx_status)) + return; + rx_status->signal = max_energy; - rx_status->chains = - (rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK); rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; } @@ -1160,7 +1210,10 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld, } #endif -static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb, +/* Note: hdr can be NULL */ +static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, + struct sk_buff *skb, struct iwl_mld_rx_phy_data *phy_data, int queue) { @@ -1182,7 +1235,7 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb, phy_data->phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE) rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE; - iwl_mld_fill_signal(mld, rx_status, phy_data); + iwl_mld_fill_signal(mld, link_id, hdr, rx_status, phy_data); /* This may be overridden by iwl_mld_rx_he() to HE_RU */ switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { @@ -1733,7 +1786,7 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi, struct sk_buff *skb; size_t mpdu_desc_size = sizeof(*mpdu_desc); bool drop = false; - u8 crypto_len = 0, band; + u8 crypto_len = 0, band, link_id; u32 pkt_len = iwl_rx_packet_payload_len(pkt); u32 mpdu_len; enum iwl_mld_reorder_result reorder_res; @@ -1822,7 +1875,10 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi, SCHED_SCAN_PASS_ALL_STATE_FOUND; } - iwl_mld_rx_fill_status(mld, skb, &phy_data, queue); + link_id = u8_get_bits(mpdu_desc->mac_phy_band, + IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK); + + iwl_mld_rx_fill_status(mld, link_id, hdr, skb, &phy_data, queue); if (iwl_mld_rx_crypto(mld, sta, hdr, rx_status, mpdu_desc, queue, le32_to_cpu(pkt->len_n_flags), &crypto_len)) @@ -2035,7 +2091,8 @@ void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi, rx_status->freq = ieee80211_channel_to_frequency(channel, rx_status->band); - iwl_mld_rx_fill_status(mld, skb, &phy_data, queue); + /* link ID is ignored for NULL header */ + iwl_mld_rx_fill_status(mld, -1, NULL, skb, &phy_data, queue); /* No more radiotap info should be added after this point. * Mark it as mac header for upper layers to know where diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 448492d94926..9e9e76b67ef0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1769,6 +1769,8 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) return; + mvmvif->deflink.average_beacon_energy = 0; + INIT_DELAYED_WORK(&mvmvif->csa_work, iwl_mvm_channel_switch_disconnect_wk); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 6c024a681508..9e83c671f4e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -304,6 +304,8 @@ struct iwl_probe_resp_data { * @mcast_sta: multicast station * @phy_ctxt: phy context allocated to this link, if any * @bf_data: beacon filtering data + * @average_beacon_energy: average beacon energy for beacons received during + * client connections */ struct iwl_mvm_vif_link_info { u8 bssid[ETH_ALEN]; @@ -342,6 +344,7 @@ struct iwl_mvm_vif_link_info { u16 mgmt_queue; struct iwl_mvm_link_bf_data bf_data; + u32 average_beacon_energy; }; /** @@ -2074,6 +2077,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); + /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index c7a3fbc49b59..892b1564677b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -489,6 +489,11 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF, iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED, struct iwl_umac_scan_channel_survey_notif), + RX_HANDLER_GRP(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF, + iwl_mvm_rx_beacon_filter_notif, + RX_HANDLER_ASYNC_LOCKED, + /* same size as v1 */ + struct iwl_beacon_filter_notif), }; #undef RX_HANDLER #undef RX_HANDLER_GRP @@ -659,6 +664,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(ESR_MODE_NOTIF), HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST), + HCMD_NAME(BEACON_FILTER_IN_NOTIF), HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), HCMD_NAME(RX_QUEUES_NOTIFICATION), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 077aadbf95db..4b57ca56e1f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -246,13 +246,62 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, ieee80211_rx_napi(mvm->hw, sta, skb, napi); } +static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) +{ + struct iwl_mvm_vif *mvm_vif; + struct ieee80211_vif *vif; + u32 id; + + if (unlikely(!hdr || !desc)) + return false; + + if (likely(!ieee80211_is_beacon(hdr->frame_control))) + return false; + + /* for the link conf lookup */ + guard(rcu)(); + + /* MAC or link ID depending on FW, but driver has them equal */ + id = u8_get_bits(desc->mac_phy_band, + IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK); + + /* >= means AUX MAC/link ID, no energy correction needed then */ + if (id >= ARRAY_SIZE(mvm->vif_id_to_mac)) + return false; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + if (!vif) + return false; + + mvm_vif = iwl_mvm_vif_from_mac80211(vif); + + /* + * If we know the MAC by MAC or link ID then the frame was + * received for the link, so by filtering it means it was + * from the AP the link is connected to. + */ + + /* skip also in case we don't have it (yet) */ + if (!mvm_vif->deflink.average_beacon_energy) + return false; + + IWL_DEBUG_STATS(mvm, "energy override by average %d\n", + mvm_vif->deflink.average_beacon_energy); + rx_status->signal = -mvm_vif->deflink.average_beacon_energy; + return true; +} + static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, struct ieee80211_rx_status *rx_status, u32 rate_n_flags, int energy_a, int energy_b) { int max_energy; - u32 rate_flags = rate_n_flags; energy_a = energy_a ? -energy_a : S8_MIN; energy_b = energy_b ? -energy_b : S8_MIN; @@ -261,9 +310,11 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n", energy_a, energy_b, max_energy); + if (iwl_mvm_used_average_energy(mvm, desc, hdr, rx_status)) + return; + rx_status->signal = max_energy; - rx_status->chains = - (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK); rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; } @@ -1906,8 +1957,11 @@ static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta) /* * Note: requires also rx_status->band to be prefilled, as well * as phy_data (apart from phy_data->info_type) + * Note: desc/hdr may be NULL */ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, struct sk_buff *skb, struct iwl_mvm_rx_phy_data *phy_data, int queue) @@ -1962,7 +2016,7 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm, rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel, rx_status->band); - iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, + iwl_mvm_get_signal_strength(mvm, desc, hdr, rx_status, rate_n_flags, phy_data->energy_a, phy_data->energy_b); /* using TLV format and must be after all fixed len fields */ @@ -2215,7 +2269,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, goto out; } - iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue); + iwl_mvm_rx_fill_status(mvm, desc, hdr, skb, &phy_data, queue); if (sta) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); @@ -2445,7 +2499,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; - iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue); + iwl_mvm_rx_fill_status(mvm, NULL, NULL, skb, &phy_data, queue); /* no more radio tap info should be put after this point. * @@ -2548,3 +2602,28 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, out: rcu_read_unlock(); } + +void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + /* MAC or link ID in v1/v2, but driver has the IDs equal */ + struct iwl_beacon_filter_notif *notif = (void *)pkt->data; + u32 id = le32_to_cpu(notif->link_id); + struct iwl_mvm_vif *mvm_vif; + struct ieee80211_vif *vif; + + /* >= means AUX MAC/link ID, no energy correction needed then */ + if (IWL_FW_CHECK(mvm, id >= ARRAY_SIZE(mvm->vif_id_to_mac), + "invalid link ID %d\n", id)) + return; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); + if (!vif) + return; + + mvm_vif = iwl_mvm_vif_from_mac80211(vif); + + mvm_vif->deflink.average_beacon_energy = + le32_to_cpu(notif->average_energy); +} From bf6ce412d8fad3ae26bed3e9a1167cef8224d926 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Fri, 11 Jul 2025 18:34:18 +0300 Subject: [PATCH 34/64] wifi: iwlwifi: mvm: Add dump handler to iwl_mvm Implement a dump handler in the iwl_mvm operation mode to collect firmware dump upon trigger from trans layer. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.366fc31fd551.I976cb17edd85a461043c7a4c7f4895bfaec9174a@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 892b1564677b..c7f08cde1f72 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -2119,6 +2119,17 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode, iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data); } +static void iwl_mvm_dump(struct iwl_op_mode *op_mode) +{ + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + struct iwl_fw_runtime *fwrt = &mvm->fwrt; + + if (!iwl_trans_fw_running(fwrt->trans)) + return; + + iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL); +} + #ifdef CONFIG_PM_SLEEP static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode) { @@ -2181,4 +2192,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops_mq = { IWL_MVM_COMMON_OPS, .rx = iwl_mvm_rx_mq, .rx_rss = iwl_mvm_rx_mq_rss, + .dump = iwl_mvm_dump, }; From e3fd06d1d8869747e02a022e3c9045a3187f3aa5 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:19 +0300 Subject: [PATCH 35/64] wifi: iwlwifi: mvm: remove support for REDUCE_TX_POWER_CMD ver 6 and 7 These versions are no longer used in any of our devices. Remove them. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.05fabbda0a2f.Id55eeb4f337eb52163621ca202d97a3539bf3f53@changeid --- .../net/wireless/intel/iwlwifi/fw/api/power.h | 48 ------------------- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 14 ++---- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 -- 3 files changed, 4 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 23140205ccb9..df70b32cfced 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -341,50 +341,6 @@ struct iwl_dev_tx_power_cmd_v5 { __le32 timer_period; } __packed; /* TX_REDUCED_POWER_API_S_VER_5 */ -/** - * struct iwl_dev_tx_power_cmd_v6 - TX power reduction command version 6 - * @per_chain: per chain restrictions - * @enable_ack_reduction: enable or disable close range ack TX power - * reduction. - * @per_chain_restriction_changed: is per_chain_restriction has changed - * from last command. used if set_mode is - * IWL_TX_POWER_MODE_SET_SAR_TIMER. - * note: if not changed, the command is used for keep alive only. - * @reserved: reserved (padding) - * @timer_period: timer in milliseconds. if expires FW will change to default - * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER - */ -struct iwl_dev_tx_power_cmd_v6 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; - u8 enable_ack_reduction; - u8 per_chain_restriction_changed; - u8 reserved[2]; - __le32 timer_period; -} __packed; /* TX_REDUCED_POWER_API_S_VER_6 */ - -/** - * struct iwl_dev_tx_power_cmd_v7 - TX power reduction command version 7 - * @per_chain: per chain restrictions - * @enable_ack_reduction: enable or disable close range ack TX power - * reduction. - * @per_chain_restriction_changed: is per_chain_restriction has changed - * from last command. used if set_mode is - * IWL_TX_POWER_MODE_SET_SAR_TIMER. - * note: if not changed, the command is used for keep alive only. - * @reserved: reserved (padding) - * @timer_period: timer in milliseconds. if expires FW will change to default - * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER - * @flags: reduce power flags. - */ -struct iwl_dev_tx_power_cmd_v7 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; - u8 enable_ack_reduction; - u8 per_chain_restriction_changed; - u8 reserved[2]; - __le32 timer_period; - __le32 flags; -} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */ - /** * struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8 * @per_chain: per chain restrictions @@ -429,8 +385,6 @@ struct iwl_dev_tx_power_cmd_per_band { * @v3: version 3 part of the command * @v4: version 4 part of the command * @v5: version 5 part of the command - * @v6: version 6 part of the command - * @v7: version 7 part of the command * @v8: version 8 part of the command */ struct iwl_dev_tx_power_cmd_v3_v8 { @@ -440,8 +394,6 @@ struct iwl_dev_tx_power_cmd_v3_v8 { struct iwl_dev_tx_power_cmd_v3 v3; struct iwl_dev_tx_power_cmd_v4 v4; struct iwl_dev_tx_power_cmd_v5 v5; - struct iwl_dev_tx_power_cmd_v6 v6; - struct iwl_dev_tx_power_cmd_v7 v7; struct iwl_dev_tx_power_cmd_v8 v8; }; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4c2d0a4098cc..749fb8441190 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -888,17 +888,11 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) len = sizeof(cmd_v9_v10.v9); n_subbands = IWL_NUM_SUB_BANDS_V1; per_chain = &cmd_v9_v10.v9.per_chain[0][0]; - } else if (cmd_ver >= 7) { - len = sizeof(cmd.v7); + } else if (cmd_ver == 8) { + len = sizeof(cmd.v8); n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = cmd.v7.per_chain[0][0]; - cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags); - if (cmd_ver == 8) - len = sizeof(cmd.v8); - } else if (cmd_ver == 6) { - len = sizeof(cmd.v6); - n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = cmd.v6.per_chain[0][0]; + per_chain = cmd.v8.per_chain[0][0]; + cmd.v8.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags); } else if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) { len = sizeof(cmd.v5); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 9e9e76b67ef0..fa9d5e0b6609 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1515,10 +1515,6 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, len = sizeof(cmd_v9_v10.v9); else if (cmd_ver == 8) len = sizeof(cmd.v8); - else if (cmd_ver == 7) - len = sizeof(cmd.v7); - else if (cmd_ver == 6) - len = sizeof(cmd.v6); else if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) len = sizeof(cmd.v5); From 100f38b0aeca07ccdd11a9f452d42ec6b81c8a5b Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:20 +0300 Subject: [PATCH 36/64] wifi: iwlwifi: mld: remove support for REDUCE_TX_POWER_CMD ver 9 iwlmld was planned to be used for HR, which has version 9, but it was decided at the end to use iwlmvm for HR, so iwlmld only needs to support version 10. Remove version 9 support. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.aeeb617abfae.I05101972506180644c42be5096c1b2afa36c625a@changeid --- .../net/wireless/intel/iwlwifi/mld/power.c | 10 +------ .../wireless/intel/iwlwifi/mld/regulatory.c | 29 ++++--------------- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c index 8cc276041360..f664b277adf7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c @@ -377,23 +377,15 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld, u16 u_tx_power = tx_power == IWL_DEFAULT_MAX_TX_POWER ? IWL_DEV_MAX_TX_POWER : 8 * tx_power; struct iwl_dev_tx_power_cmd cmd = { - /* Those fields sit on the same place for v9 and v10 */ .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK), .common.pwr_restriction = cpu_to_le16(u_tx_power), }; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - int len = sizeof(cmd.common); + int len = sizeof(cmd.common) + sizeof(cmd.v10); if (WARN_ON(!mld_link)) return -ENODEV; cmd.common.link_id = cpu_to_le32(mld_link->fw_id); - if (cmd_ver == 10) - len += sizeof(cmd.v10); - else if (cmd_ver == 9) - len += sizeof(cmd.v9); - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 887f1fb2f926..b82ddd629e24 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -120,37 +120,20 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) u32 cmd_id = REDUCE_TX_POWER_CMD; struct iwl_dev_tx_power_cmd cmd = { .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), + .v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags), }; - __le16 *per_chain; int ret; - u16 len = sizeof(cmd.common); - u32 n_subbands; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - if (cmd_ver == 10) { - len += sizeof(cmd.v10); - n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = &cmd.v10.per_chain[0][0][0]; - cmd.v10.flags = - cpu_to_le32(mld->fwrt.reduced_power_flags); - } else if (cmd_ver == 9) { - len += sizeof(cmd.v9); - n_subbands = IWL_NUM_SUB_BANDS_V1; - per_chain = &cmd.v9.per_chain[0][0]; - } else { - return -EOPNOTSUPP; - } /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */ - ret = iwl_sar_fill_profile(&mld->fwrt, per_chain, - IWL_NUM_CHAIN_TABLES, - n_subbands, prof_a, prof_b); + ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0], + IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2, + prof_a, prof_b); /* return on error or if the profile is disabled (positive number) */ if (ret) return ret; - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); + return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, + sizeof(cmd.common) + sizeof(cmd.v10)); } int iwl_mld_init_sar(struct iwl_mld *mld) From 9696454c920382d8c856a9c2ae4703af4b416e0b Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:21 +0300 Subject: [PATCH 37/64] wifi: iwlwifi: remove an unused struct iwl_reduce_tx_power_cmd is not used anywhere, remove it. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.313285673570.I87c646f8b9b83d63c7c6c293cc5d454c32d852c2@changeid --- drivers/net/wireless/intel/iwlwifi/fw/api/power.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index df70b32cfced..786b3bf4b448 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -255,19 +255,6 @@ struct iwl_uapsd_misbehaving_ap_notif { u8 reserved[3]; } __packed; -/** - * struct iwl_reduce_tx_power_cmd - TX power reduction command - * REDUCE_TX_POWER_CMD = 0x9f - * @flags: (reserved for future implementation) - * @mac_context_id: id of the mac ctx for which we are reducing TX power. - * @pwr_restriction: TX power restriction in dBms. - */ -struct iwl_reduce_tx_power_cmd { - u8 flags; - u8 mac_context_id; - __le16 pwr_restriction; -} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */ - enum iwl_dev_tx_power_cmd_mode { IWL_TX_POWER_MODE_SET_LINK = 0, IWL_TX_POWER_MODE_SET_DEVICE = 1, From 8bec2ec156903e12a8b45a57ae9bca409ead5646 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:22 +0300 Subject: [PATCH 38/64] wifi: iwlwifi: mld: remove support for iwl_geo_tx_power_profiles_cmd version 4 iwlmld was planned to be used for HR/GF, which has version 4, but it was decided at the end to use iwlmvm for HR/GF, so iwlmld only needs to support version 5. Remove version 4 support. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.faeb1e6bac2a.I1a29b16f59b67c103d1f91dedee27e04cd7fdfdd@changeid --- .../wireless/intel/iwlwifi/mld/regulatory.c | 43 +++++-------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index b82ddd629e24..75d2f5cb23a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -71,40 +71,17 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) static int iwl_mld_geo_sar_init(struct iwl_mld *mld) { u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD); - union iwl_geo_tx_power_profiles_cmd cmd; - u16 len; - u32 n_bands; - __le32 sk = cpu_to_le32(0); - int ret; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) != - offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops)); - - cmd.v4.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES); - /* Only set to South Korea if the table revision is 1 */ - if (mld->fwrt.geo_rev == 1) - sk = cpu_to_le32(1); + __le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0); + union iwl_geo_tx_power_profiles_cmd cmd = { + .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES), + .v5.table_revision = sk, + }; + int ret; - if (cmd_ver == 5) { - len = sizeof(cmd.v5); - n_bands = ARRAY_SIZE(cmd.v5.table[0]); - cmd.v5.table_revision = sk; - } else if (cmd_ver == 4) { - len = sizeof(cmd.v4); - n_bands = ARRAY_SIZE(cmd.v4.table[0]); - cmd.v4.table_revision = sk; - } else { - return -EOPNOTSUPP; - } - - BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) != - offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table)); - /* the table is at the same position for all versions, so set use v4 */ - ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v4.table[0][0], - n_bands, BIOS_GEO_MAX_PROFILE_NUM); + ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0], + ARRAY_SIZE(cmd.v5.table[0]), + BIOS_GEO_MAX_PROFILE_NUM); /* It is a valid scenario to not support SAR, or miss wgds table, * but in that case there is no need to send the command. @@ -112,7 +89,7 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) if (ret) return 0; - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); + return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5)); } int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) From 3735526d3e1c852dd9a3c05d82896a456819adc9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 11 Jul 2025 18:34:23 +0300 Subject: [PATCH 39/64] wifi: iwlwifi: mld: support iwl_omi_send_status_notif version 2 The firmware provides the station id, use it since it makes our lives easier. No need to assume we have a single BSS vif, and look up the station id to whom the OMI was sent. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.7d2cd878855f.I8625ebb2c4e1fb484aafd16a07549f2eeb506e08@changeid --- .../wireless/intel/iwlwifi/fw/api/datapath.h | 15 ++++++++-- drivers/net/wireless/intel/iwlwifi/mld/link.c | 30 ++++++++++++++++++- .../net/wireless/intel/iwlwifi/mld/notif.c | 3 +- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 6c8e6874a5e7..ee822a87c42c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -700,12 +700,23 @@ struct iwl_sec_key_cmd { } __packed; /* SEC_KEY_CMD_API_S_VER_1 */ /** - * struct iwl_omi_send_status_notif - OMI status notification + * struct iwl_omi_send_status_notif_v1 - OMI status notification * @success: indicates that the OMI was sent successfully * (currently always set) */ -struct iwl_omi_send_status_notif { +struct iwl_omi_send_status_notif_v1 { __le32 success; } __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_1 */ +/** + * struct iwl_omi_send_status_notif - OMI status notification + * @success: indicates that the OMI was sent successfully + * (currently always set) + * @sta_id: sta_id to which the OMI was sent + */ +struct iwl_omi_send_status_notif { + __le32 success; + __le32 sta_id; +} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_2 */ + #endif /* __iwl_fw_api_datapath_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index ff237f78a468..c48cc3909637 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -649,11 +649,39 @@ void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld, void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { + int ver = iwl_fw_lookup_notif_ver(mld->fw, DATA_PATH_GROUP, + OMI_SEND_STATUS_NOTIF, 1); struct ieee80211_link_sta *link_sta; struct iwl_mld_link *mld_link; struct ieee80211_vif *vif; - vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link); + if (ver == 2) { + const struct iwl_omi_send_status_notif *notif = + (const void *)pkt->data; + u32 sta_id = le32_to_cpu(notif->sta_id); + struct iwl_mld_vif *mld_vif; + + if (IWL_FW_CHECK(mld, sta_id >= mld->fw->ucode_capa.num_stations, + "Invalid station %d\n", sta_id)) + return; + + link_sta = wiphy_dereference(mld->wiphy, + mld->fw_id_to_link_sta[sta_id]); + if (IWL_FW_CHECK(mld, !link_sta, "Station does not exist\n")) + return; + + vif = iwl_mld_sta_from_mac80211(link_sta->sta)->vif; + mld_vif = iwl_mld_vif_from_mac80211(vif); + + mld_link = iwl_mld_link_dereference_check(mld_vif, + link_sta->link_id); + if (WARN(!mld_link, "Link %d does not exist\n", + link_sta->link_id)) + return; + } else { + vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, + &mld_link); + } if (IWL_FW_CHECK(mld, !vif, "unexpected OMI notification\n")) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index 4bfed90c30c5..262d8e25e62a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -349,7 +349,8 @@ CMD_VERSIONS(time_msmt_notif, CMD_VERSIONS(time_sync_confirm_notif, CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify)) CMD_VERSIONS(omi_status_notif, - CMD_VER_ENTRY(1, iwl_omi_send_status_notif)) + CMD_VER_ENTRY(1, iwl_omi_send_status_notif_v1) + CMD_VER_ENTRY(2, iwl_omi_send_status_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)) From 0ce92d548b44649a8de706f9bb9e74a4ed2f18a7 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:24 +0300 Subject: [PATCH 40/64] wifi: iwlwifi: mld: Revert "wifi: iwlwifi: mld: add kunit test for emlsr with bt on" Due to a hw bug, this feature won't be enabled. Revert its tests. This reverts commit f7cc80b871ee ("wifi: iwlwifi: mld: add kunit test for emlsr with bt on") Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.5fdf77497ad2.I1160f1dcff734cb42baa8fbf8aac121a1a24a4c5@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 4 +- drivers/net/wireless/intel/iwlwifi/mld/mlo.h | 4 - .../wireless/intel/iwlwifi/mld/tests/Makefile | 2 +- .../intel/iwlwifi/mld/tests/emlsr_with_bt.c | 140 ------------------ 4 files changed, 2 insertions(+), 148 deletions(-) delete mode 100644 drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index be66a71a0fd7..d002d2772a1d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -693,8 +693,7 @@ s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld, #define IWL_MLD_BT_COEX_ENABLE_EMLSR_RSSI_THRESH -63 #define IWL_MLD_BT_COEX_WIFI_LOSS_THRESH 7 -VISIBLE_IF_IWLWIFI_KUNIT -bool +static bool iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, struct ieee80211_bss_conf *link, bool check_entry) { @@ -723,7 +722,6 @@ iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, struct ieee80211_bss_conf *link, link->link_id, bt_penalty); return bt_penalty < IWL_MLD_BT_COEX_WIFI_LOSS_THRESH; } -EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_bt_allows_emlsr); static u32 iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h index 704f64134798..d936589fe39d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h @@ -163,10 +163,6 @@ void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld); u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif, struct iwl_mld_link_sel_data *a, struct iwl_mld_link_sel_data *b); - -bool iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, - struct ieee80211_bss_conf *link, - bool entry_criteria); #endif void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile index 3e2ae6020613..36317feb923b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o emlsr_with_bt.o +iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o ccflags-y += -I$(src)/../ obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmld-tests.o diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c deleted file mode 100644 index 91556ee5c142..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * KUnit tests for link selection functions - * - * Copyright (C) 2025 Intel Corporation - */ -#include - -#include "utils.h" -#include "mld.h" -#include "mlo.h" - -static const struct emlsr_with_bt_test_case { - const char *desc; - struct { - struct iwl_bt_coex_profile_notif notif; - s32 signal; - bool check_entry; - } input; - bool emlsr_allowed; -} emlsr_with_bt_cases[] = { - { - .desc = "BT penalty(exit) with low rssi 4.5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {7, 9}, - .signal = -69, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(exit) from high rssi 5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {5, 5}, - .signal = -68, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(exit) with low rssi 8: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {4, 5}, - .signal = -69, - .check_entry = false, - }, - .emlsr_allowed = false, - }, - { - .desc = "BT penalty(exit) from high rssi 9: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {9, 9}, - .signal = -68, - .check_entry = false, - }, - .emlsr_allowed = false, - }, - { - .desc = "BT penalty(entry) with low rssi 4.5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {7, 9}, - .signal = -63, - .check_entry = true, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) from high rssi 5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {5, 5}, - .signal = -62, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) with low rssi 8: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {4, 5}, - .signal = -63, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) from high rssi 9: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {9, 9}, - .signal = -62, - .check_entry = true, - }, - .emlsr_allowed = false, - }, -}; - -KUNIT_ARRAY_PARAM_DESC(emlsr_with_bt, emlsr_with_bt_cases, desc); - -static void test_emlsr_with_bt(struct kunit *test) -{ - struct iwl_mld *mld = test->priv; - const struct emlsr_with_bt_test_case *test_param = - (const void *)(test->param_value); - struct ieee80211_vif *vif = - iwlmld_kunit_add_vif(true, NL80211_IFTYPE_STATION); - struct ieee80211_bss_conf *link = iwlmld_kunit_add_link(vif, 1); - bool actual_value = false; - - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - - /* Extract test case parameters */ - link->bss->signal = DBM_TO_MBM(test_param->input.signal); - memcpy(&mld->last_bt_notif, &test_param->input.notif, - sizeof(struct iwl_bt_coex_profile_notif)); - - actual_value = iwl_mld_bt_allows_emlsr(mld, link, - test_param->input.check_entry); - /* Assert that the returned value matches the expected emlsr_allowed */ - KUNIT_EXPECT_EQ(test, actual_value, test_param->emlsr_allowed); -} - -static struct kunit_case emlsr_with_bt_test_cases[] = { - KUNIT_CASE_PARAM(test_emlsr_with_bt, emlsr_with_bt_gen_params), - {}, -}; - -static struct kunit_suite emlsr_with_bt = { - .name = "iwlmld-emlsr-with-bt-tests", - .test_cases = emlsr_with_bt_test_cases, - .init = iwlmld_kunit_test_init, -}; - -kunit_test_suite(emlsr_with_bt); From 7cc5f89bfbc309e8027eda255a1db0957c7fca86 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:25 +0300 Subject: [PATCH 41/64] wifi: iwlwifi: mld: Revert "wifi: iwlwifi: mld: allow EMLSR with 2.4 GHz when BT is ON" Due to a hw bug, this feature won't be enabled. Revert its implementation. This reverts commit 37808a3788fd ("wifi: iwlwifi: mld: allow EMLSR with 2.4 GHz when BT is ON") Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.57755ac3f39d.I63ae0ee3e6cdc9b11175ad15927aaad3b8f8f47a@changeid --- drivers/net/wireless/intel/iwlwifi/mld/coex.c | 8 ++- drivers/net/wireless/intel/iwlwifi/mld/mld.h | 4 +- drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 66 +++---------------- .../intel/iwlwifi/mld/tests/link-selection.c | 6 -- 4 files changed, 18 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/coex.c b/drivers/net/wireless/intel/iwlwifi/mld/coex.c index 32c727b3b391..5f262bd43f21 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/coex.c @@ -24,13 +24,17 @@ int iwl_mld_send_bt_init_conf(struct iwl_mld *mld) void iwl_mld_handle_bt_coex_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { - const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data; + const struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; const struct iwl_bt_coex_profile_notif zero_notif = {}; /* zeroed structure means that BT is OFF */ bool bt_is_active = memcmp(notif, &zero_notif, sizeof(*notif)); - mld->last_bt_notif = *notif; + if (bt_is_active == mld->bt_is_active) + return; + IWL_DEBUG_INFO(mld, "BT was turned %s\n", bt_is_active ? "ON" : "OFF"); + mld->bt_is_active = bt_is_active; + iwl_mld_emlsr_check_bt(mld); } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index a9e59378f142..8bc4749599ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -127,6 +127,7 @@ * cleanup using iwl_mld_free_internal_sta * @netdetect: indicates the FW is in suspend mode with netdetect configured * @p2p_device_vif: points to the p2p device vif if exists + * @bt_is_active: indicates that BT is active * @dev: pointer to device struct. For printing purposes * @trans: pointer to the transport layer * @cfg: pointer to the device configuration @@ -189,7 +190,6 @@ * @ptp_data: data of the PTP clock * @time_sync: time sync data. * @ftm_initiator: FTM initiator data - * @last_bt_notif: last received BT Coex notif */ struct iwl_mld { /* Add here fields that need clean up on restart */ @@ -214,7 +214,7 @@ struct iwl_mld { bool netdetect; #endif /* CONFIG_PM_SLEEP */ struct ieee80211_vif *p2p_device_vif; - struct iwl_bt_coex_profile_notif last_bt_notif; + bool bt_is_active; ); struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX]; /* And here fields that survive a fw restart */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index d002d2772a1d..e57f5388fe77 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -689,40 +689,6 @@ s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld, #undef RSSI_THRESHOLD } -#define IWL_MLD_BT_COEX_DISABLE_EMLSR_RSSI_THRESH -69 -#define IWL_MLD_BT_COEX_ENABLE_EMLSR_RSSI_THRESH -63 -#define IWL_MLD_BT_COEX_WIFI_LOSS_THRESH 7 - -static bool -iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, struct ieee80211_bss_conf *link, - bool check_entry) -{ - int bt_penalty, rssi_thresh; - s32 link_rssi; - - if (WARN_ON_ONCE(!link->bss)) - return false; - - link_rssi = MBM_TO_DBM(link->bss->signal); - rssi_thresh = check_entry ? - IWL_MLD_BT_COEX_ENABLE_EMLSR_RSSI_THRESH : - IWL_MLD_BT_COEX_DISABLE_EMLSR_RSSI_THRESH; - /* No valid RSSI - force to take low rssi */ - if (!link_rssi) - link_rssi = rssi_thresh - 1; - - if (link_rssi > rssi_thresh) - bt_penalty = max(mld->last_bt_notif.wifi_loss_mid_high_rssi[PHY_BAND_24][0], - mld->last_bt_notif.wifi_loss_mid_high_rssi[PHY_BAND_24][1]); - else - bt_penalty = max(mld->last_bt_notif.wifi_loss_low_rssi[PHY_BAND_24][0], - mld->last_bt_notif.wifi_loss_low_rssi[PHY_BAND_24][1]); - - IWL_DEBUG_EHT(mld, "BT penalty for link-id %0X is %d\n", - link->link_id, bt_penalty); - return bt_penalty < IWL_MLD_BT_COEX_WIFI_LOSS_THRESH; -} - static u32 iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, struct ieee80211_vif *vif, @@ -737,8 +703,7 @@ iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, if (WARN_ON_ONCE(!conf)) return IWL_MLD_EMLSR_EXIT_INVALID; - if (link->chandef->chan->band == NL80211_BAND_2GHZ && - !iwl_mld_bt_allows_emlsr(mld, conf, true)) + if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active) ret |= IWL_MLD_EMLSR_EXIT_BT_COEX; if (link->signal < @@ -1076,41 +1041,30 @@ static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); - const struct iwl_bt_coex_profile_notif zero_notif = {}; struct iwl_mld *mld = mld_vif->mld; struct ieee80211_bss_conf *link; unsigned int link_id; - const struct iwl_bt_coex_profile_notif *notif = &mld->last_bt_notif; if (!iwl_mld_vif_has_emlsr_cap(vif)) return; - /* zeroed structure means that BT is OFF */ - if (!memcmp(notif, &zero_notif, sizeof(*notif))) { + if (!mld->bt_is_active) { iwl_mld_retry_emlsr(mld, vif); return; } - for_each_vif_active_link(vif, link, link_id) { - bool emlsr_active, emlsr_allowed; + /* BT is turned ON but we are not in EMLSR, nothing to do */ + if (!iwl_mld_emlsr_active(vif)) + return; + /* In EMLSR and BT is turned ON */ + + for_each_vif_active_link(vif, link, link_id) { if (WARN_ON(!link->chanreq.oper.chan)) continue; - if (link->chanreq.oper.chan->band != NL80211_BAND_2GHZ) - continue; - - emlsr_active = iwl_mld_emlsr_active(vif); - emlsr_allowed = iwl_mld_bt_allows_emlsr(mld, link, - !emlsr_active); - if (emlsr_allowed && !emlsr_active) { - iwl_mld_retry_emlsr(mld, vif); - return; - } - - if (!emlsr_allowed && emlsr_active) { - iwl_mld_exit_emlsr(mld, vif, - IWL_MLD_EMLSR_EXIT_BT_COEX, + if (link->chanreq.oper.chan->band == NL80211_BAND_2GHZ) { + iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BT_COEX, iwl_mld_get_primary_link(vif)); return; } 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 94a037bec1fa..766c24db3613 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c @@ -287,7 +287,6 @@ static void test_iwl_mld_link_pair_allows_emlsr(struct kunit *test) const struct link_pair_case *params = test->param_value; struct iwl_mld *mld = test->priv; struct ieee80211_vif *vif; - struct ieee80211_bss_conf *link; /* link A is the primary and link B is the secondary */ struct iwl_mld_link_sel_data a = { .chandef = params->chandef_a, @@ -311,11 +310,6 @@ static void test_iwl_mld_link_pair_allows_emlsr(struct kunit *test) wiphy_lock(mld->wiphy); - link = wiphy_dereference(mld->wiphy, vif->link_conf[a.link_id]); - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - link = wiphy_dereference(mld->wiphy, vif->link_conf[b.link_id]); - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - /* Simulate channel load */ if (params->primary_link_active) { struct iwl_mld_phy *phy = From 0356e509d373fb9e320f283a2da8f0c0ea9371e0 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:26 +0300 Subject: [PATCH 42/64] wifi: iwlwifi: mld: remove support for iwl_mcc_update_resp versions iwlmld was planned to be used for HR/GF, which has versions 5/6, but it was decided at the end to use iwlmvm for HR/GF, so iwlmld only needs to support version 8. Remove versions 5 and 6 support. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.9c64bfbb16cb.I109bee4d4bf455cbffbb8d2340023338bcab886d@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mcc.c | 52 +------------------- 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c index 680abda95adb..16bb1b4904f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c @@ -15,7 +15,7 @@ /* It is the caller's responsibility to free the pointer returned here */ static struct iwl_mcc_update_resp_v8 * -iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt) +iwl_mld_copy_mcc_resp(const struct iwl_rx_packet *pkt) { const struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (const void *)pkt->data; int n_channels = __le32_to_cpu(mcc_resp_v8->n_channels); @@ -32,43 +32,11 @@ iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt) return resp_cp; } -/* It is the caller's responsibility to free the pointer returned here */ -static struct iwl_mcc_update_resp_v8 * -iwl_mld_parse_mcc_update_resp_v5_v6(const struct iwl_rx_packet *pkt) -{ - const struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (const void *)pkt->data; - struct iwl_mcc_update_resp_v8 *resp_cp; - int n_channels = __le32_to_cpu(mcc_resp_v4->n_channels); - int resp_len; - - if (iwl_rx_packet_payload_len(pkt) != - struct_size(mcc_resp_v4, channels, n_channels)) - return ERR_PTR(-EINVAL); - - resp_len = struct_size(resp_cp, channels, n_channels); - resp_cp = kzalloc(resp_len, GFP_KERNEL); - if (!resp_cp) - return ERR_PTR(-ENOMEM); - - resp_cp->status = mcc_resp_v4->status; - resp_cp->mcc = mcc_resp_v4->mcc; - resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap)); - resp_cp->source_id = mcc_resp_v4->source_id; - resp_cp->geo_info = mcc_resp_v4->geo_info; - resp_cp->n_channels = mcc_resp_v4->n_channels; - memcpy(resp_cp->channels, mcc_resp_v4->channels, - n_channels * sizeof(__le32)); - - return resp_cp; -} - /* It is the caller's responsibility to free the pointer returned here */ static struct iwl_mcc_update_resp_v8 * iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2, enum iwl_mcc_source src_id) { - int resp_ver = iwl_fw_lookup_notif_ver(mld->fw, LONG_GROUP, - MCC_UPDATE_CMD, 0); struct iwl_mcc_update_cmd mcc_update_cmd = { .mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]), .source_id = (u8)src_id, @@ -93,23 +61,7 @@ iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2, pkt = cmd.resp_pkt; - /* For Wifi-7 radios, we get version 8 - * For Wifi-6E radios, we get version 6 - * For Wifi-6 radios, we get version 5, but 5, 6, and 4 are compatible. - */ - switch (resp_ver) { - case 5: - case 6: - resp_cp = iwl_mld_parse_mcc_update_resp_v5_v6(pkt); - break; - case 8: - resp_cp = iwl_mld_parse_mcc_update_resp_v8(pkt); - break; - default: - IWL_FW_CHECK_FAILED(mld, "Unknown MCC_UPDATE_CMD version %d\n", resp_ver); - resp_cp = ERR_PTR(-EINVAL); - } - + resp_cp = iwl_mld_copy_mcc_resp(pkt); if (IS_ERR(resp_cp)) goto exit; From ee86cd90c91e8820c2509bbbba02f4e3c5e1e3c6 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:27 +0300 Subject: [PATCH 43/64] wifi: iwlwifi: remove support of versions 4 and 5 of iwl_alive_ntf These are not used in any of our devices. Remove them. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.dd784443be53.I4ff3b2392294f5df2625a71e2deee3364e9708f6@changeid --- .../net/wireless/intel/iwlwifi/fw/api/alive.h | 15 ------ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 50 ++++++------------- 2 files changed, 16 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 3ce477c248ce..ad5b95cad0bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h @@ -82,21 +82,6 @@ struct iwl_alive_ntf_v3 { struct iwl_umac_alive umac_data; } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ -struct iwl_alive_ntf_v4 { - __le16 status; - __le16 flags; - struct iwl_lmac_alive lmac_data[2]; - struct iwl_umac_alive umac_data; -} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_4 */ - -struct iwl_alive_ntf_v5 { - __le16 status; - __le16 flags; - struct iwl_lmac_alive lmac_data[2]; - struct iwl_umac_alive umac_data; - struct iwl_sku_id sku_id; -} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */ - struct iwl_imr_alive_info { __le64 base_addr; __le32 size; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 749fb8441190..d931c6eaf12f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -121,6 +121,22 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, return false; palive = (void *)pkt->data; + + umac = &palive->umac_data; + lmac1 = &palive->lmac_data[0]; + lmac2 = &palive->lmac_data[1]; + status = le16_to_cpu(palive->status); + + BUILD_BUG_ON(sizeof(palive->sku_id.data) != + sizeof(alive_data->sku_id)); + memcpy(alive_data->sku_id, palive->sku_id.data, + sizeof(palive->sku_id.data)); + + IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n", + le32_to_cpu(alive_data->sku_id[0]), + le32_to_cpu(alive_data->sku_id[1]), + le32_to_cpu(alive_data->sku_id[2])); + mvm->trans->dbg.imr_data.imr_enable = le32_to_cpu(palive->imr.enabled); mvm->trans->dbg.imr_data.imr_size = @@ -168,40 +184,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, IWL_DEBUG_FW(mvm, "platform id: 0x%llx\n", palive_v8->platform_id); } - } - - if (version >= 5) { - struct iwl_alive_ntf_v5 *palive; - - if (pkt_len < sizeof(*palive)) - return false; - - palive = (void *)pkt->data; - umac = &palive->umac_data; - lmac1 = &palive->lmac_data[0]; - lmac2 = &palive->lmac_data[1]; - status = le16_to_cpu(palive->status); - - BUILD_BUG_ON(sizeof(palive->sku_id.data) != - sizeof(alive_data->sku_id)); - memcpy(alive_data->sku_id, palive->sku_id.data, - sizeof(palive->sku_id.data)); - - IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n", - le32_to_cpu(alive_data->sku_id[0]), - le32_to_cpu(alive_data->sku_id[1]), - le32_to_cpu(alive_data->sku_id[2])); - } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) { - struct iwl_alive_ntf_v4 *palive; - - if (pkt_len < sizeof(*palive)) - return false; - - palive = (void *)pkt->data; - umac = &palive->umac_data; - lmac1 = &palive->lmac_data[0]; - lmac2 = &palive->lmac_data[1]; - status = le16_to_cpu(palive->status); } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v3)) { struct iwl_alive_ntf_v3 *palive3; From 493681d9f95bdf119af077ea05eeb42476e1f488 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:28 +0300 Subject: [PATCH 44/64] wifi: iwlwifi: remove support of version 4 of iwl_wowlan_rsc_tsc_params_cmd This are not used in any of our devices. Remove it. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.89156be9bc7f.I5ff5c1055eaf4fef9bd73233ea4d95504634ceed@changeid --- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 5 ---- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 29 +++++++------------ 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index b16bd8aa136a..53445087e9cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -456,11 +456,6 @@ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 { union iwl_all_tsc_rsc all_tsc_rsc; } __packed; /* ALL_TSC_RSC_API_S_VER_2 */ -struct iwl_wowlan_rsc_tsc_params_cmd_v4 { - struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 params; - __le32 sta_id; -} __packed; /* ALL_TSC_RSC_API_S_VER_4 */ - struct iwl_wowlan_rsc_tsc_params_cmd { __le64 ucast_rsc[IWL_MAX_TID_COUNT]; __le64 mcast_rsc[WOWLAN_GTK_KEYS_NUM][IWL_MAX_TID_COUNT]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 8930f8e3c0de..ef9bab042902 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -211,7 +211,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, } struct wowlan_key_rsc_tsc_data { - struct iwl_wowlan_rsc_tsc_params_cmd_v4 *rsc_tsc; + struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 *rsc_tsc; bool have_rsc_tsc; }; @@ -236,16 +236,16 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw, u64 pn64; tkip_sc = - data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc; + data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; tkip_tx_sc = - &data->rsc_tsc->params.all_tsc_rsc.tkip.tsc; + &data->rsc_tsc->all_tsc_rsc.tkip.tsc; pn64 = atomic64_read(&key->tx_pn); tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64)); tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64)); } else { tkip_sc = - data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc; + data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; } /* @@ -269,15 +269,15 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw, u64 pn64; aes_sc = - data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc; + data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; aes_tx_sc = - &data->rsc_tsc->params.all_tsc_rsc.aes.tsc; + &data->rsc_tsc->all_tsc_rsc.aes.tsc; pn64 = atomic64_read(&key->tx_pn); aes_tx_sc->pn = cpu_to_le64(pn64); } else { aes_sc = - data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc; + data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; } /* @@ -480,30 +480,21 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm, else ret = 0; kfree(data.rsc); - } else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) { + } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) { struct wowlan_key_rsc_tsc_data data = {}; - int size; data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL); if (!data.rsc_tsc) return -ENOMEM; - if (ver == 4) { - size = sizeof(*data.rsc_tsc); - data.rsc_tsc->sta_id = - cpu_to_le32(mvm_link->ap_sta_id); - } else { - /* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */ - size = sizeof(data.rsc_tsc->params); - } - ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_rsc_tsc_data, &data); if (data.have_rsc_tsc) ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM, - CMD_ASYNC, size, + CMD_ASYNC, + sizeof(data.rsc_tsc), data.rsc_tsc); else ret = 0; From 24bc49d158c7848b56faf7b9023c92f751a74921 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Fri, 11 Jul 2025 18:34:29 +0300 Subject: [PATCH 45/64] wifi: iwlwifi: remove support of several iwl_ppag_table_cmd versions We only need to support version 1, 5 and 7. Remove versions 2, 3, 4 and 6. Reviewed-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250711183056.10d91f675505.Idd3a6da568261ee738918f290168a2ddaa87196b@changeid --- .../net/wireless/intel/iwlwifi/fw/api/power.h | 20 ++++--------------- .../wireless/intel/iwlwifi/fw/regulatory.c | 20 ++++++------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 786b3bf4b448..ab84aac6605d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -571,8 +571,7 @@ enum iwl_ppag_flags { /** * union iwl_ppag_table_cmd - union for all versions of PPAG command * @v1: command version 1 structure. - * @v2: command version from 2 to 6 are same structure as v2. - * but has a different format of the flags bitmap + * @v2: command version 5 structure. * @v3: command version 7 structure. * @v1.flags: values from &enum iwl_ppag_flags * @v1.gain: table of antenna gain values per chain and sub-band @@ -593,9 +592,7 @@ union iwl_ppag_table_cmd { __le32 flags; s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; s8 reserved[2]; - } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4, - * VER5, VER6 - */ + } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */ struct { struct bios_value_u32 ppag_config_info; s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; @@ -603,20 +600,11 @@ union iwl_ppag_table_cmd { } __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ } __packed; -#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) -#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \ +#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) +#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \ IWL_PPAG_ETSI_LPI_UHB_MASK | \ IWL_PPAG_USA_LPI_UHB_MASK) -#define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \ - IWL_PPAG_ETSI_VLP_UHB_MASK | \ - IWL_PPAG_ETSI_SP_UHB_MASK | \ - IWL_PPAG_USA_VLP_UHB_MASK | \ - IWL_PPAG_USA_SP_UHB_MASK | \ - IWL_PPAG_CANADA_LPI_UHB_MASK | \ - IWL_PPAG_CANADA_VLP_UHB_MASK | \ - IWL_PPAG_CANADA_SP_UHB_MASK) - #define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26 #define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 3d6d1a85bb51..80d8373fccfc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -344,18 +344,18 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, num_sub_bands = IWL_NUM_SUB_BANDS_V1; gain = cmd->v1.gain[0]; *cmd_size = sizeof(cmd->v1); - cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); + cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK); if (fwrt->ppag_bios_rev >= 1) { /* in this case FW supports revision 0 */ IWL_DEBUG_RADIO(fwrt, "PPAG table rev is %d, send truncated table\n", fwrt->ppag_bios_rev); } - } else if (cmd_ver >= 2 && cmd_ver <= 6) { + } else if (cmd_ver == 5) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; gain = cmd->v2.gain[0]; *cmd_size = sizeof(cmd->v2); - cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags); + cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK); if (fwrt->ppag_bios_rev == 0) { /* in this case FW supports revisions 1,2 or 3 */ IWL_DEBUG_RADIO(fwrt, @@ -378,17 +378,9 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, "PPAG MODE bits were read from bios: %d\n", fwrt->ppag_flags); - if (cmd_ver == 6) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK); - else if (cmd_ver == 5) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK); - else if (cmd_ver < 5) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK); - - if ((cmd_ver == 1 && - !fw_has_capa(&fwrt->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || - (cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) { + if (cmd_ver == 1 && + !fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) { cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); } else { From 1772e571b332fdc480289c241f2273a808c5568d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Jul 2025 12:58:49 +0200 Subject: [PATCH 46/64] wifi: mac80211: make VHT opmode NSS ignore a debug message There's no need to always print it, it's only useful for debugging specific client issues. Make it a debug message. Reported-by: Paul Menzel Link: https://lore.kernel.org/linux-wireless/20250529070922.3467-1-pmenzel@molgen.mpg.de/ Link: https://patch.msgid.link/20250708105849.22448-2-johannes@sipsolutions.net Signed-off-by: Johannes Berg --- net/mac80211/vht.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index c5c5d16ed6c8..b099d79e8fbb 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -672,8 +672,9 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; } } else { - pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d", - link_sta->pub->addr, nss); + sdata_dbg(sdata, + "Ignore NSS change to invalid %d in VHT opmode notif from %pM", + nss, link_sta->pub->addr); } } From 50459501b9a212dbe7a673727589ee105a8a9954 Mon Sep 17 00:00:00 2001 From: Thomas Fourier Date: Wed, 9 Jul 2025 13:13:34 +0200 Subject: [PATCH 47/64] mwl8k: Add missing check after DMA map The DMA map functions can fail and should be tested for errors. If the mapping fails, unmap and return an error. Fixes: 788838ebe8a4 ("mwl8k: use pci_unmap_addr{,set}() to keep track of unmap addresses on rx") Signed-off-by: Thomas Fourier Link: https://patch.msgid.link/20250709111339.25360-2-fourier.thomas@gmail.com Signed-off-by: Johannes Berg --- drivers/net/wireless/marvell/mwl8k.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index bc34a025acd6..891e125ad30b 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -1227,6 +1227,10 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) addr = dma_map_single(&priv->pdev->dev, skb->data, MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pdev->dev, addr)) { + kfree_skb(skb); + break; + } rxq->rxd_count++; rx = rxq->tail++; From a6d521bafcb290294128a51b13dbf4baae5748fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:37:53 +0300 Subject: [PATCH 48/64] wifi: mac80211: don't unreserve never reserved chanctx If a link has no chanctx, indicating it is an inactive link that we tracked CSA for, then attempting to unreserve the reserved chanctx will throw a warning and fail, since there never was a reserved chanctx. Skip the unreserve. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.022192f4b1ae.Ib58156ac13e674a9f4d714735be0764a244c0aae@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 53f8b9bd2bd4..7a8643f08929 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2561,7 +2561,8 @@ ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link) if (!local->ops->abort_channel_switch) return; - ieee80211_link_unreserve_chanctx(link); + if (rcu_access_pointer(link->conf->chanctx_conf)) + ieee80211_link_unreserve_chanctx(link); ieee80211_vif_unblock_queues_csa(sdata); From 8aec30bb11280d932d0349e8d0727a6f29f8fcc4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:37:54 +0300 Subject: [PATCH 49/64] wifi: mac80211: remove ieee80211_link_unreserve_chanctx() return value All the paths that could return an error are considered misuses of the function and WARN already, and none of the callers ever check the return value. Remove it. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.5b436ee3c20c.Ieff61ec510939adb5fe6da4840557b649b3aa820@changeid Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 8 +++----- net/mac80211/ieee80211_i.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 4bcbcf9d98b5..73a590598934 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -1108,7 +1108,7 @@ void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link, __ieee80211_link_copy_chanctx_to_vlans(link, clear); } -int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) +void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) { struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_chanctx *ctx = link->reserved_chanctx; @@ -1116,7 +1116,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) lockdep_assert_wiphy(sdata->local->hw.wiphy); if (WARN_ON(!ctx)) - return -EINVAL; + return; list_del(&link->reserved_chanctx_list); link->reserved_chanctx = NULL; @@ -1124,7 +1124,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) { if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { if (WARN_ON(!ctx->replace_ctx)) - return -EINVAL; + return; WARN_ON(ctx->replace_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED); @@ -1140,8 +1140,6 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) ieee80211_free_chanctx(sdata->local, ctx, false); } } - - return 0; } static struct ieee80211_chanctx * diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ec68204fddc9..142b547ca606 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2697,7 +2697,7 @@ ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, bool radar_required); int __must_check ieee80211_link_use_reserved_context(struct ieee80211_link_data *link); -int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link); +void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link); int __must_check ieee80211_link_change_chanreq(struct ieee80211_link_data *link, From 14450be2332a49445106403492a367412b8c23f4 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 9 Jul 2025 23:37:55 +0300 Subject: [PATCH 50/64] wifi: cfg80211: Fix interface type validation Fix a condition that verified valid values of interface types. Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.7ad199ca5939.I0ac1ff74798bf59a87a57f2e18f2153c308b119b@changeid Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6ec9a8865b8b..f67424ec1085 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -633,7 +633,7 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, const struct ieee80211_sband_iftype_data *data; int i; - if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) + if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) return NULL; if (iftype == NL80211_IFTYPE_AP_VLAN) From 5241526dede93e6f1011b6b5e905801e24675ece Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:37:56 +0300 Subject: [PATCH 51/64] wifi: mac80211: don't send keys to driver when fips_enabled When fips_enabled is set, don't send any keys to the driver (including possibly WoWLAN KEK/KCK material), assuming that no device exists with the necessary certifications. If this turns out to be false in the future, we can add a HW flag. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.e5eebc2b19d8.I968ef8c9ffb48d464ada78685bd25d22349fb063@changeid Signed-off-by: Johannes Berg --- net/mac80211/driver-ops.c | 5 ++++- net/mac80211/driver-ops.h | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index 35349a7f16cb..ba9fba165926 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2015 Intel Deutschland GmbH - * Copyright (C) 2022-2024 Intel Corporation + * Copyright (C) 2022-2025 Intel Corporation */ #include #include "ieee80211_i.h" @@ -515,6 +515,9 @@ int drv_set_key(struct ieee80211_local *local, !(sdata->vif.active_links & BIT(key->link_id)))) return -ENOLINK; + if (fips_enabled) + return -EOPNOTSUPP; + trace_drv_set_key(local, cmd, sdata, sta, key); ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 8baebb5636ec..181bcb34b795 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -8,6 +8,7 @@ #ifndef __MAC80211_DRIVER_OPS #define __MAC80211_DRIVER_OPS +#include #include #include "ieee80211_i.h" #include "trace.h" @@ -902,6 +903,9 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return; + if (fips_enabled) + return; + trace_drv_set_rekey_data(local, sdata, data); if (local->ops->set_rekey_data) local->ops->set_rekey_data(&local->hw, &sdata->vif, data); From 8d313426d5029698daf68ee98d9fa6caa0cf370e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:37:57 +0300 Subject: [PATCH 52/64] wifi: mac80211: clean up cipher suite handling Under the previous commit's assumption that FIPS isn't supported by hardware, we don't need to modify the cipher suite list, but just need to use the software one instead of the driver's in this case, so clean up the code. Also fix it to exclude TKIP in this case, since that's also dependent on RC4. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.cff427e8f8a5.I744d1ea6a37e3ea55ae8bc3e770acee734eff268@changeid Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 2 -- net/mac80211/main.c | 65 +++++++++----------------------------- 2 files changed, 15 insertions(+), 52 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 142b547ca606..2a482089f9e1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1403,8 +1403,6 @@ struct ieee80211_local { bool rx_mcast_action_reg; unsigned int filter_flags; /* FIF_* */ - bool wiphy_ciphers_allocated; - struct cfg80211_chan_def dflt_chandef; bool emulate_chanctx; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c1c758e76d2e..ec60b82af007 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation */ #include @@ -1025,12 +1025,9 @@ EXPORT_SYMBOL(ieee80211_alloc_hw_nm); static int ieee80211_init_cipher_suites(struct ieee80211_local *local) { - bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */ bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE); - int r = 0, w = 0; - u32 *suites; static const u32 cipher_suites[] = { - /* keep WEP first, it may be removed below */ + /* keep WEP and TKIP first, they may be removed below */ WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, @@ -1046,34 +1043,17 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) WLAN_CIPHER_SUITE_BIP_GMAC_256, }; - if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) || - local->hw.wiphy->cipher_suites) { - /* If the driver advertises, or doesn't support SW crypto, - * we only need to remove WEP if necessary. - */ - if (have_wep) - return 0; + if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) && fips_enabled) { + dev_err(local->hw.wiphy->dev.parent, + "Drivers with SW_CRYPTO_CONTROL cannot work with FIPS\n"); + return -EINVAL; + } - /* well if it has _no_ ciphers ... fine */ - if (!local->hw.wiphy->n_cipher_suites) - return 0; + if (WARN_ON(ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) && + !local->hw.wiphy->cipher_suites)) + return -EINVAL; - /* Driver provides cipher suites, but we need to exclude WEP */ - suites = kmemdup_array(local->hw.wiphy->cipher_suites, - local->hw.wiphy->n_cipher_suites, - sizeof(u32), GFP_KERNEL); - if (!suites) - return -ENOMEM; - - for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { - u32 suite = local->hw.wiphy->cipher_suites[r]; - - if (suite == WLAN_CIPHER_SUITE_WEP40 || - suite == WLAN_CIPHER_SUITE_WEP104) - continue; - suites[w++] = suite; - } - } else { + if (fips_enabled || !local->hw.wiphy->cipher_suites) { /* assign the (software supported and perhaps offloaded) * cipher suites */ @@ -1083,19 +1063,13 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) if (!have_mfp) local->hw.wiphy->n_cipher_suites -= 4; - if (!have_wep) { - local->hw.wiphy->cipher_suites += 2; - local->hw.wiphy->n_cipher_suites -= 2; + /* FIPS does not permit the use of RC4 */ + if (fips_enabled) { + local->hw.wiphy->cipher_suites += 3; + local->hw.wiphy->n_cipher_suites -= 3; } - - /* not dynamically allocated, so just return */ - return 0; } - local->hw.wiphy->cipher_suites = suites; - local->hw.wiphy->n_cipher_suites = w; - local->wiphy_ciphers_allocated = true; - return 0; } @@ -1651,10 +1625,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_led_exit(local); destroy_workqueue(local->workqueue); fail_workqueue: - if (local->wiphy_ciphers_allocated) { - kfree(local->hw.wiphy->cipher_suites); - local->wiphy_ciphers_allocated = false; - } kfree(local->int_scan_req); return result; } @@ -1725,11 +1695,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) mutex_destroy(&local->iflist_mtx); - if (local->wiphy_ciphers_allocated) { - kfree(local->hw.wiphy->cipher_suites); - local->wiphy_ciphers_allocated = false; - } - idr_for_each(&local->ack_status_frames, ieee80211_free_ack_frame, NULL); idr_destroy(&local->ack_status_frames); From 2813d22149909d5eca67c079b63b8c93a2864339 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 9 Jul 2025 23:37:58 +0300 Subject: [PATCH 53/64] wifi: mac80211_hwsim: Declare support for AP scanning To support testing scenarios. Signed-off-by: Ilan Peer Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.6916e0a49955.I48e374ad7e3ea5877a5e93e5c5fe8301465771c8@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index eefe8da3b14d..3789d46d5614 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -5384,7 +5384,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | NL80211_FEATURE_STATIC_SMPS | NL80211_FEATURE_DYNAMIC_SMPS | - NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_AP_SCAN; wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION); wiphy_ext_feature_set(hw->wiphy, From 44ff9dae52cb275a1876d6f52fb2af5995149a83 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:37:59 +0300 Subject: [PATCH 54/64] wifi: mac80211: only assign chanctx in reconfig At the end of reconfig we are activating all the links that were active before the error. During the activation, _ieee80211_link_use_channel will unassign and re-assign the chanctx from/to the link. But we only need to do the assign, as we are re-building the state as it was before the reconfig. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.6245c3ae7031.Ia5f68992c7c112bea8a426c9339f50c88be3a9ca@changeid Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 73a590598934..c9cea0e7ac16 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -910,7 +910,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, conf = rcu_dereference_protected(link->conf->chanctx_conf, lockdep_is_held(&local->hw.wiphy->mtx)); - if (conf) { + if (conf && !local->in_reconfig) { curr_ctx = container_of(conf, struct ieee80211_chanctx, conf); drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx); @@ -930,8 +930,9 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, /* succeeded, so commit it to the data structures */ conf = &new_ctx->conf; - list_add(&link->assigned_chanctx_list, - &new_ctx->assigned_links); + if (!local->in_reconfig) + list_add(&link->assigned_chanctx_list, + &new_ctx->assigned_links); } } else { ret = 0; @@ -1932,7 +1933,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, if (ret < 0) goto out; - __ieee80211_link_release_channel(link, false); + if (!local->in_reconfig) + __ieee80211_link_release_channel(link, false); ctx = ieee80211_find_chanctx(local, link, chanreq, mode); /* Note: context is now reserved */ From 63df3956903748c5f374a0dfe7a89490714a4625 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:38:00 +0300 Subject: [PATCH 55/64] wifi: mac80211: don't mark keys for inactive links as uploaded During resume, the driver can call ieee80211_add_gtk_rekey for keys that are not programmed into the device, e.g. keys of inactive links. Don't mark such a key as uploaded to avoid removing it later from the driver/device. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.655094412b0b.Iacae31af3ba2a705da0a9baea976c2f799d65dc4@changeid Signed-off-by: Johannes Berg --- net/mac80211/key.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/key.c b/net/mac80211/key.c index dcf8643a0baa..997892da8886 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -510,7 +510,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, } else { if (!new->local->wowlan) ret = ieee80211_key_enable_hw_accel(new); - else + else if (link_id < 0 || !sdata->vif.active_links || + BIT(link_id) & sdata->vif.active_links) new->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; } From 6ee152b0cd45643ef0a1697585b97b63985ea79d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:38:01 +0300 Subject: [PATCH 56/64] wifi: mac80211: simplify __ieee80211_rx_h_amsdu() loop The loop handling individual subframes can be simplified to not use a somewhat confusing goto inside the loop. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.a217a1e8c667.I5283df9627912c06c8327b5786d6b715c6f3a4e1@changeid Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index caa3e6b3f46e..9bca5e0a41b0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3033,7 +3033,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; struct sk_buff_head frame_list; - ieee80211_rx_result res; struct ethhdr ethhdr; const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; @@ -3095,24 +3094,18 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) while (!skb_queue_empty(&frame_list)) { rx->skb = __skb_dequeue(&frame_list); - res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); - switch (res) { + switch (ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb)) { case RX_QUEUED: - continue; - case RX_CONTINUE: break; + case RX_CONTINUE: + if (ieee80211_frame_allowed(rx, fc)) { + ieee80211_deliver_skb(rx); + break; + } + fallthrough; default: - goto free; + dev_kfree_skb(rx->skb); } - - if (!ieee80211_frame_allowed(rx, fc)) - goto free; - - ieee80211_deliver_skb(rx); - continue; - -free: - dev_kfree_skb(rx->skb); } return RX_QUEUED; From 93370f2d37f50757a810da409efc0223c342527e Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 9 Jul 2025 23:38:02 +0300 Subject: [PATCH 57/64] wifi: mac80211: handle WLAN_HT_ACTION_NOTIFY_CHANWIDTH async If this action frame, with the value of IEEE80211_HT_CHANWIDTH_ANY, arrives right after a beacon that changed the operational bandwidth from 20 MHz to 40 MHz, then updating the rate control bandwidth to 40 can race with updating the chanctx width (that happens in the beacon proccesing) back to 40 MHz: cpu0 cpu1 ieee80211_rx_mgmt_beacon ieee80211_config_bw ieee80211_link_change_chanreq (*)ieee80211_link_update_chanreq ieee80211_rx_h_action (**)ieee80211_sta_cur_vht_bw (***) ieee80211_recalc_chanctx_chantype in (**), the maximum between the capability width and the bss width is returned. But the bss width was just updated to 40 in (*), so the action frame handling code will increase the width of the rate control before the chanctx was increased (in ***), leading to a FW error (at least in iwlwifi driver. But this is wrong regardless). Fix this by simply handling the action frame async, so it won't race with the beacon proccessing. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218632 Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.bb9dc6f36c35.I39782d6077424e075974c3bee4277761494a1527@changeid Signed-off-by: Johannes Berg --- net/mac80211/ht.c | 40 +++++++++++++++++++++++++++++++++++++- net/mac80211/ieee80211_i.h | 6 ++++++ net/mac80211/iface.c | 29 +++++++++++++++++++++++++++ net/mac80211/rx.c | 35 ++++++--------------------------- 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 32390d8a9d75..1c82a28b03de 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -9,7 +9,7 @@ * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation * Copyright 2017 Intel Deutschland GmbH - * Copyright(c) 2020-2024 Intel Corporation + * Copyright(c) 2020-2025 Intel Corporation */ #include @@ -603,3 +603,41 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id, } /* this might change ... don't want non-open drivers using it */ EXPORT_SYMBOL_GPL(ieee80211_request_smps); + +void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct link_sta_info *link_sta, + u8 chanwidth, enum nl80211_band band) +{ + enum ieee80211_sta_rx_bandwidth max_bw, new_bw; + struct ieee80211_supported_band *sband; + struct sta_opmode_info sta_opmode = {}; + + lockdep_assert_wiphy(local->hw.wiphy); + + if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) + max_bw = IEEE80211_STA_RX_BW_20; + else + max_bw = ieee80211_sta_cap_rx_bw(link_sta); + + /* set cur_max_bandwidth and recalc sta bw */ + link_sta->cur_max_bandwidth = max_bw; + new_bw = ieee80211_sta_cur_vht_bw(link_sta); + + if (link_sta->pub->bandwidth == new_bw) + return; + + link_sta->pub->bandwidth = new_bw; + sband = local->hw.wiphy->bands[band]; + sta_opmode.bw = + ieee80211_sta_rx_bw_to_chan_width(link_sta); + sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; + + rate_control_rate_update(local, sband, link_sta, + IEEE80211_RC_BW_CHANGED); + cfg80211_sta_opmode_change_notify(sdata->dev, + sta->addr, + &sta_opmode, + GFP_KERNEL); +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2a482089f9e1..83172eb964c8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2204,6 +2204,12 @@ u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs); enum nl80211_smps_mode ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps); +void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct link_sta_info *link_sta, + u8 chanwidth, enum nl80211_band band); + /* VHT */ void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0ba590a68605..07ba68f7cd81 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1556,6 +1556,35 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local, break; } } + } else if (ieee80211_is_action(mgmt->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_HT) { + switch (mgmt->u.action.u.ht_smps.action) { + case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { + u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; + struct ieee80211_rx_status *status; + struct link_sta_info *link_sta; + struct sta_info *sta; + + sta = sta_info_get_bss(sdata, mgmt->sa); + if (!sta) + break; + + status = IEEE80211_SKB_RXCB(skb); + if (!status->link_valid) + link_sta = &sta->deflink; + else + link_sta = rcu_dereference_protected(sta->link[status->link_id], + lockdep_is_held(&local->hw.wiphy->mtx)); + if (link_sta) + ieee80211_ht_handle_chanwidth_notif(local, sdata, sta, + link_sta, chanwidth, + status->band); + break; + } + default: + WARN_ON(1); + break; + } } else if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_VHT) { switch (mgmt->u.action.u.vht_group_notif.action_code) { diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9bca5e0a41b0..b414c9e6e61b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3580,41 +3580,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto handled; } case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { - struct ieee80211_supported_band *sband; u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; - enum ieee80211_sta_rx_bandwidth max_bw, new_bw; - struct sta_opmode_info sta_opmode = {}; + + if (chanwidth != IEEE80211_HT_CHANWIDTH_20MHZ && + chanwidth != IEEE80211_HT_CHANWIDTH_ANY) + goto invalid; /* If it doesn't support 40 MHz it can't change ... */ if (!(rx->link_sta->pub->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) goto handled; - if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) - max_bw = IEEE80211_STA_RX_BW_20; - else - max_bw = ieee80211_sta_cap_rx_bw(rx->link_sta); - - /* set cur_max_bandwidth and recalc sta bw */ - rx->link_sta->cur_max_bandwidth = max_bw; - new_bw = ieee80211_sta_cur_vht_bw(rx->link_sta); - - if (rx->link_sta->pub->bandwidth == new_bw) - goto handled; - - rx->link_sta->pub->bandwidth = new_bw; - sband = rx->local->hw.wiphy->bands[status->band]; - sta_opmode.bw = - ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); - sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; - - rate_control_rate_update(local, sband, rx->link_sta, - IEEE80211_RC_BW_CHANGED); - cfg80211_sta_opmode_change_notify(sdata->dev, - rx->sta->addr, - &sta_opmode, - GFP_ATOMIC); - goto handled; + goto queue; } default: goto invalid; From a597432cc9e640439370d9dc95952220cc13fc2b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2025 23:38:03 +0300 Subject: [PATCH 58/64] wifi: mac80211: don't use TPE data from assoc response Since there's no TPE element in the (re)assoc response, trying to use the data from it just leads to using the defaults, even though the real values had been set during authentication from the discovered BSS information. Fix this by simply not handling the TPE data in assoc response since it's not intended to be present, if it changes later the necessary changes will be made by tracking beacons later. As a side effect, by passing the real frame subtype, now print a correct value for ML reconfiguration responses. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250709233537.caa1ca853f5a.I588271f386731978163aa9d84ae75d6f79633e16@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7a8643f08929..5298dbbb5341 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1214,18 +1214,36 @@ EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee80211_determine_chan_mode); static int ieee80211_config_bw(struct ieee80211_link_data *link, struct ieee802_11_elems *elems, - bool update, u64 *changed, - const char *frame) + bool update, u64 *changed, u16 stype) { struct ieee80211_channel *channel = link->conf->chanreq.oper.chan; struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_chan_req chanreq = {}; struct cfg80211_chan_def ap_chandef; enum ieee80211_conn_mode ap_mode; + const char *frame; u32 vht_cap_info = 0; u16 ht_opmode; int ret; + switch (stype) { + case IEEE80211_STYPE_BEACON: + frame = "beacon"; + break; + case IEEE80211_STYPE_ASSOC_RESP: + frame = "assoc response"; + break; + case IEEE80211_STYPE_REASSOC_RESP: + frame = "reassoc response"; + break; + case IEEE80211_STYPE_ACTION: + /* the only action frame that gets here */ + frame = "ML reconf response"; + break; + default: + return -EINVAL; + } + /* don't track any bandwidth changes in legacy/S1G modes */ if (link->u.mgd.conn.mode == IEEE80211_CONN_MODE_LEGACY || link->u.mgd.conn.mode == IEEE80211_CONN_MODE_S1G) @@ -1274,7 +1292,9 @@ static int ieee80211_config_bw(struct ieee80211_link_data *link, ieee80211_min_bw_limit_from_chandef(&chanreq.oper)) ieee80211_chandef_downgrade(&chanreq.oper, NULL); - if (ap_chandef.chan->band == NL80211_BAND_6GHZ && + /* TPE element is not present in (re)assoc/ML reconfig response */ + if (stype == IEEE80211_STYPE_BEACON && + ap_chandef.chan->band == NL80211_BAND_6GHZ && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) { ieee80211_rearrange_tpe(&elems->tpe, &ap_chandef, &chanreq.oper); @@ -5348,7 +5368,9 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, /* check/update if AP changed anything in assoc response vs. scan */ if (ieee80211_config_bw(link, elems, link_id == assoc_data->assoc_link_id, - changed, "assoc response")) { + changed, + le16_to_cpu(mgmt->frame_control) & + IEEE80211_FCTL_STYPE)) { ret = false; goto out; } @@ -7543,7 +7565,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, changed |= ieee80211_recalc_twt_req(sdata, sband, link, link_sta, elems); - if (ieee80211_config_bw(link, elems, true, &changed, "beacon")) { + if (ieee80211_config_bw(link, elems, true, &changed, + IEEE80211_STYPE_BEACON)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DEAUTH_LEAVING, true, deauth_buf); From c932be7262323011ae8caa050811300b85347050 Mon Sep 17 00:00:00 2001 From: Yuvarani V Date: Thu, 10 Jul 2025 11:04:27 +0530 Subject: [PATCH 59/64] wifi: cfg80211: parse attribute to update unsolicited probe response template At present, the updated unsolicited broadcast probe response template is not processed during userspace commands such as channel switch or color change. This leads to an issue where older incorrect unsolicited probe response is still used during these events. Add support to parse the netlink attribute and store it so that mac80211/drivers can use it to set the BSS_CHANGED_UNSOL_BCAST_PROBE_RESP flag in order to send the updated unsolicited broadcast probe response templates during these events. Signed-off-by: Yuvarani V Signed-off-by: Aditya Kumar Singh Link: https://patch.msgid.link/20250710-update_unsol_bcast_probe_resp-v2-1-31aca39d3b30@oss.qualcomm.com Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++++ net/wireless/nl80211.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f67424ec1085..77bc17d6e96d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1526,6 +1526,7 @@ struct cfg80211_ap_update { * @n_counter_offsets_beacon: number of csa counters the beacon (tail) * @n_counter_offsets_presp: number of csa counters in the probe response * @beacon_after: beacon data to be used on the new channel + * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters * @radar_required: whether radar detection is required on the new channel * @block_tx: whether transmissions should be blocked while changing * @count: number of beacons until switch @@ -1540,6 +1541,7 @@ struct cfg80211_csa_settings { unsigned int n_counter_offsets_beacon; unsigned int n_counter_offsets_presp; struct cfg80211_beacon_data beacon_after; + struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; bool radar_required; bool block_tx; u8 count; @@ -1555,6 +1557,7 @@ struct cfg80211_csa_settings { * @counter_offset_beacon: offsets of the counters within the beacon (tail) * @counter_offset_presp: offsets of the counters within the probe response * @beacon_next: beacon data to be used after the color change + * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters * @count: number of beacons until the color change * @color: the color used after the change * @link_id: defines the link on which color change is expected during MLO. @@ -1565,6 +1568,7 @@ struct cfg80211_color_change_settings { u16 counter_offset_beacon; u16 counter_offset_presp; struct cfg80211_beacon_data beacon_next; + struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; u8 count; u8 color; u8 link_id; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4e6c0a4e2a82..1ee14592828d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10995,6 +10995,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) params.block_tx = true; + if ((wdev->iftype == NL80211_IFTYPE_AP || + wdev->iftype == NL80211_IFTYPE_P2P_GO) && + info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { + err = nl80211_parse_unsol_bcast_probe_resp( + rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], + ¶ms.unsol_bcast_probe_resp); + if (err) + goto free; + } + params.link_id = link_id; err = rdev_channel_switch(rdev, dev, ¶ms); @@ -16797,6 +16807,14 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) params.counter_offset_presp = offset; } + if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { + err = nl80211_parse_unsol_bcast_probe_resp( + rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], + ¶ms.unsol_bcast_probe_resp); + if (err) + goto out; + } + params.link_id = nl80211_link_id(info->attrs); err = rdev_color_change(rdev, dev, ¶ms); From f7130c9e3e12574168314496634db98af1317caf Mon Sep 17 00:00:00 2001 From: Yuvarani V Date: Thu, 10 Jul 2025 11:04:28 +0530 Subject: [PATCH 60/64] wifi: mac80211: parse unsolicited broadcast probe response data During commands like channel switch and color change, the updated unsolicited broadcast probe response template may be provided. However, this data is not parsed or acted upon in mac80211. Add support to parse it and set the BSS changed flag BSS_CHANGED_UNSOL_BCAST_PROBE_RESP so that drivers could take further action. Signed-off-by: Yuvarani V Signed-off-by: Aditya Kumar Singh Link: https://patch.msgid.link/20250710-update_unsol_bcast_probe_resp-v2-2-31aca39d3b30@oss.qualcomm.com Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d76643d46150..9ef280f3b55b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -4187,6 +4187,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, goto out; } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, + ¶ms->unsol_bcast_probe_resp, + link_data, link_conf, &changed); + if (err) + goto out; + chanctx = container_of(conf, struct ieee80211_chanctx, conf); ch_switch.timestamp = 0; @@ -5128,6 +5134,12 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev, goto out; } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, + ¶ms->unsol_bcast_probe_resp, + link, link_conf, &changed); + if (err) + goto out; + err = ieee80211_set_color_change_beacon(link, params, &changed); if (err) goto out; From 3df924c8f7d9223481feaac149a8ab93db9c0e11 Mon Sep 17 00:00:00 2001 From: Alex Gavin Date: Thu, 10 Jul 2025 14:14:30 -0700 Subject: [PATCH 61/64] wifi: mac80211_hwsim: Update comments in header - Reorders 'HWSIM_ATTR_PAD' to after 'HWSIM_ATTR_FREQ', matching order in 'enum hwsim_attrs' - Change references from old commands to new names - Fixes typos Signed-off-by: Alex Gavin Link: https://patch.msgid.link/20250710211437.8516-1-alex.gavin@candelatech.com Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.h b/drivers/net/wireless/virtual/mac80211_hwsim.h index f32fc3a492b0..fa157c883f7f 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.h +++ b/drivers/net/wireless/virtual/mac80211_hwsim.h @@ -62,7 +62,7 @@ enum hwsim_tx_control_flags { * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to * kernel, uses: * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, - * %HWSIM_ATTR_TX_INFO, %WSIM_ATTR_TX_INFO_FLAGS, + * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_TX_INFO_FLAGS, * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, * returns the radio ID (>= 0) or negative on errors, if successful @@ -126,24 +126,24 @@ enum hwsim_commands { * space * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame - * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_NEW_RADIO * command giving the number of channels supported by the new radio * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO * only to destroy a radio - * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint + * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatory driver hint * (nla string, length 2) * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) * @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag) - * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_NEW_RADIO * command to force use of channel contexts even when only a * single channel is supported - * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_NEW_RADIO * command to force radio removal when process that created the radio dies * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666 * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio. - * @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received. + * @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore * @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding * rates of %HWSIM_ATTR_TX_INFO * @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio @@ -151,7 +151,7 @@ enum hwsim_commands { * @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types * @HWSIM_ATTR_MLO_SUPPORT: claim MLO support (exact parameters TBD) for * the new radio - * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_NEW_RADIO * to provide peer measurement capabilities. (nl80211_peer_measurement_attrs) * @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR * to provide details about peer measurement request (nl80211_peer_measurement_attrs) From 9975aeebe2908cdd552ee59607754755459fad52 Mon Sep 17 00:00:00 2001 From: Maharaja Kennadyrajan Date: Fri, 11 Jul 2025 09:08:46 +0530 Subject: [PATCH 62/64] wifi: mac80211: use RCU-safe iteration in ieee80211_csa_finish The ieee80211_csa_finish() function currently uses for_each_sdata_link() to iterate over links of sdata. However, this macro internally uses wiphy_dereference(), which expects the wiphy->mtx lock to be held. When ieee80211_csa_finish() is invoked under an RCU read-side critical section (e.g., under rcu_read_lock()), this leads to a warning from the RCU debugging framework. WARNING: suspicious RCU usage net/mac80211/cfg.c:3830 suspicious rcu_dereference_protected() usage! This warning is triggered because wiphy_dereference() is not safe to use without holding the wiphy mutex, and it is being used in an RCU context without the required locking. Fix this by introducing and using a new macro, for_each_sdata_link_rcu(), which performs RCU-safe iteration over sdata links using list_for_each_entry_rcu() and rcu_dereference(). This ensures that the link pointers are accessed safely under RCU and eliminates the warning. Fixes: f600832794c9 ("wifi: mac80211: restructure tx profile retrieval for MLO MBSSID") Signed-off-by: Maharaja Kennadyrajan Link: https://patch.msgid.link/20250711033846.40455-1-maharaja.kennadyrajan@oss.qualcomm.com [unindent like the non-RCU macro] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 +- net/mac80211/ieee80211_i.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9ef280f3b55b..b99e39cb808b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3841,7 +3841,7 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id) */ struct ieee80211_link_data *iter; - for_each_sdata_link(local, iter) { + for_each_sdata_link_rcu(local, iter) { if (iter->sdata == sdata || rcu_access_pointer(iter->conf->tx_bss_conf) != tx_bss_conf) continue; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 83172eb964c8..084e2673a27e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1226,6 +1226,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) if ((_link = wiphy_dereference((_local)->hw.wiphy, \ ___sdata->link[___link_id]))) +/* + * for_each_sdata_link_rcu() must be used under RCU read lock. + */ +#define for_each_sdata_link_rcu(_local, _link) \ + /* outer loop just to define the variables ... */ \ + for (struct ieee80211_sub_if_data *___sdata = NULL; \ + !___sdata; \ + ___sdata = (void *)~0 /* always stop */) \ + list_for_each_entry_rcu(___sdata, &(_local)->interfaces, list) \ + if (ieee80211_sdata_running(___sdata)) \ + for (int ___link_id = 0; \ + ___link_id < ARRAY_SIZE((___sdata)->link); \ + ___link_id++) \ + if ((_link = rcu_dereference((___sdata)->link[___link_id]))) + #define for_each_link_data(sdata, __link) \ struct ieee80211_sub_if_data *__sdata = sdata; \ for (int __link_id = 0; \ From e9a896d498506af16d52ee33b80c1cdb4f36350d Mon Sep 17 00:00:00 2001 From: Aditya Kumar Singh Date: Mon, 14 Jul 2025 09:37:42 +0530 Subject: [PATCH 63/64] wifi: cfg80211: fix off channel operation allowed check for MLO In cfg80211_off_channel_oper_allowed(), the current logic disallows off-channel operations if any link operates on a radar channel, assuming such channels cannot be vacated. This assumption holds for non-MLO interfaces but not for MLO. With MLO and multi-radio devices, different links may operate on separate radios. This allows one link to scan off-channel while another remains on a radar channel. For example, in a 5 GHz split-phy setup, the lower band can scan while the upper band stays on a radar channel. Off-channel operations can be allowed if the radio/link onto which the input channel falls is different from the radio/link which has an active radar channel. Therefore, fix cfg80211_off_channel_oper_allowed() by returning false only if the requested channel maps to the same radio as an active radar channel. Allow off-channel operations when the requested channel is on a different radio, as in MLO with multi-radio setups. Signed-off-by: Aditya Kumar Singh Signed-off-by: Amith A Link: https://patch.msgid.link/20250714040742.538550-1-quic_amitajit@quicinc.com Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1ee14592828d..e1df03e8ed5c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9761,6 +9761,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, { unsigned int link_id; bool all_ok = true; + int radio_idx; lockdep_assert_wiphy(wdev->wiphy); @@ -9770,8 +9771,10 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, if (!cfg80211_beaconing_iface_active(wdev)) return true; + radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, chan); + /* - * FIXME: check if we have a free HW resource/link for chan + * FIXME: check if we have a free radio/link for chan * * This, as well as the FIXME below, requires knowing the link * capabilities of the hardware. @@ -9780,20 +9783,28 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, /* we cannot leave radar channels */ for_each_valid_link(wdev, link_id) { struct cfg80211_chan_def *chandef; + int link_radio_idx; chandef = wdev_chandef(wdev, link_id); if (!chandef || !chandef->chan) continue; + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + continue; + /* - * FIXME: don't require all_ok, but rather check only the - * correct HW resource/link onto which 'chan' falls, - * as only that link leaves the channel for doing - * the off-channel operation. + * chandef->chan is a radar channel. If the radio/link onto + * which this radar channel falls is the same radio/link onto + * which the input 'chan' falls, off-channel operation should + * not be allowed. Hence, set 'all_ok' to false. */ - if (chandef->chan->flags & IEEE80211_CHAN_RADAR) + link_radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, + chandef->chan); + if (link_radio_idx == radio_idx) { all_ok = false; + break; + } } if (all_ok) From 9a44b5e36cd699fdd2150a63fab225ac510c1971 Mon Sep 17 00:00:00 2001 From: Sarika Sharma Date: Mon, 14 Jul 2025 14:14:05 +0530 Subject: [PATCH 64/64] wifi: cfg80211: fix double free for link_sinfo in nl80211_station_dump() Currently, the link_sinfo structure is being freed twice in nl80211_dump_station(), once after the send_station() call and again in the error handling path. This results in a double free of both link_sinfo and link_sinfo->pertid, which might lead to undefined behavior or kernel crashes. Hence, fix by ensuring cfg80211_sinfo_release_content() is only invoked once during execution of nl80211_station_dump(). Fixes: 49e47223ecc4 ("wifi: cfg80211: allocate memory for link_station info structure") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/81f30515-a83d-4b05-a9d1-e349969df9e9@sabinyo.mountain/ Reported-by: syzbot+4ba6272678aa468132c8@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/68655325.a70a0220.5d25f.0316.GAE@google.com Signed-off-by: Sarika Sharma Link: https://patch.msgid.link/20250714084405.178066-1-quic_sarishar@quicinc.com Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e1df03e8ed5c..63f015ce9ad4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7451,6 +7451,7 @@ static int nl80211_dump_station(struct sk_buff *skb, struct wireless_dev *wdev; u8 mac_addr[ETH_ALEN]; int sta_idx = cb->args[2]; + bool sinfo_alloc = false; int err, i; err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); @@ -7479,6 +7480,7 @@ static int nl80211_dump_station(struct sk_buff *skb, err = -ENOMEM; goto out_err; } + sinfo_alloc = true; } err = rdev_dump_station(rdev, wdev->netdev, sta_idx, @@ -7491,6 +7493,11 @@ static int nl80211_dump_station(struct sk_buff *skb, if (sinfo.valid_links) cfg80211_sta_set_mld_sinfo(&sinfo); + /* reset the sinfo_alloc flag as nl80211_send_station() + * always releases sinfo + */ + sinfo_alloc = false; + if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, @@ -7505,7 +7512,8 @@ static int nl80211_dump_station(struct sk_buff *skb, cb->args[2] = sta_idx; err = skb->len; out_err: - cfg80211_sinfo_release_content(&sinfo); + if (sinfo_alloc) + cfg80211_sinfo_release_content(&sinfo); wiphy_unlock(&rdev->wiphy); return err;