From 34116ec67cc12bc0501ce2912372d167d597e4dd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sat, 5 Apr 2025 12:07:26 -0600 Subject: [PATCH 01/53] wifi: iwlwifi: mvm: d3: Avoid -Wflex-array-member-not-at-end warnings -Wflex-array-member-not-at-end was introduced in GCC-14, and we are getting ready to enable it, globally. Use the `DEFINE_RAW_FLEX()` helper for on-stack definitions of a flexible structure where the size of the flexible-array member is known at compile-time, and refactor the rest of the code, accordingly. So, with these changes, fix the following warnings: drivers/net/wireless/intel/iwlwifi/mvm/d3.c:124:52: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] drivers/net/wireless/intel/iwlwifi/mvm/d3.c:2067:51: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] drivers/net/wireless/intel/iwlwifi/mvm/d3.c:2162:43: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] drivers/net/wireless/intel/iwlwifi/mvm/d3.c:2225:43: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Acked-by: Miri Korenblit Link: https://patch.msgid.link/Z_FxXjiMvG5u73fi@kspp Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 129 +++++++++----------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 507c03198c92..e1070b891300 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -120,19 +120,17 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */ - struct { - struct iwl_mvm_wep_key_cmd wep_key_cmd; - struct iwl_mvm_wep_key wep_key; - } __packed wkc = { - .wep_key_cmd.mac_id_n_color = - cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, - mvmvif->color)), - .wep_key_cmd.num_keys = 1, - /* firmware sets STA_KEY_FLG_WEP_13BYTES */ - .wep_key_cmd.decryption_type = STA_KEY_FLG_WEP, - .wep_key.key_index = key->keyidx, - .wep_key.key_size = key->keylen, - }; + DEFINE_RAW_FLEX(struct iwl_mvm_wep_key_cmd, wkc, wep_key, 1); + struct iwl_mvm_wep_key *wep_key = wkc->wep_key; + + wkc->mac_id_n_color = + cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)); + wkc->num_keys = 1; + /* firmware sets STA_KEY_FLG_WEP_13BYTES */ + wkc->decryption_type = STA_KEY_FLG_WEP; + wep_key->key_index = key->keyidx; + wep_key->key_size = key->keylen; /* * This will fail -- the key functions don't set support @@ -142,18 +140,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) break; - memcpy(&wkc.wep_key.key[3], key->key, key->keylen); + memcpy(&wep_key->key[3], key->key, key->keylen); if (key->keyidx == mvmvif->tx_key_idx) { /* TX key must be at offset 0 */ - wkc.wep_key.key_offset = 0; + wep_key->key_offset = 0; } else { /* others start at 1 */ data->wep_key_idx++; - wkc.wep_key.key_offset = data->wep_key_idx; + wep_key->key_offset = data->wep_key_idx; } mutex_lock(&mvm->mutex); - ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc); + ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, + __struct_size(wkc), wkc); data->error = ret != 0; mvm->ptk_ivlen = key->iv_len; @@ -2061,10 +2060,8 @@ static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status, struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i]; struct ieee80211_key_conf *key, *old_key; struct ieee80211_key_seq seq; - struct { - struct ieee80211_key_conf conf; - u8 key[32]; - } conf = {}; + DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, + WOWLAN_KEY_MAX_SIZE); u16 flags = le16_to_cpu(mlo_key->flags); int j, link_id, key_id, key_type; @@ -2081,40 +2078,40 @@ static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status, key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES)) continue; - conf.conf.cipher = old_keys->cipher[link_id][key_type]; + conf->cipher = old_keys->cipher[link_id][key_type]; /* WARN_ON? */ - if (!conf.conf.cipher) + if (!conf->cipher) continue; - conf.conf.keylen = 0; - switch (conf.conf.cipher) { + conf->keylen = 0; + switch (conf->cipher) { case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: - conf.conf.keylen = WLAN_KEY_LEN_CCMP; + conf->keylen = WLAN_KEY_LEN_CCMP; break; case WLAN_CIPHER_SUITE_GCMP_256: - conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; + conf->keylen = WLAN_KEY_LEN_GCMP_256; break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128; + conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128; break; case WLAN_CIPHER_SUITE_BIP_GMAC_256: - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256; + conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256; break; case WLAN_CIPHER_SUITE_AES_CMAC: - conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC; + conf->keylen = WLAN_KEY_LEN_AES_CMAC; break; case WLAN_CIPHER_SUITE_BIP_CMAC_256: - conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256; + conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256; break; } - if (WARN_ON(!conf.conf.keylen || - conf.conf.keylen > sizeof(conf.key))) + if (WARN_ON(!conf->keylen || + conf->keylen > WOWLAN_KEY_MAX_SIZE)) continue; - memcpy(conf.conf.key, mlo_key->key, conf.conf.keylen); - conf.conf.keyidx = key_id; + memcpy(conf->key, mlo_key->key, conf->keylen); + conf->keyidx = key_id; old_key = old_keys->key[link_id][key_id]; if (old_key) { @@ -2126,7 +2123,7 @@ static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status, IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n", key_id, link_id); - key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id); + key = ieee80211_gtk_rekey_add(vif, conf, link_id); if (WARN_ON(IS_ERR(key))) { ret = false; goto out; @@ -2156,30 +2153,28 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, { int i, j; struct ieee80211_key_conf *key; - struct { - struct ieee80211_key_conf conf; - u8 key[32]; - } conf = { - .conf.cipher = gtk_cipher, - }; + DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, + WOWLAN_KEY_MAX_SIZE); int link_id = vif->active_links ? __ffs(vif->active_links) : -1; + conf->cipher = gtk_cipher; + BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); - BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key)); + BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_CCMP); + BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_GCMP_256); + BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_TKIP); + BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(status->gtk[0].key)); switch (gtk_cipher) { case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: - conf.conf.keylen = WLAN_KEY_LEN_CCMP; + conf->keylen = WLAN_KEY_LEN_CCMP; break; case WLAN_CIPHER_SUITE_GCMP_256: - conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; + conf->keylen = WLAN_KEY_LEN_GCMP_256; break; case WLAN_CIPHER_SUITE_TKIP: - conf.conf.keylen = WLAN_KEY_LEN_TKIP; + conf->keylen = WLAN_KEY_LEN_TKIP; break; default: WARN_ON(1); @@ -2189,14 +2184,14 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, if (!status->gtk[i].len) continue; - conf.conf.keyidx = status->gtk[i].id; + conf->keyidx = status->gtk[i].id; IWL_DEBUG_WOWLAN(mvm, "Received from FW GTK cipher %d, key index %d\n", - conf.conf.cipher, conf.conf.keyidx); - memcpy(conf.conf.key, status->gtk[i].key, + conf->cipher, conf->keyidx); + memcpy(conf->key, status->gtk[i].key, sizeof(status->gtk[i].key)); - key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id); + key = ieee80211_gtk_rekey_add(vif, conf, link_id); if (IS_ERR(key)) return false; @@ -2218,42 +2213,40 @@ 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) { + DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, + WOWLAN_KEY_MAX_SIZE); struct ieee80211_key_conf *key_config; - struct { - struct ieee80211_key_conf conf; - u8 key[WOWLAN_KEY_MAX_SIZE]; - } conf = { - .conf.cipher = cipher, - .conf.keyidx = key_data->id, - }; struct ieee80211_key_seq seq; int link_id = vif->active_links ? __ffs(vif->active_links) : -1; + conf->cipher = cipher; + conf->keyidx = key_data->id; + if (!key_data->len) return true; - iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher); + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf->cipher); switch (cipher) { case WLAN_CIPHER_SUITE_BIP_GMAC_128: - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128; + conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128; break; case WLAN_CIPHER_SUITE_BIP_GMAC_256: - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256; + conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256; break; case WLAN_CIPHER_SUITE_AES_CMAC: - conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC; + conf->keylen = WLAN_KEY_LEN_AES_CMAC; break; case WLAN_CIPHER_SUITE_BIP_CMAC_256: - conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256; + conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256; break; default: WARN_ON(1); } - BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); - memcpy(conf.conf.key, key_data->key, conf.conf.keylen); + BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(key_data->key)); + memcpy(conf->key, key_data->key, conf->keylen); - key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id); + key_config = ieee80211_gtk_rekey_add(vif, conf, link_id); if (IS_ERR(key_config)) return false; ieee80211_set_key_rx_seq(key_config, 0, &seq); From 5c14bff6929c3373b04598c12264d8d7894f86e2 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 9 Jun 2025 21:21:07 +0300 Subject: [PATCH 02/53] wifi: iwlwifi: mld: remove unneeded compilations Those are internal files so they should not be compiled. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.3bfe5222fe79.I1ebd746b0c513e278d231b5c48f5438ca9b9231f@changeid --- drivers/net/wireless/intel/iwlwifi/mld/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/Makefile index ece66e7a9be4..c966e573f430 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mld/Makefile @@ -9,8 +9,4 @@ iwlmld-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o iwlmld-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmld-$(CONFIG_PM_SLEEP) += d3.o -# non-upstream things -iwlmld-$(CONFIG_IWL_VENDOR_CMDS) += vendor-cmd.o -iwlmld-$(CONFIG_IWLMVM_AX_SOFTAP_TESTMODE) += ax-softap-testmode.o - subdir-ccflags-y += -I$(src)/../ From 21f7fe24d2efa996a36895d3098d0fbb52c62bbd Mon Sep 17 00:00:00 2001 From: Daniel Gabay Date: Mon, 9 Jun 2025 21:21:08 +0300 Subject: [PATCH 03/53] wifi: iwlwifi: mld: respect AUTO_EML_ENABLE in iwl_mld_retry_emlsr() Respect this flag before initiating MLO scan. Signed-off-by: Daniel Gabay Reviewed-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.b5c7fbdcb15c.Iaa176c49142b46b0b896728005357faec6a55fa6@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index dba5379ed009..20c2b436039a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -1167,8 +1167,8 @@ void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif) { struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); - if (!iwl_mld_vif_has_emlsr_cap(vif) || iwl_mld_emlsr_active(vif) || - mld_vif->emlsr.blocked_reasons) + if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif) || + iwl_mld_emlsr_active(vif) || mld_vif->emlsr.blocked_reasons) return; iwl_mld_int_mlo_scan(mld, vif); From aab09bf1222566b230db263a075aaad5cc813d50 Mon Sep 17 00:00:00 2001 From: Itamar Shalev Date: Mon, 9 Jun 2025 21:21:09 +0300 Subject: [PATCH 04/53] wifi: iwlwifi: mld: respect AUTO_EML_ENABLE in iwl_mld_int_mlo_scan() Respect this flag and don't scan for another link if it is set. Signed-off-by: Itamar Shalev Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.9ecb5c5301d4.I88b37e93d9ba66d4381f4976541b4aca2a20e36e@changeid --- drivers/net/wireless/intel/iwlwifi/mld/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 3fce7cd2d512..55d54bf29eae 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -1809,8 +1809,8 @@ void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif) lockdep_assert_wiphy(mld->wiphy); - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) || - hweight16(vif->valid_links) == 1) + if (!IWL_MLD_AUTO_EML_ENABLE || !vif->cfg.assoc || + !ieee80211_vif_is_mld(vif) || hweight16(vif->valid_links) == 1) return; if (mld->scan.status & IWL_MLD_SCAN_INT_MLO) { From 3b05871a22dbfccaf2bd8d979e06076c81508b2c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Jun 2025 21:21:10 +0300 Subject: [PATCH 05/53] wifi: iwlwifi: pcie: add missing TOP reset code The TOP reset requires code to handle the interrupt, which had been in my patch at some point, but clearly got lost. As the test had been running on the wrong hardware and failing due to that, we missed this. Add the missing code. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.3f84eb03cc00.If138ceeb8bb178b3931d96b537f746346227e681@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index f0405eddc367..fefde167c41b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1852,7 +1852,12 @@ static void iwl_trans_pcie_handle_reset_interrupt(struct iwl_trans *trans) } fallthrough; case CSR_IPC_STATE_RESET_TOP_READY: - /* FIXME: handle this case when requesting TOP reset */ + if (trans_pcie->fw_reset_state == FW_RESET_TOP_REQUESTED) { + IWL_DEBUG_ISR(trans, "TOP Reset continues\n"); + trans_pcie->fw_reset_state = FW_RESET_OK; + wake_up(&trans_pcie->fw_reset_waitq); + break; + } fallthrough; case CSR_IPC_STATE_RESET_NONE: IWL_FW_CHECK_FAILED(trans, From ff71bc9d0f6a5e8af353fc0588cf3b1a59815761 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 9 Jun 2025 21:21:11 +0300 Subject: [PATCH 06/53] wifi: iwlwifi: move iwl-context-info header files context info is PCIE specific, so it should be located in pcie directory. The c files are already there, move also the header files. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.606f48f72bcd.I4b89d373d961146e5369d1aed9f625150de7bf7d@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 2 +- .../net/wireless/intel/iwlwifi/{ => pcie}/iwl-context-info-v2.h | 0 .../net/wireless/intel/iwlwifi/{ => pcie}/iwl-context-info.h | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename drivers/net/wireless/intel/iwlwifi/{ => pcie}/iwl-context-info-v2.h (100%) rename drivers/net/wireless/intel/iwlwifi/{ => pcie}/iwl-context-info.h (100%) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 8a40801cf0dd..221c3997ee87 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -15,7 +15,7 @@ #include #include "fw/api/commands.h" #include "pcie/internal.h" -#include "iwl-context-info-v2.h" +#include "pcie/iwl-context-info-v2.h" struct iwl_trans_dev_restart_data { struct list_head list; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-v2.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/iwl-context-info-v2.h rename to drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/iwl-context-info.h rename to drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h From 34e33e39f405bd85270e9c89d9d547aab5bcc4fb Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 9 Jun 2025 21:21:13 +0300 Subject: [PATCH 07/53] wifi: iwlwifi: bump minimum API version in BZ/SC/DR Stop supporting older FWs. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.aeeef3290d03.I2433bfe9def643b5f4c0e77ff3cf8cd1285f5aad@changeid --- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 05e45fff8b36..b5ad6d635fcb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -13,7 +13,7 @@ #define IWL_BZ_UCODE_API_MAX 99 /* Lowest firmware API version supported */ -#define IWL_BZ_UCODE_API_MIN 93 +#define IWL_BZ_UCODE_API_MIN 94 /* Memory offsets and lengths */ #define IWL_BZ_SMEM_OFFSET 0x400000 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index 45e55cef42ea..95aa27c35357 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -12,7 +12,7 @@ #define IWL_DR_UCODE_API_MAX 99 /* Lowest firmware API version supported */ -#define IWL_DR_UCODE_API_MIN 97 +#define IWL_DR_UCODE_API_MIN 98 /* Memory offsets and lengths */ #define IWL_DR_SMEM_OFFSET 0x400000 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index b2e4d4035296..12c2adb4b5c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -13,7 +13,7 @@ #define IWL_SC_UCODE_API_MAX 99 /* Lowest firmware API version supported */ -#define IWL_SC_UCODE_API_MIN 97 +#define IWL_SC_UCODE_API_MIN 98 /* NVM versions */ #define IWL_SC_NVM_VERSION 0x0a1d From 14beeed861b9ae3e1db3aad19d2592e496aeae4c Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Mon, 9 Jun 2025 21:21:14 +0300 Subject: [PATCH 08/53] wifi: iwlwifi: parse VLP AP not allowed nvm channel flag OEMs need the option to enable/disable VLP AP. Add NVM flag to control VLP AP configuration. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.a433cb0ea0f3.Ifc6d7ba96d200dca0e3d38ec8d71625fd81a10ae@changeid --- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 0592f0f59d1c..56bac0a9755a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -160,23 +160,26 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = { * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?) * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP + * @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed, + * Valid only when %NVM_CHANNEL_VLP is enabled. */ enum iwl_nvm_channel_flags { - NVM_CHANNEL_VALID = BIT(0), - NVM_CHANNEL_IBSS = BIT(1), - NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2), - NVM_CHANNEL_ACTIVE = BIT(3), - NVM_CHANNEL_RADAR = BIT(4), - NVM_CHANNEL_INDOOR_ONLY = BIT(5), - NVM_CHANNEL_GO_CONCURRENT = BIT(6), - NVM_CHANNEL_UNIFORM = BIT(7), - NVM_CHANNEL_20MHZ = BIT(8), - NVM_CHANNEL_40MHZ = BIT(9), - NVM_CHANNEL_80MHZ = BIT(10), - NVM_CHANNEL_160MHZ = BIT(11), - NVM_CHANNEL_DC_HIGH = BIT(12), - NVM_CHANNEL_VLP = BIT(13), - NVM_CHANNEL_AFC = BIT(14), + NVM_CHANNEL_VALID = BIT(0), + NVM_CHANNEL_IBSS = BIT(1), + NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2), + NVM_CHANNEL_ACTIVE = BIT(3), + NVM_CHANNEL_RADAR = BIT(4), + NVM_CHANNEL_INDOOR_ONLY = BIT(5), + NVM_CHANNEL_GO_CONCURRENT = BIT(6), + NVM_CHANNEL_UNIFORM = BIT(7), + NVM_CHANNEL_20MHZ = BIT(8), + NVM_CHANNEL_40MHZ = BIT(9), + NVM_CHANNEL_80MHZ = BIT(10), + NVM_CHANNEL_160MHZ = BIT(11), + NVM_CHANNEL_DC_HIGH = BIT(12), + NVM_CHANNEL_VLP = BIT(13), + NVM_CHANNEL_AFC = BIT(14), + NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15), }; /** @@ -1685,10 +1688,12 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, } /* Set the AP type for the UHB case. */ - if (nvm_flags & NVM_CHANNEL_VLP) - flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP; - else + if (nvm_flags & NVM_CHANNEL_VLP) { + if (!(nvm_flags & NVM_CHANNEL_VLP_AP_NOT_ALLOWED)) + flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP; + } else { flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT; + } if (!(nvm_flags & NVM_CHANNEL_AFC)) flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT; From 13c258fd60ff1461b963f2f1d27eba4228836749 Mon Sep 17 00:00:00 2001 From: Itamar Shalev Date: Mon, 9 Jun 2025 21:21:15 +0300 Subject: [PATCH 09/53] wifi: iwlwifi: mvm: enable antenna selection for AX210 family Support for the `set antenna` command on AX210 family. Signed-off-by: Itamar Shalev Tested-by: Miriam Rachel Korenblit Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.098c7bc296f6.I1cb4e99aa2f5a3852e24e2d32795bae3a4a73742@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 0f056a6641bd..f99dc8624bd1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -312,7 +312,8 @@ int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) /* This has been tested on those devices only */ if (mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_9000 && - mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000) + mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000 && + mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_AX210) return -EOPNOTSUPP; if (!mvm->nvm_data) From c8a00a6e89ffee419a9190d2af9c75a7afe196d2 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 9 Jun 2025 21:21:16 +0300 Subject: [PATCH 10/53] wifi: iwlwifi: pcie: move generation specific files to a folder As a new generation of pcie is going to be written, we will need a folder for each generation. Since gen1 and gen2 code is tightly coupled and has with shared logic - it is not really separable. Put the code of both in one folder. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.bb0757c326c5.I66345c2b3fda55dcb8ff779c64de72d5c19f6649@changeid --- drivers/net/wireless/intel/iwlwifi/Makefile | 8 +++++--- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +- .../wireless/intel/iwlwifi/pcie/{ => gen1_2}/internal.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/rx.c | 2 +- .../wireless/intel/iwlwifi/pcie/{ => gen1_2}/trans-gen2.c | 4 ++-- .../net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/trans.c | 2 +- .../wireless/intel/iwlwifi/pcie/{ => gen1_2}/tx-gen2.c | 0 drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/tx.c | 0 11 files changed, 14 insertions(+), 12 deletions(-) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/internal.h (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/rx.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/trans-gen2.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/trans.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/tx-gen2.c (100%) rename drivers/net/wireless/intel/iwlwifi/pcie/{ => gen1_2}/tx.c (100%) diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index 3f476e333726..71101067b889 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -7,9 +7,11 @@ iwlwifi-objs += iwl-debug.o iwlwifi-objs += iwl-nvm-utils.o iwlwifi-objs += iwl-utils.o iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o -iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o -iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o -iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o + +# Bus +iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o +iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o +iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o CFLAGS_pcie/drv.o += -Wno-override-init diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 221c3997ee87..5dba76b009a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -14,7 +14,7 @@ #include "iwl-fh.h" #include #include "fw/api/commands.h" -#include "pcie/internal.h" +#include "pcie/gen1_2/internal.h" #include "pcie/iwl-context-info-v2.h" struct iwl_trans_dev_restart_data { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index 976fd1f58da4..0df379fda463 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -6,7 +6,7 @@ #include "iwl-trans.h" #include "iwl-fh.h" #include "iwl-context-info-v2.h" -#include "internal.h" +#include "gen1_2/internal.h" #include "iwl-prph.h" static const struct dmi_system_id dmi_force_scu_active_approved_list[] = { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index cb36baac14da..d53dab95c3e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -6,7 +6,7 @@ #include "iwl-trans.h" #include "iwl-fh.h" #include "iwl-context-info.h" -#include "internal.h" +#include "gen1_2/internal.h" #include "iwl-prph.h" static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 656f8b06c27b..44e19b27f36a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -15,7 +15,7 @@ #include "iwl-trans.h" #include "iwl-drv.h" #include "iwl-prph.h" -#include "internal.h" +#include "gen1_2/internal.h" #define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \ struct _struct) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/internal.h rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index 3b7c12fc4f9e..c90707cfd351 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -22,7 +22,7 @@ #include "iwl-io.h" #include "iwl-op-mode.h" #include "iwl-drv.h" -#include "iwl-context-info.h" +#include "pcie/iwl-context-info.h" /* * RX related structures and functions diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/rx.c rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c index fefde167c41b..7b56eb78663c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c @@ -12,7 +12,7 @@ #include "iwl-io.h" #include "internal.h" #include "iwl-op-mode.h" -#include "iwl-context-info-v2.h" +#include "pcie/iwl-context-info-v2.h" #include "fw/dbg.h" /****************************************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c index 38ad719161e6..6c5acb7bf643 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c @@ -5,8 +5,8 @@ */ #include "iwl-trans.h" #include "iwl-prph.h" -#include "iwl-context-info.h" -#include "iwl-context-info-v2.h" +#include "pcie/iwl-context-info.h" +#include "pcie/iwl-context-info-v2.h" #include "internal.h" #include "fw/dbg.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/trans.c rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index cc4d289b110d..4d2806d071d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -28,7 +28,7 @@ #include "mei/iwl-mei.h" #include "internal.h" #include "iwl-fh.h" -#include "iwl-context-info-v2.h" +#include "pcie/iwl-context-info-v2.h" /* extended range in FW SRAM */ #define IWL_FW_MEM_EXTENDED_START 0x40000 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/pcie/tx.c rename to drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c From 8ecc3928f26a99c4e46d6dfb78c1d229ab8c9578 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Jun 2025 21:21:17 +0300 Subject: [PATCH 11/53] wifi: iwlwifi: pcie: initiate TOP reset if requested At load time, the firmware may request a TOP reset via bit 6 in the IPC status register. Handle that and set TOP reset in that case. Since the init will be retried, there's no need to do anything else. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.0875d5f7e066.I62f14008d89416bc4a3a1056e06762561a7fac57@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 0fd452cb94ae..f3fa37fee2e4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -113,6 +113,7 @@ #define CSR_IPC_STATE_RESET_SW_READY 1 #define CSR_IPC_STATE_RESET_TOP_READY 2 #define CSR_IPC_STATE_RESET_TOP_FOLLOWER 3 +#define CSR_IPC_STATE_TOP_RESET_REQ BIT(6) #define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114) #define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c index 7b56eb78663c..0c73b1fe3645 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c @@ -1700,6 +1700,15 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) timer_delete(&trans_pcie->txqs.txq[i]->stuck_timer); } + if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) { + u32 val = iwl_read32(trans, CSR_IPC_STATE); + + if (val & CSR_IPC_STATE_TOP_RESET_REQ) { + IWL_ERR(trans, "FW requested TOP reset for FSEQ\n"); + trans->do_top_reset = 1; + } + } + /* The STATUS_FW_ERROR bit is set in this function. This must happen * before we wake up the command caller, to ensure a proper cleanup. */ iwl_trans_fw_error(trans, IWL_ERR_TYPE_IRQ); From 40840afa53bed05b990b201d749dfee3bd6e7e42 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 9 Jun 2025 21:21:18 +0300 Subject: [PATCH 12/53] wifi: iwlwifi: move dBm averaging function into utils The function really is just a simple math helper. Move it into iwl-utils.c so that it can also be used by iwlmld. Signed-off-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.8cc965af6990.I09bb2137863e888efe756c92d8eb0271ec95456c@changeid --- drivers/net/wireless/intel/iwlwifi/Kconfig | 1 + .../net/wireless/intel/iwlwifi/iwl-utils.c | 113 ++++++++++++++++- .../net/wireless/intel/iwlwifi/iwl-utils.h | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 117 +----------------- .../wireless/intel/iwlwifi/mvm/tests/Makefile | 2 +- .../net/wireless/intel/iwlwifi/tests/Makefile | 2 +- .../{mvm/tests/scan.c => tests/utils.c} | 43 ++++--- 8 files changed, 143 insertions(+), 140 deletions(-) rename drivers/net/wireless/intel/iwlwifi/{mvm/tests/scan.c => tests/utils.c} (63%) diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 82f577da1a8b..153a8368b412 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -97,6 +97,7 @@ config IWLWIFI_OPMODE_MODULAR default y if IWLDVM=m default y if IWLMVM=m default y if IWLMLD=m + default y if IWLWIFI_KUNIT_TESTS=m comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM or IWLMLD" depends on IWLDVM=n && IWLMVM=n && IWLMLD=n diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-utils.c b/drivers/net/wireless/intel/iwlwifi/iwl-utils.c index c5b49851e4b9..d503544fda40 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-utils.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-utils.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation */ #include #include @@ -82,3 +82,114 @@ int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes, } IWL_EXPORT_SYMBOL(iwl_tx_tso_segment); #endif /* CONFIG_INET */ + +static u32 iwl_div_by_db(u32 value, u8 db) +{ + /* + * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping + * at 10 dB and looping instead of using a much larger table. + * + * Using 64 bit math is overkill, but means the helper does not require + * a limit on the input range. + */ + static const u32 db_to_val[] = { + 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89, + 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a, + }; + + while (value && db > 0) { + u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val)); + + value = (((u64)value) * db_to_val[change - 1]) >> 32; + + db -= change; + } + + return value; +} + +s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len) +{ + int average_magnitude; + u32 average_factor; + int sum_magnitude = -128; + u32 sum_factor = 0; + int i, count = 0; + + /* + * To properly average the decibel values (signal values given in dBm) + * we need to do the math in linear space. Doing a linear average of + * dB (dBm) values is a bit annoying though due to the large range of + * at least -10 to -110 dBm that will not fit into a 32 bit integer. + * + * A 64 bit integer should be sufficient, but then we still have the + * problem that there are no directly usable utility functions + * available. + * + * So, lets not deal with that and instead do much of the calculation + * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit + * gives us plenty of head-room for adding up a few values and even + * doing some math on it. And the tail should be accurate enough too + * (1/2^16 is somewhere around -48 dB, so effectively zero). + * + * i.e. the real value of sum is: + * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW + * + * However, that does mean we need to be able to bring two values to + * a common base, so we need a helper for that. + * + * Note that this function takes an input with unsigned negative dBm + * values but returns a signed dBm (i.e. a negative value). + */ + + for (i = 0; i < len; i++) { + int val_magnitude; + u32 val_factor; + + /* Assume invalid */ + if (neg_dbm_values[i] == 0xff) + continue; + + val_factor = 0x10000; + val_magnitude = -neg_dbm_values[i]; + + if (val_magnitude <= sum_magnitude) { + u8 div_db = sum_magnitude - val_magnitude; + + val_factor = iwl_div_by_db(val_factor, div_db); + val_magnitude = sum_magnitude; + } else { + u8 div_db = val_magnitude - sum_magnitude; + + sum_factor = iwl_div_by_db(sum_factor, div_db); + sum_magnitude = val_magnitude; + } + + sum_factor += val_factor; + count++; + } + + /* No valid noise measurement, return a very high noise level */ + if (count == 0) + return 0; + + average_magnitude = sum_magnitude; + average_factor = sum_factor / count; + + /* + * average_factor will be a number smaller than 1.0 (0x10000) at this + * point. What we need to do now is to adjust average_magnitude so that + * average_factor is between -0.5 dB and 0.5 dB. + * + * Just do -1 dB steps and find the point where + * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB + * = div_by_db(0xe429, i) + * is smaller than average_factor. + */ + for (i = 0; average_factor < iwl_div_by_db(0xe429, i); i++) { + /* nothing */ + } + + return clamp(average_magnitude - i, -128, 0); +} +IWL_EXPORT_SYMBOL(iwl_average_neg_dbm); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-utils.h b/drivers/net/wireless/intel/iwlwifi/iwl-utils.h index 8f1f11d06fbe..5172035e4d26 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-utils.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation */ #ifndef __iwl_utils_h__ #define __iwl_utils_h__ @@ -53,4 +53,6 @@ u32 iwl_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size) return ie - beacon; } +s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len); + #endif /* __iwl_utils_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index a4f412e750d0..e8419a2e4c4b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -2133,7 +2133,6 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, s8 iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif); - extern const struct iwl_hcmd_arr iwl_mvm_groups[]; extern const unsigned int iwl_mvm_groups_size; #endif diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 60bd9c7e5f03..5f30109ca18f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2024 Intel Corporation + * Copyright (C) 2012-2014, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -11,6 +11,7 @@ #include "mvm.h" #include "fw/api/scan.h" #include "iwl-io.h" +#include "iwl-utils.h" #define IWL_DENSE_EBS_SCAN_RATIO 5 #define IWL_SPARSE_EBS_SCAN_RATIO 1 @@ -3685,117 +3686,6 @@ static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm, return -EINVAL; } -static u32 iwl_mvm_div_by_db(u32 value, u8 db) -{ - /* - * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping - * at 10 dB and looping instead of using a much larger table. - * - * Using 64 bit math is overkill, but means the helper does not require - * a limit on the input range. - */ - static const u32 db_to_val[] = { - 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89, - 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a, - }; - - while (value && db > 0) { - u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val)); - - value = (((u64)value) * db_to_val[change - 1]) >> 32; - - db -= change; - } - - return value; -} - -VISIBLE_IF_IWLWIFI_KUNIT s8 -iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif) -{ - s8 average_magnitude; - u32 average_factor; - s8 sum_magnitude = -128; - u32 sum_factor = 0; - int i, count = 0; - - /* - * To properly average the decibel values (signal values given in dBm) - * we need to do the math in linear space. Doing a linear average of - * dB (dBm) values is a bit annoying though due to the large range of - * at least -10 to -110 dBm that will not fit into a 32 bit integer. - * - * A 64 bit integer should be sufficient, but then we still have the - * problem that there are no directly usable utility functions - * available. - * - * So, lets not deal with that and instead do much of the calculation - * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit - * gives us plenty of head-room for adding up a few values and even - * doing some math on it. And the tail should be accurate enough too - * (1/2^16 is somewhere around -48 dB, so effectively zero). - * - * i.e. the real value of sum is: - * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW - * - * However, that does mean we need to be able to bring two values to - * a common base, so we need a helper for that. - * - * Note that this function takes an input with unsigned negative dBm - * values but returns a signed dBm (i.e. a negative value). - */ - - for (i = 0; i < ARRAY_SIZE(notif->noise); i++) { - s8 val_magnitude; - u32 val_factor; - - if (notif->noise[i] == 0xff) - continue; - - val_factor = 0x10000; - val_magnitude = -notif->noise[i]; - - if (val_magnitude <= sum_magnitude) { - u8 div_db = sum_magnitude - val_magnitude; - - val_factor = iwl_mvm_div_by_db(val_factor, div_db); - val_magnitude = sum_magnitude; - } else { - u8 div_db = val_magnitude - sum_magnitude; - - sum_factor = iwl_mvm_div_by_db(sum_factor, div_db); - sum_magnitude = val_magnitude; - } - - sum_factor += val_factor; - count++; - } - - /* No valid noise measurement, return a very high noise level */ - if (count == 0) - return 0; - - average_magnitude = sum_magnitude; - average_factor = sum_factor / count; - - /* - * average_factor will be a number smaller than 1.0 (0x10000) at this - * point. What we need to do now is to adjust average_magnitude so that - * average_factor is between -0.5 dB and 0.5 dB. - * - * Just do -1 dB steps and find the point where - * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB - * = div_by_db(0xe429, i) - * is smaller than average_factor. - */ - for (i = 0; average_factor < iwl_mvm_div_by_db(0xe429, i); i++) { - /* nothing */ - } - - return average_magnitude - i; -} -EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_average_dbm_values); - void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { @@ -3853,5 +3743,6 @@ void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm, info->time_busy = le32_to_cpu(notif->busy_time); info->time_rx = le32_to_cpu(notif->rx_time); info->time_tx = le32_to_cpu(notif->tx_time); - info->noise = iwl_mvm_average_dbm_values(notif); + info->noise = + iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise)); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile index 895d53f223e9..bb33f4a06f1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile @@ -1,3 +1,3 @@ -iwlmvm-tests-y += module.o links.o scan.o hcmd.o +iwlmvm-tests-y += module.o links.o hcmd.o obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmvm-tests.o diff --git a/drivers/net/wireless/intel/iwlwifi/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/tests/Makefile index 84491488f589..1b49241c578f 100644 --- a/drivers/net/wireless/intel/iwlwifi/tests/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -iwlwifi-tests-y += module.o devinfo.o +iwlwifi-tests-y += module.o devinfo.o utils.o ccflags-y += -I$(src)/../ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c b/drivers/net/wireless/intel/iwlwifi/tests/utils.c similarity index 63% rename from drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c rename to drivers/net/wireless/intel/iwlwifi/tests/utils.c index 7a3275199ace..df2c3a891e7e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/tests/utils.c @@ -1,20 +1,19 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * KUnit tests for channel helper functions + * KUnit tests for utilities * - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation */ -#include -#include "../mvm.h" +#include "../iwl-utils.h" #include -MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); +MODULE_IMPORT_NS("IWLWIFI"); -static const struct acs_average_db_case { +static const struct average_neg_db_case { const char *desc; u8 neg_dbm[22]; s8 result; -} acs_average_db_cases[] = { +} average_neg_db_cases[] = { { .desc = "Smallest possible value, all filled", .neg_dbm = { @@ -73,38 +72,38 @@ static const struct acs_average_db_case { }, }; -KUNIT_ARRAY_PARAM_DESC(acs_average_db, acs_average_db_cases, desc) +KUNIT_ARRAY_PARAM_DESC(average_neg_db, average_neg_db_cases, desc) -static void test_acs_average_db(struct kunit *test) +static void test_average_neg_db(struct kunit *test) { - const struct acs_average_db_case *params = test->param_value; - struct iwl_umac_scan_channel_survey_notif notif; + const struct average_neg_db_case *params = test->param_value; + u8 reversed[ARRAY_SIZE(params->neg_dbm)]; int i; /* Test the values in the given order */ - for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++) - notif.noise[i] = params->neg_dbm[i]; KUNIT_ASSERT_EQ(test, - iwl_mvm_average_dbm_values(¬if), + iwl_average_neg_dbm(params->neg_dbm, + ARRAY_SIZE(params->neg_dbm)), params->result); /* Test in reverse order */ for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++) - notif.noise[ARRAY_SIZE(params->neg_dbm) - i - 1] = + reversed[ARRAY_SIZE(params->neg_dbm) - i - 1] = params->neg_dbm[i]; KUNIT_ASSERT_EQ(test, - iwl_mvm_average_dbm_values(¬if), + iwl_average_neg_dbm(reversed, + ARRAY_SIZE(params->neg_dbm)), params->result); } -static struct kunit_case acs_average_db_case[] = { - KUNIT_CASE_PARAM(test_acs_average_db, acs_average_db_gen_params), +static struct kunit_case average_db_case[] = { + KUNIT_CASE_PARAM(test_average_neg_db, average_neg_db_gen_params), {} }; -static struct kunit_suite acs_average_db = { - .name = "iwlmvm-acs-average-db", - .test_cases = acs_average_db_case, +static struct kunit_suite average_db = { + .name = "iwl-average-db", + .test_cases = average_db_case, }; -kunit_test_suite(acs_average_db); +kunit_test_suite(average_db); From 2110d001db47dd5a6b58c399ea3524dc3c572065 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Mon, 9 Jun 2025 21:21:19 +0300 Subject: [PATCH 13/53] wifi: iwlwifi: Remove unused cfg parameter from iwl_nvm_get_regdom_bw_flags Refactor iwl_nvm_get_regdom_bw_flags() by removing the unused cfg parameter to enhance code clarity and maintainability Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.987b1a749b78.I11a67c0737fb39b594831c10f62de1a195ed24e3@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 56bac0a9755a..c5c80f72696f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1632,8 +1632,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, int ch_idx, u16 nvm_flags, - struct iwl_reg_capa reg_capa, - const struct iwl_rf_cfg *cfg) + struct iwl_reg_capa reg_capa) { u32 flags = NL80211_RRF_NO_HT40; @@ -1820,8 +1819,8 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans, } reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, - ch_flags, reg_capa, - cfg); + ch_flags, + reg_capa); /* we can't continue the same rule */ if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags || From 6efaf59ffa3712db9562e8243492d69d32765e3a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Jun 2025 21:21:20 +0300 Subject: [PATCH 14/53] wifi: iwlwifi: mld: fix misspelling of 'established' This got pretty mangled, fix the spelling. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.afbb67d4dda9.Id1412d9336740e6101e672b38411641c6e206999@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 4ba050397632..9b4bdbf40d4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1468,7 +1468,7 @@ void iwl_mld_mac80211_mgd_prepare_tx(struct ieee80211_hw *hw, struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); u32 duration = IWL_MLD_SESSION_PROTECTION_ASSOC_TIME_MS; - /* After a successful association the connection is etalibeshed + /* After a successful association the connection is established * and we can rely on the quota to send the disassociation frame. */ if (info->was_assoc) From eda36f5195d6c078e20331f1dfcf688bd6567c2b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 9 Jun 2025 21:21:21 +0300 Subject: [PATCH 15/53] wifi: iwlwifi: pcie: reinit device properly during TOP reset During TOP reset a full _iwl_trans_pcie_start_hw() is needed so the device is properly initialized for operation. Fix that. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250609211928.903444f8e8e8.I7f70600339abb9d658f97924aef22faf1af00a3c@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) 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 c90707cfd351..796410f2fa48 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1074,6 +1074,7 @@ void iwl_pcie_rx_allocator_work(struct work_struct *data); /* common trans ops for all generations transports */ void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); +int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); int iwl_trans_pcie_start_hw(struct iwl_trans *trans); void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val); 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 6c5acb7bf643..b5e4b60f710c 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 @@ -610,6 +610,11 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, msleep(10); IWL_INFO(trans, "TOP reset successful, reinit now\n"); /* now load the firmware again properly */ + ret = _iwl_trans_pcie_start_hw(trans); + if (ret) { + IWL_ERR(trans, "failed to start HW after TOP reset\n"); + goto out; + } trans_pcie->prph_scratch->ctrl_cfg.control.control_flags &= ~cpu_to_le32(IWL_PRPH_SCRATCH_TOP_RESET); top_reset_done = true; 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 4d2806d071d9..bace11a949c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -1845,7 +1845,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans) return iwl_trans_pcie_sw_reset(trans, true); } -static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) +int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int err; From 8689bc3fc017d445f48b6b9e80a8c2c0aa3961af Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:20 +0300 Subject: [PATCH 16/53] wifi: iwlwifi: pcie: abort D3 handshake on error The D3 handshake can be interrupted by an error, especially on resume where we no longer want to check explicitly for errors. Expand the sx_complete to sx_state and handle any errors occurring during the handshake. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.157dca92c573.I6dd3b9d2f435c2c363224aa84e373931e56a545f@changeid --- .../intel/iwlwifi/pcie/gen1_2/internal.h | 9 ++++-- .../wireless/intel/iwlwifi/pcie/gen1_2/rx.c | 16 ++++++++-- .../intel/iwlwifi/pcie/gen1_2/trans.c | 31 +++++++++++++------ 3 files changed, 42 insertions(+), 14 deletions(-) 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 796410f2fa48..ebcc174f6c62 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -382,7 +382,7 @@ struct iwl_pcie_txqs { * @irq_lock: lock to synchronize IRQ handling * @txq_memory: TXQ allocation array * @sx_waitq: waitqueue for Sx transitions - * @sx_complete: completion for Sx transitions + * @sx_state: state tracking Sx transitions * @pcie_dbg_dumped_once: indicates PCIe regs were dumped already * @opmode_down: indicates opmode went away * @num_rx_bufs: number of RX buffers to allocate/use @@ -448,7 +448,12 @@ struct iwl_trans_pcie { u8 __iomem *hw_base; bool ucode_write_complete; - bool sx_complete; + enum { + IWL_SX_INVALID = 0, + IWL_SX_WAITING, + IWL_SX_ERROR, + IWL_SX_COMPLETE, + } sx_state; wait_queue_head_t ucode_write_waitq; wait_queue_head_t sx_waitq; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c index 0c73b1fe3645..619a9505e6d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c @@ -2394,6 +2394,11 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) } else { iwl_pcie_irq_handle_error(trans); } + + if (trans_pcie->sx_state == IWL_SX_WAITING) { + trans_pcie->sx_state = IWL_SX_ERROR; + wake_up(&trans_pcie->sx_waitq); + } } /* After checking FH register check HW register */ @@ -2428,13 +2433,20 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP && trans_pcie->prph_info) { u32 sleep_notif = le32_to_cpu(trans_pcie->prph_info->sleep_notif); + if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND || sleep_notif == IWL_D3_SLEEP_STATUS_RESUME) { IWL_DEBUG_ISR(trans, "Sx interrupt: sleep notification = 0x%x\n", sleep_notif); - trans_pcie->sx_complete = true; - wake_up(&trans_pcie->sx_waitq); + if (trans_pcie->sx_state == IWL_SX_WAITING) { + trans_pcie->sx_state = IWL_SX_COMPLETE; + wake_up(&trans_pcie->sx_waitq); + } else { + IWL_ERR(trans, + "unexpected Sx interrupt (0x%x)\n", + sleep_notif); + } } else { /* uCode wakes up after power-down sleep */ IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); 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 bace11a949c8..6054ebebd8c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -1536,30 +1536,41 @@ static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int ret; + if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return 0; + + trans_pcie->sx_state = IWL_SX_WAITING; + if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND : UREG_DOORBELL_TO_ISR6_RESUME); - else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + else iwl_write32(trans, CSR_IPC_SLEEP_CONTROL, suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND : CSR_IPC_SLEEP_CONTROL_RESUME); - else - return 0; ret = wait_event_timeout(trans_pcie->sx_waitq, - trans_pcie->sx_complete, 2 * HZ); - - /* Invalidate it toward next suspend or resume */ - trans_pcie->sx_complete = false; - + trans_pcie->sx_state != IWL_SX_WAITING, + 2 * HZ); if (!ret) { IWL_ERR(trans, "Timeout %s D3\n", suspend ? "entering" : "exiting"); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + } else { + ret = 0; } - return 0; + if (trans_pcie->sx_state == IWL_SX_ERROR) { + IWL_ERR(trans, "FW error while %s D3\n", + suspend ? "entering" : "exiting"); + ret = -EIO; + } + + /* Invalidate it toward next suspend or resume */ + trans_pcie->sx_state = IWL_SX_INVALID; + + return ret; } int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset) From 5943ce4e37dbae7cc11740609b165d0fb4b7df08 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 11 Jun 2025 22:26:21 +0300 Subject: [PATCH 17/53] wifi: iwlwifi: add support for the devcoredump This handler will be used by upcoming changes to trigger firmware dumps from devcoredump through trans layer. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.bb38efe6700d.I9c666440dd1eac13ac52a2c2d533224c36fea2a6@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h | 10 ++++++++++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h index 5dc299296d6d..a146d0e399f2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h @@ -147,6 +147,8 @@ struct iwl_fw_error_dump_mode { * Op_mode needs to reset its internal state because the device did not * survive the system state transition. The firmware is no longer running, * etc... + * @dump: Op_mode needs to collect the firmware dump upon this handler + * being called. */ struct iwl_op_mode_ops { struct iwl_op_mode *(*start)(struct iwl_trans *trans, @@ -174,6 +176,7 @@ struct iwl_op_mode_ops { enum iwl_fw_ini_time_point tp_id, union iwl_dbg_tlv_tp_data *tp_data); void (*device_powered_off)(struct iwl_op_mode *op_mode); + void (*dump)(struct iwl_op_mode *op_mode); }; int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops); @@ -286,4 +289,11 @@ static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode) op_mode->ops->device_powered_off(op_mode); } +static inline void iwl_op_mode_dump(struct iwl_op_mode *op_mode) +{ + if (!op_mode || !op_mode->ops || !op_mode->ops->dump) + return; + op_mode->ops->dump(op_mode); +} + #endif /* __iwl_op_mode_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 44e19b27f36a..a42a6da5d2ea 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1564,12 +1564,21 @@ static const struct dev_pm_ops iwl_dev_pm_ops = { #endif /* CONFIG_PM_SLEEP */ +static void iwl_pci_dump(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct iwl_trans *trans = pci_get_drvdata(pdev); + + iwl_op_mode_dump(trans->op_mode); +} + static struct pci_driver iwl_pci_driver = { .name = DRV_NAME, .id_table = iwl_hw_card_ids, .probe = iwl_pci_probe, .remove = iwl_pci_remove, .driver.pm = IWL_PM_OPS, + .driver.coredump = iwl_pci_dump, }; int __must_check iwl_pci_register_driver(void) From 8dab046d6e569d60a002d8256be22be2c8b522cf Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 11 Jun 2025 22:26:22 +0300 Subject: [PATCH 18/53] wifi: iwlwifi: mld: Add dump handler to iwl_mld Implement a dump handler in the iwl_mld 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/20250611222325.18ebf46690ce.Ia52941f761a446cb3e43cbe49d2b9a49fc15f4a8@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mld.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 8cdd960c5245..103912c4e4cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -723,6 +723,17 @@ static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode) {} #endif +static void iwl_mld_dump(struct iwl_op_mode *op_mode) +{ + struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); + struct iwl_fw_runtime *fwrt = &mld->fwrt; + + if (!iwl_trans_fw_running(fwrt->trans)) + return; + + iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL); +} + static const struct iwl_op_mode_ops iwl_mld_ops = { .start = iwl_op_mode_mld_start, .stop = iwl_op_mode_mld_stop, @@ -737,6 +748,7 @@ static const struct iwl_op_mode_ops iwl_mld_ops = { .sw_reset = iwl_mld_sw_reset, .time_point = iwl_mld_time_point, .device_powered_off = pm_sleep_ptr(iwl_mld_device_powered_off), + .dump = iwl_mld_dump, }; struct iwl_mld_mod_params iwlmld_mod_params = { From cc8d9cbf269dab363c768bfa9312265bc807fca5 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 11 Jun 2025 22:26:23 +0300 Subject: [PATCH 19/53] wifi: iwlwifi: fw: Fix possible memory leak in iwl_fw_dbg_collect Ensure descriptor is freed on error to avoid memory leak. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.8158d15ec866.Ifa3e422c302397111f20a16da7509e6574bc19e3@changeid --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index ea739ebe7cb0..95a732efce45 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -3008,6 +3008,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, struct iwl_fw_dump_desc *desc; unsigned int delay = 0; bool monitor_only = false; + int ret; if (trigger) { u16 occurrences = le16_to_cpu(trigger->occurrences) - 1; @@ -3038,7 +3039,11 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, desc->trig_desc.type = cpu_to_le32(trig); memcpy(desc->trig_desc.data, str, len); - return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); + ret = iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); + if (ret) + kfree(desc); + + return ret; } IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); From 7a7cb2eb54592b8fa8e59740fb61603c9f3f16bf Mon Sep 17 00:00:00 2001 From: Or Ron Date: Wed, 11 Jun 2025 22:26:24 +0300 Subject: [PATCH 20/53] wifi: iwlwifi: phy periph read - flow modification If for some reason the reading of phy prph fails, there is no reason to keep reading them. Check the status abd break early in such case. Signed-off-by: Or Ron Reviewed-by: Eilon Rinat Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.124ce6613edd.Ic1aad57cc6163f0551a3dafae048434f4a2fe7f5@changeid --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 16 ++++++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 95a732efce45..98ad020014d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1106,6 +1106,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, u32 prph_val; u32 dphy_state; u32 dphy_addr; + u32 prph_stts; int i; range->internal_base_addr = cpu_to_le32(addr); @@ -1133,6 +1134,21 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, iwl_write_prph_no_grab(fwrt->trans, indirect_wr_addr, WMAL_INDRCT_CMD(addr + i)); + + if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 && + fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 && + fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 && + fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) { + udelay(2); + prph_stts = iwl_read_prph_no_grab(fwrt->trans, + WMAL_MRSPF_STTS); + + /* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */ + if (prph_stts == WMAL_TIMEOUT_VAL || + !WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(prph_stts)) + break; + } + prph_val = iwl_read_prph_no_grab(fwrt->trans, indirect_rd_addr); *val++ = cpu_to_le32(prph_val); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 23b2009fbb28..a7214ddcfaf5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2024 Intel Corporation + * Copyright (C) 2005-2014, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -514,6 +514,14 @@ enum { #define WMAL_INDRCT_CMD(addr) \ ((WMAL_CMD_READ_BURST_ACCESS << WMAL_INDRCT_RD_CMD1_OPMOD_POS) | \ ((addr) & WMAL_INDRCT_RD_CMD1_BYTE_ADDRESS_MSK)) +#define WMAL_MRSPF_STTS 0xADFC24 +#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS 15 +#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK 0x8000 +#define WMAL_TIMEOUT_VAL 0xA5A5A5A2 +#define WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(val) \ + (((val) >> (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)) & \ + ((WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK) >> \ + (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS))) #define WFPM_LMAC1_PS_CTL_RW 0xA03380 #define WFPM_LMAC2_PS_CTL_RW 0xA033C0 From bc0440eeaf829b2840e9d4f946551c0c6fe9f9e3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:25 +0300 Subject: [PATCH 21/53] wifi: iwlwifi: mld: add timer host wakeup debugfs Add a debugfs file to be able to control how long, at most, the device will sleep before waking up the host. This will be useful to test certain "assert during suspend" scenarios for the previous change. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.9f2a39cae1e1.Ie0003f21286fea50b507d0debe06332b030cd4cb@changeid --- drivers/net/wireless/intel/iwlwifi/fw/api/d3.h | 6 ++++-- drivers/net/wireless/intel/iwlwifi/mld/d3.c | 7 +++++++ drivers/net/wireless/intel/iwlwifi/mld/debugfs.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/mld/mld.h | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 9c271ea67155..9ce819503aed 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2024 Intel Corporation + * Copyright (C) 2012-2014, 2018-2025 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -19,9 +19,11 @@ enum iwl_d0i3_flags { /** * enum iwl_d3_wakeup_flags - D3 manager wakeup flags * @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert + * @IWL_WAKEUP_D3_HOST_TIMER: wake up on host timer expiry */ enum iwl_d3_wakeup_flags { - IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0), + IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0), + IWL_WAKEUP_D3_HOST_TIMER = BIT(1), }; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index 339b148d6793..d450d24689f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -1317,6 +1317,13 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld) struct iwl_d3_manager_config d3_cfg_cmd_data = {}; int ret; + if (mld->debug_max_sleep) { + d3_cfg_cmd_data.wakeup_host_timer = + cpu_to_le32(mld->debug_max_sleep); + d3_cfg_cmd_data.wakeup_flags = + cpu_to_le32(IWL_WAKEUP_D3_HOST_TIMER); + } + lockdep_assert_wiphy(mld->wiphy); IWL_DEBUG_WOWLAN(mld, "Starting the no wowlan suspend flow\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index 352da8aa7898..75cc1d8bb90c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -546,6 +546,11 @@ iwl_mld_add_debugfs_files(struct iwl_mld *mld, struct dentry *debugfs_dir) #endif MLD_DEBUGFS_ADD_FILE(inject_packet, debugfs_dir, 0200); +#ifdef CONFIG_PM_SLEEP + debugfs_create_u32("max_sleep", 0600, debugfs_dir, + &mld->debug_max_sleep); +#endif + debugfs_create_bool("rx_ts_ptp", 0600, debugfs_dir, &mld->monitor.ptp_time); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index 1a2c44f44eff..241ab3a00e56 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -159,6 +159,7 @@ * @addresses: device MAC addresses. * @scan: instance of the scan object * @wowlan: WoWLAN support data. + * @debug_max_sleep: maximum sleep time in D3 (for debug purposes) * @led: the led device * @mcc_src: the source id of the MCC, comes from the firmware * @bios_enable_puncturing: is puncturing enabled by bios @@ -252,6 +253,7 @@ struct iwl_mld { struct iwl_mld_scan scan; #ifdef CONFIG_PM_SLEEP struct wiphy_wowlan_support wowlan; + u32 debug_max_sleep; #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_IWLWIFI_LEDS struct led_classdev led; From 1cc04e196a59d27ac2ac19e2e0b4ad041a626a69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:26 +0300 Subject: [PATCH 22/53] wifi: iwlwifi: mld: remove special FW error resume handling The (applicable) firmware versions will send an error interrupt as part of the resume process, so there's no need now to check for it explicitly. Simplify the code. This also fixes an issue where any dump taken during the resume isn't able to do the reset handshake as part of the dump (since interrupts are disabled) and then there isn't all the correct data and we get more errors later. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.9e778f1bae0c.I96483b5236ab23141b45079464c73f93e0164e65@changeid --- drivers/net/wireless/intel/iwlwifi/mld/d3.c | 72 +------------------ .../net/wireless/intel/iwlwifi/mld/mac80211.c | 9 ++- 2 files changed, 10 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index d450d24689f6..b156cf56a30d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -204,66 +204,6 @@ void iwl_mld_ipv6_addr_change(struct ieee80211_hw *hw, } #endif -enum rt_status { - FW_ALIVE, - FW_NEEDS_RESET, - FW_ERROR, -}; - -static enum rt_status iwl_mld_check_err_tables(struct iwl_mld *mld, - struct ieee80211_vif *vif) -{ - u32 err_id; - - /* check for lmac1 error */ - if (iwl_fwrt_read_err_table(mld->trans, - mld->trans->dbg.lmac_error_event_table[0], - &err_id)) { - if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) { - struct cfg80211_wowlan_wakeup wakeup = { - .rfkill_release = true, - }; - ieee80211_report_wowlan_wakeup(vif, &wakeup, - GFP_KERNEL); - - return FW_NEEDS_RESET; - } - return FW_ERROR; - } - - /* check if we have lmac2 set and check for error */ - if (iwl_fwrt_read_err_table(mld->trans, - mld->trans->dbg.lmac_error_event_table[1], - NULL)) - return FW_ERROR; - - /* check for umac error */ - if (iwl_fwrt_read_err_table(mld->trans, - mld->trans->dbg.umac_error_event_table, - NULL)) - return FW_ERROR; - - return FW_ALIVE; -} - -static bool iwl_mld_fw_needs_restart(struct iwl_mld *mld, - struct ieee80211_vif *vif) -{ - enum rt_status rt_status = iwl_mld_check_err_tables(mld, vif); - - if (rt_status == FW_ALIVE) - return false; - - if (rt_status == FW_ERROR) { - IWL_ERR(mld, "FW Error occurred during suspend\n"); - iwl_fwrt_dump_error_logs(&mld->fwrt); - iwl_dbg_tlv_time_point(&mld->fwrt, - IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL); - } - - return true; -} - static int iwl_mld_netdetect_config(struct iwl_mld *mld, struct ieee80211_vif *vif, @@ -1383,10 +1323,7 @@ int iwl_mld_no_wowlan_resume(struct iwl_mld *mld) mld->fw_status.in_d3 = false; iwl_fw_dbg_read_d3_debug_data(&mld->fwrt); - if (iwl_mld_fw_needs_restart(mld, NULL)) - ret = -ENODEV; - else - ret = iwl_mld_wait_d3_notif(mld, &resume_data, false); + ret = iwl_mld_wait_d3_notif(mld, &resume_data, false); if (!ret && (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)) return -ENODEV; @@ -1935,15 +1872,10 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld) iwl_fw_dbg_read_d3_debug_data(&mld->fwrt); - if (iwl_mld_fw_needs_restart(mld, bss_vif)) { - fw_err = true; - goto err; - } - resume_data.wowlan_status = kzalloc(sizeof(*resume_data.wowlan_status), GFP_KERNEL); if (!resume_data.wowlan_status) - return -1; + return -ENOMEM; if (mld->netdetect) resume_data.notifs_expected |= IWL_D3_ND_MATCH_INFO; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 9b4bdbf40d4d..0f156e868504 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -508,8 +508,15 @@ int iwl_mld_mac80211_start(struct ieee80211_hw *hw) if (in_d3) { /* mac80211 already cleaned up the state, no need for cleanup */ ret = iwl_mld_no_wowlan_resume(mld); - if (ret) + if (ret) { iwl_mld_stop_fw(mld); + /* We're not really restarting in the sense of + * in_hw_restart even if we got an error during + * this. We'll just start again below and have + * nothing to recover, mac80211 will do anyway. + */ + mld->fw_status.in_hw_restart = false; + } } #endif /* CONFIG_PM_SLEEP */ From f26281c1b727b90ec18ae90044d5f429d2250e82 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:27 +0300 Subject: [PATCH 23/53] wifi: iwlwifi: mld: fix last_mlo_scan_time type This should be u64, otherwise it rolls over quickly on 32-bit systems. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.5381030253cd.I4e3a7bca5b52fc826e26311055286421508c4d1b@changeid --- drivers/net/wireless/intel/iwlwifi/mld/scan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.h b/drivers/net/wireless/intel/iwlwifi/mld/scan.h index 3ae940d55065..4044cac3f086 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.h @@ -130,7 +130,7 @@ struct iwl_mld_scan { void *cmd; unsigned long last_6ghz_passive_jiffies; unsigned long last_start_time_jiffies; - unsigned long last_mlo_scan_time; + u64 last_mlo_scan_time; }; #endif /* __iwl_mld_scan_h__ */ From 9748ad82a9d92b036ff3115207e36e2b9932e354 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:28 +0300 Subject: [PATCH 24/53] wifi: iwlwifi: defer MLO scan after link activation Doing a scan right after link activation can be less reliable than at other times, as the firmware is still busy trying to catch beacons from the just activated link, etc. In case a new MLO scan request comes in, defer it for a few seconds after a link activation. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.09548e958a9e.I24dbfd425da260f3ae6fa5a48fe25bd4ab6fcf99@changeid --- drivers/net/wireless/intel/iwlwifi/mld/iface.c | 15 +++++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/iface.h | 12 ++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/link.c | 4 ++++ drivers/net/wireless/intel/iwlwifi/mld/scan.c | 12 ++++++++++++ 4 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c index 235b55e0fe59..38993d65c052 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c @@ -55,6 +55,8 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif) ieee80211_iter_keys(mld->hw, vif, iwl_mld_cleanup_keys_iter, NULL); + wiphy_delayed_work_cancel(mld->wiphy, &mld_vif->mlo_scan_start_wk); + CLEANUP_STRUCT(mld_vif); } @@ -385,6 +387,17 @@ int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif, return iwl_mld_send_mac_cmd(mld, &cmd); } +static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy, + struct wiphy_work *wk) +{ + struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif, + mlo_scan_start_wk.work); + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); + + iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif)); +} + IWL_MLD_ALLOC_FN(vif, vif) /* Constructor function for struct iwl_mld_vif */ @@ -412,6 +425,8 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) iwl_mld_emlsr_prevent_done_wk); wiphy_delayed_work_init(&mld_vif->emlsr.tmp_non_bss_done_wk, iwl_mld_emlsr_tmp_non_bss_done_wk); + wiphy_delayed_work_init(&mld_vif->mlo_scan_start_wk, + iwl_mld_mlo_scan_start_wk); } iwl_mld_init_internal_sta(&mld_vif->aux_sta); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index 49e2ce65557d..874e9ef9e798 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -133,6 +133,8 @@ struct iwl_mld_emlsr { * @low_latency_causes: bit flags, indicating the causes for low-latency, * see @iwl_mld_low_latency_cause. * @ps_disabled: indicates that PS is disabled for this interface + * @last_link_activation_time: last time a link was activated, for + * deferring MLO scans (to make them more reliable) * @mld: pointer to the mld structure. * @deflink: default link data, for use in non-MLO, * @link: reference to link data for each valid link, for use in MLO. @@ -144,6 +146,7 @@ struct iwl_mld_emlsr { * @roc_activity: the id of the roc_activity running. Relevant for STA and * p2p device only. Set to %ROC_NUM_ACTIVITIES when not in use. * @aux_sta: station used for remain on channel. Used in P2P device. + * @mlo_scan_start_wk: worker to start a deferred MLO scan */ struct iwl_mld_vif { /* Add here fields that need clean up on restart */ @@ -161,6 +164,7 @@ struct iwl_mld_vif { #endif u8 low_latency_causes; bool ps_disabled; + time64_t last_link_activation_time; ); /* And here fields that survive a fw restart */ struct iwl_mld *mld; @@ -179,6 +183,8 @@ struct iwl_mld_vif { #endif enum iwl_roc_activity roc_activity; struct iwl_mld_int_sta aux_sta; + + struct wiphy_delayed_work mlo_scan_start_wk; }; static inline struct iwl_mld_vif * @@ -187,6 +193,12 @@ iwl_mld_vif_from_mac80211(struct ieee80211_vif *vif) return (void *)vif->drv_priv; } +static inline struct ieee80211_vif * +iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif) +{ + return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv); +} + #define iwl_mld_link_dereference_check(mld_vif, link_id) \ rcu_dereference_check((mld_vif)->link[link_id], \ lockdep_is_held(&mld_vif->mld->wiphy->mtx)) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index d0f56189ad3f..c65ac6ecbd1d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -404,6 +404,7 @@ int iwl_mld_activate_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link) { struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link); + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(mld_link->vif); int ret; lockdep_assert_wiphy(mld->wiphy); @@ -418,6 +419,9 @@ int iwl_mld_activate_link(struct iwl_mld *mld, LINK_CONTEXT_MODIFY_ACTIVE); if (ret) mld_link->active = false; + else + mld_vif->last_link_activation_time = + ktime_get_boottime_seconds(); return ret; } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 55d54bf29eae..cf3063e6ec53 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -1800,9 +1800,12 @@ static void iwl_mld_int_mlo_scan_start(struct iwl_mld *mld, IWL_DEBUG_SCAN(mld, "Internal MLO scan: ret=%d\n", ret); } +#define IWL_MLD_MLO_SCAN_BLOCKOUT_TIME 5 /* seconds */ + void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif) { struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS]; + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); unsigned long usable_links = ieee80211_vif_usable_links(vif); size_t n_channels = 0; u8 link_id; @@ -1818,6 +1821,15 @@ void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif) return; } + if (mld_vif->last_link_activation_time > ktime_get_boottime_seconds() - + IWL_MLD_MLO_SCAN_BLOCKOUT_TIME) { + /* timing doesn't matter much, so use the blockout time */ + wiphy_delayed_work_queue(mld->wiphy, + &mld_vif->mlo_scan_start_wk, + IWL_MLD_MLO_SCAN_BLOCKOUT_TIME); + return; + } + for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { struct ieee80211_bss_conf *link_conf = link_conf_dereference_check(vif, link_id); From 51512b654f1ca543cb7fbf24235671581c2180a9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:29 +0300 Subject: [PATCH 25/53] wifi: iwlwifi: dvm: fix some kernel-doc issues Fix a couple of kernel-doc warnings in the old DVM code. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.b33528d06431.I948261d6610c47f09133fa73f5e5ea9b9848fd21@changeid --- drivers/net/wireless/intel/iwlwifi/dvm/agn.h | 2 ++ drivers/net/wireless/intel/iwlwifi/dvm/commands.h | 14 +++++++------- drivers/net/wireless/intel/iwlwifi/dvm/dev.h | 4 ++-- drivers/net/wireless/intel/iwlwifi/dvm/devices.c | 2 ++ drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 2 ++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 1ebc7effcc2a..9fbdff28c88b 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h @@ -397,6 +397,8 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state) * returns a (newly allocated) struct containing all the * relevant values for driver use. The struct must be freed * later with iwl_free_nvm_data(). + * + * Return: the parsed NVM data */ struct iwl_nvm_data * iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h index 96ea6c8dfc89..9eef2134392e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2023-2024 Intel Corporation + * Copyright (C) 2005-2014, 2023-2025 Intel Corporation */ /* * Please use this file (commands.h) only for uCode API definitions. @@ -614,7 +614,7 @@ struct iwl_rxon_time_cmd { * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ /** - * struct iwl5000_channel_switch_cmd + * struct iwl5000_channel_switch_cmd - channel switch command (5000 series) * @band: 0- 5.2GHz, 1- 2.4GHz * @expect_beacon: 0- resume transmits after channel switch * 1- wait for beacon to resume transmits @@ -635,7 +635,7 @@ struct iwl5000_channel_switch_cmd { } __packed; /** - * struct iwl6000_channel_switch_cmd + * struct iwl6000_channel_switch_cmd - channel switch command (6000 series) * @band: 0- 5.2GHz, 1- 2.4GHz * @expect_beacon: 0- resume transmits after channel switch * 1- wait for beacon to resume transmits @@ -791,7 +791,7 @@ struct iwl_keyinfo { } __packed; /** - * struct sta_id_modify + * struct sta_id_modify - station modify command * @addr: station's MAC address * @reserved1: reserved for alignment * @sta_id: index of station in uCode's station table @@ -2992,7 +2992,7 @@ struct iwl_missed_beacon_notif { #define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1) /** - * struct iwl_sensitivity_cmd + * struct iwl_sensitivity_cmd - sensitivity configuration command * @control: (1) updates working table, (0) updates default table * @table: energy threshold values, use HD_* as index into table * @@ -3848,7 +3848,7 @@ struct iwlagn_wowlan_status { #define IWL_MIN_SLOT_TIME 20 /** - * struct iwl_wipan_slot + * struct iwl_wipan_slot - WiPAN slot configuration * @width: Time in TU * @type: * 0 - BSS @@ -3868,7 +3868,7 @@ struct iwl_wipan_slot { #define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5) /** - * struct iwl_wipan_params_cmd + * struct iwl_wipan_params_cmd - WiPAN parameters * @flags: * bit0: reserved * bit1: CP leave channel with CTS diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h index 25b24820466d..4d12bf901703 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h @@ -104,7 +104,7 @@ struct iwl_qos_info { }; /** - * enum iwl_agg_state + * enum iwl_agg_state - aggregation state * * The state machine of the BA agreement establishment / tear down. * These states relate to a specific RA / TID. @@ -519,7 +519,7 @@ enum iwl_scan_type { }; /** - * struct iwl_hw_params + * struct iwl_hw_params - HW parameters * * Holds the module parameters * diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index 3447ae0b160a..be7e61e2b291 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -55,6 +55,7 @@ static void iwl1000_nic_config(struct iwl_priv *priv) * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time * @priv: pointer to iwl_priv data structure * @tsf_bits: number of bits need to shift for masking) + * Return: low 32 bits of beacon time mask */ static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, u16 tsf_bits) @@ -66,6 +67,7 @@ static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time * @priv: pointer to iwl_priv data structure * @tsf_bits: number of bits need to shift for masking) + * Return: high 32 bits of beacon time mask */ static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, u16 tsf_bits) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index 24fefa0e8148..a7806776a51e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -232,6 +232,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, * that may be %NULL, for example during TX or key setup. In * that case, we need to use the broadcast station, so this * inline wraps that pattern. + * + * Return: station ID for mac80211 station (or broadcast if %NULL) */ static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context, struct ieee80211_sta *sta) From edc34789ca3387062d2d6a0bd06e2cb5cfc9ac4c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:30 +0300 Subject: [PATCH 26/53] wifi: iwlwifi: pcie: fix kernel-doc warnings Also fix the name of the iwl_prph_scratch_mem_desc_addr_array struct and some related spelling. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.ca2dec14f107.Ia4cfeea63e946f3b54e3e6b7bd6ab81130b0a7e6@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h | 5 ++++- .../net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index 0df379fda463..06be929a3ca5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -391,13 +391,13 @@ static int iwl_pcie_load_payloads_segments { struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0]; struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; - struct iwl_prph_scrath_mem_desc_addr_array *addresses; + struct iwl_prph_scratch_mem_desc_addr_array *addresses; const void *data; u32 len; int i; /* allocate and init DRAM descriptors array */ - len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array); + len = sizeof(struct iwl_prph_scratch_mem_desc_addr_array); desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent (trans, len, 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 ebcc174f6c62..b1dcaae0dc10 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -39,7 +39,7 @@ struct iwl_host_cmd; * trans_pcie layer */ /** - * struct iwl_rx_mem_buffer + * struct iwl_rx_mem_buffer - driver-side RX buffer descriptor * @page_dma: bus address of rxb page * @page: driver's pointer to the rxb page * @list: list entry for the membuffer @@ -190,6 +190,7 @@ struct iwl_rb_allocator { * iwl_get_closed_rb_stts - get closed rb stts from different structs * @trans: transport pointer (for configuration) * @rxq: the rxq to get the rb stts from + * Return: last closed RB index */ static inline u16 iwl_get_closed_rb_stts(struct iwl_trans *trans, struct iwl_rxq *rxq) @@ -703,6 +704,7 @@ static inline void iwl_txq_stop(struct iwl_trans *trans, struct iwl_txq *txq) * iwl_txq_inc_wrap - increment queue index, wrap back to beginning * @trans: the transport (for configuration data) * @index: current index + * Return: the queue index incremented, subject to wrapping */ static inline int iwl_txq_inc_wrap(struct iwl_trans *trans, int index) { @@ -714,6 +716,7 @@ static inline int iwl_txq_inc_wrap(struct iwl_trans *trans, int index) * iwl_txq_dec_wrap - decrement queue index, wrap back to end * @trans: the transport (for configuration data) * @index: current index + * Return: the queue index decremented, subject to wrapping */ static inline int iwl_txq_dec_wrap(struct iwl_trans *trans, int index) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h index 8c5c0ea46181..416baadc5017 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h @@ -130,11 +130,11 @@ struct iwl_prph_scratch_pnvm_cfg { } __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ /** - * struct iwl_prph_scrath_mem_desc_addr_array + * struct iwl_prph_scratch_mem_desc_addr_array - DRAM * @mem_descs: array of dram addresses. - * Each address is the beggining of a pnvm payload. + * Each address is the beginning of a PNVM payload. */ -struct iwl_prph_scrath_mem_desc_addr_array { +struct iwl_prph_scratch_mem_desc_addr_array { __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; } __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ From 4f372263ef92ed2af55a8c226750b72021ff8d0f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:31 +0300 Subject: [PATCH 27/53] wifi: iwlwifi: mei: fix kernel-doc warnings Fix some warnings and fill in some TBDs while at it. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.30bd10804d19.I21e7be2df56f20e1215dc35d94f3225708c5d74f@changeid --- drivers/net/wireless/intel/iwlwifi/mei/sap.h | 30 ++++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mei/sap.h b/drivers/net/wireless/intel/iwlwifi/mei/sap.h index 3b56637b9697..ba1f75f739c2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/sap.h +++ b/drivers/net/wireless/intel/iwlwifi/mei/sap.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2021 - 2022 Intel Corporation + * Copyright (C) 2021 - 2022, 2025 Intel Corporation */ #ifndef __sap_h__ @@ -340,12 +340,12 @@ enum iwl_sap_wifi_auth_type { }; /** - * enum iwl_sap_wifi_cipher_alg - * @SAP_WIFI_CIPHER_ALG_NONE: TBD - * @SAP_WIFI_CIPHER_ALG_TKIP: TBD - * @SAP_WIFI_CIPHER_ALG_CCMP: TBD - * @SAP_WIFI_CIPHER_ALG_GCMP: TBD - * @SAP_WIFI_CIPHER_ALG_GCMP_256: TBD + * enum iwl_sap_wifi_cipher_alg - MEI WiFi cipher algorithm IDs + * @SAP_WIFI_CIPHER_ALG_NONE: No encryption + * @SAP_WIFI_CIPHER_ALG_TKIP: TKIPO + * @SAP_WIFI_CIPHER_ALG_CCMP: CCMP + * @SAP_WIFI_CIPHER_ALG_GCMP: GCMP-128 + * @SAP_WIFI_CIPHER_ALG_GCMP_256: GCMP-256 */ enum iwl_sap_wifi_cipher_alg { SAP_WIFI_CIPHER_ALG_NONE = IWL_MEI_CIPHER_NONE, @@ -601,7 +601,7 @@ enum iwl_sap_flex_filter_flags { }; /** - * struct iwl_sap_flex_filter - + * struct iwl_sap_flex_filter - filter configuration * @src_port: Source port in network format. * @dst_port: Destination port in network format. * @flags: Flags and protocol, see &enum iwl_sap_flex_filter_flags. @@ -633,7 +633,7 @@ enum iwl_sap_ipv4_filter_flags { }; /** - * struct iwl_sap_ipv4_filter- + * struct iwl_sap_ipv4_filter - IPv4 filter configuration * @ipv4_addr: The IP address to filer. * @flags: See &enum iwl_sap_ipv4_filter_flags. */ @@ -643,7 +643,7 @@ struct iwl_sap_ipv4_filter { } __packed; /** - * enum iwl_sap_ipv6_filter_flags - + * enum iwl_sap_ipv6_filter_flags - IPv6 filter flags * @SAP_IPV6_ADDR_FILTER_COPY: Pass packets to the host. * @SAP_IPV6_ADDR_FILTER_ENABLED: If false, the filter should be ignored. */ @@ -653,7 +653,7 @@ enum iwl_sap_ipv6_filter_flags { }; /** - * struct iwl_sap_ipv6_filter - + * struct iwl_sap_ipv6_filter - IPv6 filter configuration * @addr_lo24: Lowest 24 bits of the IPv6 address. * @flags: See &enum iwl_sap_ipv6_filter_flags. */ @@ -663,7 +663,7 @@ struct iwl_sap_ipv6_filter { } __packed; /** - * enum iwl_sap_icmpv6_filter_flags - + * enum iwl_sap_icmpv6_filter_flags - ICMPv6 filter flags * @SAP_ICMPV6_FILTER_ENABLED: If false, the filter should be ignored. * @SAP_ICMPV6_FILTER_COPY: Pass packets to the host. */ @@ -673,8 +673,8 @@ enum iwl_sap_icmpv6_filter_flags { }; /** - * enum iwl_sap_vlan_filter_flags - - * @SAP_VLAN_FILTER_VLAN_ID_MSK: TBD + * enum iwl_sap_vlan_filter_flags - VLAN filter flags + * @SAP_VLAN_FILTER_VLAN_ID_MSK: VLAN ID * @SAP_VLAN_FILTER_ENABLED: If false, the filter should be ignored. */ enum iwl_sap_vlan_filter_flags { @@ -751,7 +751,7 @@ struct iwl_sap_pldr_data { } __packed; /** - * enum iwl_sap_pldr_status - + * enum iwl_sap_pldr_status - product reset status * @SAP_PLDR_STATUS_SUCCESS: PLDR started/ended successfully * @SAP_PLDR_STATUS_FAILURE: PLDR failed to start/end */ From 7ca8176b8eef3fda6f78f398c37d45739962c902 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:32 +0300 Subject: [PATCH 28/53] wifi: iwlwifi: mvm: fix kernel-doc warnings Some kernel-doc warnings remain, fix them. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.f238dd2937ed.I1b42df920b0f057a7d7ac01e61201621229a444c@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 3 ++- drivers/net/wireless/intel/iwlwifi/mvm/time-event.h | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index 69259ebb966b..dfb062b7c5c2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -411,6 +411,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, * with the mac80211 subsystem. This should be performed prior to calling * ieee80211_register_hw * + * Return: negative error code, or 0 on success */ int iwl_mvm_rate_control_register(void); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 6b183f5e9bbc..f6906061510b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -214,7 +214,7 @@ struct iwl_mvm_vif; */ /** - * enum iwl_mvm_agg_state + * enum iwl_mvm_agg_state - aggregation session state * * The state machine of the BA agreement establishment / tear down. * These states relate to a specific RA / TID. @@ -483,6 +483,7 @@ struct iwl_mvm_int_sta { * about. Otherwise (if this is a new STA), this should be false. * @flags: if update==true, this marks what is being changed via ORs of values * from enum iwl_sta_modify_flag. Otherwise, this is ignored. + * Return: negative error code or 0 on success */ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, bool update, unsigned int flags); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h index 49256ba4cf58..1ef8768756db 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2019-2020, 2023 Intel Corporation + * Copyright (C) 2012-2014, 2019-2020, 2023, 2025 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH */ #ifndef __time_event_h__ @@ -124,6 +124,8 @@ void iwl_mvm_rx_roc_notif(struct iwl_mvm *mvm, * ROC request, it will issue a notification to the driver that it is on the * requested channel. Once the FW completes the ROC request it will issue * another notification to the driver. + * + * Return: negative error code or 0 on success */ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int duration, enum ieee80211_roc_type type); @@ -179,6 +181,8 @@ void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm, * * This function is used to schedule NoA time event and is used to perform * the channel switch flow. + * + * Return: negative error code or 0 on success */ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -188,7 +192,7 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm, * iwl_mvm_te_scheduled - check if the fw received the TE cmd * @te_data: the time event data that corresponds to that time event * - * This function returns true iff this TE is added to the fw. + * Return: %true if this TE is added to the fw, %false otherwise */ static inline bool iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data) From 8ddf4e19de1e98091ace48626b9245f9d985a6bd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:33 +0300 Subject: [PATCH 29/53] wifi: iwlwifi: mld: make PHY config a debug message This means nothing to a normal user and really has no value for most people, print it as a debug message instead. Signed-off-by: Johannes Berg Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.ee6254c03a33.I2cf4e1e2e604b42b6eb9737c0ef3b75fec69edea@changeid --- drivers/net/wireless/intel/iwlwifi/mld/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.c b/drivers/net/wireless/intel/iwlwifi/mld/phy.c index d5a32ee56b92..1d93fb9e4dbf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/phy.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.c @@ -181,7 +181,7 @@ int iwl_mld_send_phy_cfg_cmd(struct iwl_mld *mld) .phy_specific_cfg = mld->fwrt.phy_filters, }; - IWL_INFO(mld, "Sending Phy CFG command: 0x%x\n", cmd.phy_cfg); + IWL_DEBUG_INFO(mld, "Sending Phy CFG command: 0x%x\n", cmd.phy_cfg); return iwl_mld_send_cmd_pdu(mld, PHY_CONFIGURATION_CMD, &cmd); } From d41e3781c86415f1994ffdd266b28450847b7ddb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jun 2025 22:26:34 +0300 Subject: [PATCH 30/53] wifi: iwlwifi: fw: make PNVM version a debug message This means nothing to a normal user and really has no value for most people, print it as a debug message instead. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250611222325.0f77cb90aa20.I06f2adca38d012a71cde3956e1d2005293f70604@changeid --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 4f3c2f7f4f5b..3bcd375995cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -332,7 +332,7 @@ iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans, ret = iwl_trans_load_pnvm(trans, pnvm_data, capa); if (ret) goto free; - IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version); + IWL_DEBUG_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version); set: iwl_trans_set_pnvm(trans, capa); From 12d0026ea3c2277eb054c8ec04f419f327a9da49 Mon Sep 17 00:00:00 2001 From: Yuesong Li Date: Thu, 12 Jun 2025 10:24:53 +0800 Subject: [PATCH 31/53] wifi: iwlwifi: convert to use secs_to_jiffies() Since secs_to_jiffies()(commit:b35108a51cf7) has been introduced, we can use it to avoid scaling the time to msec. Signed-off-by: Yuesong Li Link: https://patch.msgid.link/20250612022501.3492345-1-liyuesong@vivo.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 5f8b60824043..b34ee68f3dce 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -429,7 +429,7 @@ static void iwlagn_rx_statistics(struct iwl_priv *priv, * thermal update even if the uCode doesn't give * us one */ mod_timer(&priv->statistics_periodic, jiffies + - msecs_to_jiffies(reg_recalib_period * 1000)); + secs_to_jiffies(reg_recalib_period)); if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index c70f2a20f7d5..803ba35e7501 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -198,7 +198,7 @@ void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay) iwl_fw_cancel_timestamp(fwrt); - fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000); + fwrt->timestamp.delay = secs_to_jiffies(delay); schedule_delayed_work(&fwrt->timestamp.wk, round_jiffies_relative(fwrt->timestamp.delay)); From ad80cb3c72dd85af6ef3c58882280418209eefb4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Jun 2025 14:48:47 +0300 Subject: [PATCH 32/53] wifi: iwlwifi: make FSEQ version a debug message This means nothing to a normal user and really has no value for most people, print it as a debug message instead. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144707.dce85795612b.I24807178fa7ddc7c2edfce3dc30f81bced846b35@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 9504a0cb8b13..6492bc7d1680 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1276,8 +1276,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, if (tlv_len != sizeof(*fseq_ver)) goto invalid_tlv_len; - IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n", - fseq_ver->version); + IWL_DEBUG_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n", + fseq_ver->version); } break; case IWL_UCODE_TLV_FW_NUM_STATIONS: From 873cc719523d835e7f85be8fab0a3c78b4c98162 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Jun 2025 14:48:48 +0300 Subject: [PATCH 33/53] wifi: iwlwifi: add HE 1024QAM for <242-tone RU for PE For the new PE RF, this should also be supported. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.5716b631c59a.If81456c73a2d5834c29cbf410f7e642184c32b82@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index c5c80f72696f..1e4162f1bb44 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1047,6 +1047,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, 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) From 6a1b633fdcd904901db9162462b7c0f0897800e3 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 12 Jun 2025 14:48:49 +0300 Subject: [PATCH 34/53] wifi: iwlwifi: support RZL platform device ID Add support for a new device ID that we will have on RZL. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.0c509d05fc51.I462e2ca5b636b88764177b9e41a63f7717f50793@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index a42a6da5d2ea..4201c4b07e3b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -545,6 +545,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xE340, PCI_ANY_ID, iwl_sc_mac_cfg)}, {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 */ {0} From b2c1f9b6e3aac9567c84208b73d716cc5d456404 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 12 Jun 2025 14:48:50 +0300 Subject: [PATCH 35/53] wifi: iwlwifi: mld: use the correct struct size for tracing For the iwlmld driver the RX command is using struct iwl_rx_mpdu_desc and not the much older struct iwl_rx_mpdu_res_start. Adjust the value of rx_mpdu_cmd_hdr_size accordingly so that the trace data is correct. Signed-off-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.688d95d99ff3.Id3055ca6c19cf8c821cbbd80c09ca2a21d9acec7@changeid --- drivers/net/wireless/intel/iwlwifi/mld/mld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 103912c4e4cc..73bb32ec8076 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -356,7 +356,7 @@ iwl_mld_configure_trans(struct iwl_op_mode *op_mode) trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD; - trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); + trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc); trans->conf.wide_cmd_header = true; iwl_trans_op_mode_enter(trans, op_mode); From b04e93bb6dd2005192fedf139d651bda94a4e34c Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 12 Jun 2025 14:48:51 +0300 Subject: [PATCH 36/53] wifi: iwlwifi: mld: Block EMLSR when scanning on P2P Device Temporarily block EMLSR when scanning on a P2P Device interface, as this is an indication that P2P activity is about to start, e.g., P2P client connection to a P2P GO. Since a P2P scan while a station interface connection is active might be long, increase the EMLSR blocking timeout to 10 seconds. Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.85fb79d537fe.I27523f8d3f00f2b66f5f555f098e323be29465ea@changeid --- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 27 +---------------- drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 30 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/mlo.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mld/scan.c | 4 +++ 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 0f156e868504..1eb4dfb83778 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -2580,28 +2580,6 @@ static int iwl_mld_mac80211_tx_last_beacon(struct ieee80211_hw *hw) return mld->ibss_manager; } -#define IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT (5 * HZ) - -static void iwl_mld_vif_iter_emlsr_block_tmp_non_bss(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); - int ret; - - if (!iwl_mld_vif_has_emlsr_cap(vif)) - return; - - ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif, - IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS, - iwl_mld_get_primary_link(vif)); - if (ret) - return; - - wiphy_delayed_work_queue(mld_vif->mld->wiphy, - &mld_vif->emlsr.tmp_non_bss_done_wk, - IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT); -} - static void iwl_mld_prep_add_interface(struct ieee80211_hw *hw, enum nl80211_iftype type) { @@ -2614,10 +2592,7 @@ static void iwl_mld_prep_add_interface(struct ieee80211_hw *hw, type == NL80211_IFTYPE_P2P_CLIENT)) return; - ieee80211_iterate_active_interfaces_mtx(mld->hw, - IEEE80211_IFACE_ITER_NORMAL, - iwl_mld_vif_iter_emlsr_block_tmp_non_bss, - NULL); + iwl_mld_emlsr_block_tmp_non_bss(mld); } static int iwl_mld_set_hw_timestamp(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index 20c2b436039a..8ed2c6de1282 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -287,6 +287,36 @@ int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif, return _iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, true); } +#define IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT (10 * HZ) + +static void iwl_mld_vif_iter_emlsr_block_tmp_non_bss(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); + int ret; + + if (!iwl_mld_vif_has_emlsr_cap(vif)) + return; + + ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif, + IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS, + iwl_mld_get_primary_link(vif)); + if (ret) + return; + + wiphy_delayed_work_queue(mld_vif->mld->wiphy, + &mld_vif->emlsr.tmp_non_bss_done_wk, + IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT); +} + +void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld) +{ + ieee80211_iterate_active_interfaces_mtx(mld->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mld_vif_iter_emlsr_block_tmp_non_bss, + NULL); +} + static void _iwl_mld_select_links(struct iwl_mld *mld, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h index 9afa3d6ea649..704f64134798 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h @@ -157,6 +157,8 @@ struct iwl_mld_link_sel_data { u16 grade; }; +void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld); + #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif, struct iwl_mld_link_sel_data *a, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index cf3063e6ec53..63d5d39bb083 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -1752,6 +1752,10 @@ int iwl_mld_regular_scan_start(struct iwl_mld *mld, struct ieee80211_vif *vif, struct cfg80211_scan_request *req, struct ieee80211_scan_ies *ies) { + + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) + iwl_mld_emlsr_block_tmp_non_bss(mld); + return _iwl_mld_single_scan_start(mld, vif, req, ies, IWL_MLD_SCAN_REGULAR); } From 69749bc08cc037d6dfcaa9955df9857f9172375b Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 12 Jun 2025 14:48:52 +0300 Subject: [PATCH 37/53] wifi: iwlwifi: mld: advertise support for TTLM changes The iwlmld driver is able to handle TTLM changes as long as all TIDs have the same TID to Link Mapping. Add the corresponding code so that mac80211 will accept and trigger the TTLM change. Signed-off-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.3b0a4fd2c12b.I1fab7840f1cc222bd1e8cb58ac1a4177474fcd56@changeid --- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 1eb4dfb83778..a8b2e2046d76 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -2622,6 +2622,23 @@ static int iwl_mld_start_pmsr(struct ieee80211_hw *hw, return iwl_mld_ftm_start(mld, vif, request); } +static enum ieee80211_neg_ttlm_res +iwl_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_neg_ttlm *neg_ttlm) +{ + u16 map; + + /* Verify all TIDs are mapped to the same links set */ + map = neg_ttlm->downlink[0]; + for (int i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) { + if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] || + neg_ttlm->uplink[i] != map) + return NEG_TTLM_RES_REJECT; + } + + return NEG_TTLM_RES_ACCEPT; +} + const struct ieee80211_ops iwl_mld_hw_ops = { .tx = iwl_mld_mac80211_tx, .start = iwl_mld_mac80211_start, @@ -2691,4 +2708,5 @@ const struct ieee80211_ops iwl_mld_hw_ops = { .prep_add_interface = iwl_mld_prep_add_interface, .set_hw_timestamp = iwl_mld_set_hw_timestamp, .start_pmsr = iwl_mld_start_pmsr, + .can_neg_ttlm = iwl_mld_can_neg_ttlm, }; From e4efdfcaaf49bd3d5c507f694e94320383ab7983 Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 12 Jun 2025 14:48:53 +0300 Subject: [PATCH 38/53] wifi: iwlwifi: pcie: move iwl_trans_pcie_dump_regs() to utils.c Move the iwl_trans_pcie_dump_regs() function to utils.c in the PCIe directory since it operates on PCIe registers and is not hardware-dependent. Refactor the pcie_dbg_dumped_once indicator, previously part of the iwl_trans_pcie struct, into a static variable within the iwl_trans_pcie_dump_regs() function, where it is used. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.06950459ce97.I3105158eb9ae698efebe4b9ada1093aeb1f1b869@changeid --- drivers/net/wireless/intel/iwlwifi/Makefile | 2 +- .../intel/iwlwifi/pcie/gen1_2/internal.h | 3 - .../intel/iwlwifi/pcie/gen1_2/trans.c | 101 +---------------- .../net/wireless/intel/iwlwifi/pcie/utils.c | 104 ++++++++++++++++++ .../net/wireless/intel/iwlwifi/pcie/utils.h | 11 ++ 5 files changed, 120 insertions(+), 101 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/pcie/utils.c create mode 100644 drivers/net/wireless/intel/iwlwifi/pcie/utils.h diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index 71101067b889..b82392978b76 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -9,7 +9,7 @@ iwlwifi-objs += iwl-utils.o iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o # Bus -iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o +iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o 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 b1dcaae0dc10..52c6c22e2cc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -384,7 +384,6 @@ struct iwl_pcie_txqs { * @txq_memory: TXQ allocation array * @sx_waitq: waitqueue for Sx transitions * @sx_state: state tracking Sx transitions - * @pcie_dbg_dumped_once: indicates PCIe regs were dumped already * @opmode_down: indicates opmode went away * @num_rx_bufs: number of RX buffers to allocate/use * @affinity_mask: IRQ affinity mask for each RX queue @@ -460,7 +459,6 @@ struct iwl_trans_pcie { u16 num_rx_bufs; - bool pcie_dbg_dumped_once; u32 rx_page_order; u32 rx_buf_bytes; u32 supported_dma_mask; @@ -1069,7 +1067,6 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) } void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state, bool from_irq); -void iwl_trans_pcie_dump_regs(struct iwl_trans *trans); #ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); 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 6054ebebd8c8..c31a62b8f925 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -29,105 +29,12 @@ #include "internal.h" #include "iwl-fh.h" #include "pcie/iwl-context-info-v2.h" +#include "pcie/utils.h" /* extended range in FW SRAM */ #define IWL_FW_MEM_EXTENDED_START 0x40000 #define IWL_FW_MEM_EXTENDED_END 0x57FFF -void iwl_trans_pcie_dump_regs(struct iwl_trans *trans) -{ -#define PCI_DUMP_SIZE 352 -#define PCI_MEM_DUMP_SIZE 64 -#define PCI_PARENT_DUMP_SIZE 524 -#define PREFIX_LEN 32 - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct pci_dev *pdev = trans_pcie->pci_dev; - u32 i, pos, alloc_size, *ptr, *buf; - char *prefix; - - if (trans_pcie->pcie_dbg_dumped_once) - return; - - /* Should be a multiple of 4 */ - BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3); - BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3); - BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3); - - /* Alloc a max size buffer */ - alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN; - alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN); - alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN); - alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN); - - buf = kmalloc(alloc_size, GFP_ATOMIC); - if (!buf) - return; - prefix = (char *)buf + alloc_size - PREFIX_LEN; - - IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n"); - - /* Print wifi device registers */ - sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); - IWL_ERR(trans, "iwlwifi device config registers:\n"); - for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++) - if (pci_read_config_dword(pdev, i, ptr)) - goto err_read; - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); - - IWL_ERR(trans, "iwlwifi device memory mapped registers:\n"); - for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++) - *ptr = iwl_read32(trans, i); - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - if (pos) { - IWL_ERR(trans, "iwlwifi device AER capability structure:\n"); - for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++) - if (pci_read_config_dword(pdev, pos + i, ptr)) - goto err_read; - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, - 32, 4, buf, i, 0); - } - - /* Print parent device registers next */ - if (!pdev->bus->self) - goto out; - - pdev = pdev->bus->self; - sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); - - IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n", - pci_name(pdev)); - for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++) - if (pci_read_config_dword(pdev, i, ptr)) - goto err_read; - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); - - /* Print root port AER registers */ - pos = 0; - pdev = pcie_find_root_port(pdev); - if (pdev) - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - if (pos) { - IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n", - pci_name(pdev)); - sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); - for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++) - if (pci_read_config_dword(pdev, pos + i, ptr)) - goto err_read; - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, - 4, buf, i, 0); - } - goto out; - -err_read: - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); - IWL_ERR(trans, "Read failed at 0x%X\n", i); -out: - trans_pcie->pcie_dbg_dumped_once = 1; - kfree(buf); -} - int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ @@ -704,7 +611,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, trans_pcie->ucode_write_complete, 5 * HZ); if (!ret) { IWL_ERR(trans, "Failed to load firmware chunk!\n"); - iwl_trans_pcie_dump_regs(trans); + iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev); return -ETIMEDOUT; } @@ -2460,7 +2367,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", cntrl); - iwl_trans_pcie_dump_regs(trans); + iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev); if (iwlwifi_mod_params.remove_when_gone && cntrl == ~0U) iwl_trans_pcie_reset(trans, @@ -4057,7 +3964,7 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans, IMR_D2S_REQUESTED, 5 * HZ); if (!ret || trans_pcie->imr_status == IMR_D2S_ERROR) { IWL_ERR(trans, "Failed to copy IMR Memory chunk!\n"); - iwl_trans_pcie_dump_regs(trans); + iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev); return -ETIMEDOUT; } trans_pcie->imr_status = IMR_D2S_IDLE; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c new file mode 100644 index 000000000000..1bb274d8390c --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2025 Intel Corporation + */ + +#include +#include + +#include "iwl-io.h" +#include "pcie/utils.h" + +void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev) +{ +#define PCI_DUMP_SIZE 352 +#define PCI_MEM_DUMP_SIZE 64 +#define PCI_PARENT_DUMP_SIZE 524 +#define PREFIX_LEN 32 + + static bool pcie_dbg_dumped_once = 0; + u32 i, pos, alloc_size, *ptr, *buf; + char *prefix; + + if (pcie_dbg_dumped_once) + return; + + /* Should be a multiple of 4 */ + BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3); + BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3); + BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3); + + /* Alloc a max size buffer */ + alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN; + alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN); + alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN); + alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN); + + buf = kmalloc(alloc_size, GFP_ATOMIC); + if (!buf) + return; + prefix = (char *)buf + alloc_size - PREFIX_LEN; + + IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n"); + + /* Print wifi device registers */ + sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); + IWL_ERR(trans, "iwlwifi device config registers:\n"); + for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++) + if (pci_read_config_dword(pdev, i, ptr)) + goto err_read; + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); + + IWL_ERR(trans, "iwlwifi device memory mapped registers:\n"); + for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++) + *ptr = iwl_read32(trans, i); + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); + if (pos) { + IWL_ERR(trans, "iwlwifi device AER capability structure:\n"); + for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++) + if (pci_read_config_dword(pdev, pos + i, ptr)) + goto err_read; + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, + 32, 4, buf, i, 0); + } + + /* Print parent device registers next */ + if (!pdev->bus->self) + goto out; + + pdev = pdev->bus->self; + sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); + + IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n", + pci_name(pdev)); + for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++) + if (pci_read_config_dword(pdev, i, ptr)) + goto err_read; + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); + + /* Print root port AER registers */ + pos = 0; + pdev = pcie_find_root_port(pdev); + if (pdev) + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); + if (pos) { + IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n", + pci_name(pdev)); + sprintf(prefix, "iwlwifi %s: ", pci_name(pdev)); + for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++) + if (pci_read_config_dword(pdev, pos + i, ptr)) + goto err_read; + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, + 4, buf, i, 0); + } + goto out; + +err_read: + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); + IWL_ERR(trans, "Read failed at 0x%X\n", i); +out: + pcie_dbg_dumped_once = 1; + kfree(buf); +} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h new file mode 100644 index 000000000000..af2a2eec7ec5 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2025 Intel Corporation + */ + +#ifndef __iwl_pcie_utils_h__ +#define __iwl_pcie_utils_h__ + +void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); + +#endif /* __iwl_pcie_utils_h__ */ From 9feeb4caec93fdf838f23faa6e3f3b9c2f97f99c Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 12 Jun 2025 14:48:54 +0300 Subject: [PATCH 39/53] wifi: iwlwifi: move iwl_trans_pcie_write_mem to iwl-trans.c Move the iwl_trans_pcie_write_mem function to iwl_trans_write_mem in iwl-trans.c as it is not specific to PCIe. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.52034d131773.Ie783304faae7ec3a95a510dfee925838fe6466b4@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 14 +++++++++++++- .../intel/iwlwifi/pcie/gen1_2/internal.h | 2 -- .../wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 18 ------------------ .../wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 11 +++++------ 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 5dba76b009a6..78808c956444 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -497,7 +497,19 @@ IWL_EXPORT_SYMBOL(iwl_trans_read_mem); int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, const void *buf, int dwords) { - return iwl_trans_pcie_write_mem(trans, addr, buf, dwords); + int offs, ret = 0; + const u32 *vals = buf; + + if (iwl_trans_grab_nic_access(trans)) { + iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); + for (offs = 0; offs < dwords; offs++) + iwl_write32(trans, HBUS_TARG_MEM_WDAT, + vals ? vals[offs] : 0); + iwl_trans_release_nic_access(trans); + } else { + ret = -EBUSY; + } + return ret; } IWL_EXPORT_SYMBOL(iwl_trans_write_mem); 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 52c6c22e2cc6..007f63a8d3c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1089,8 +1089,6 @@ u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg); void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val); int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords); -int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, - const void *buf, int dwords); int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership); struct iwl_trans_dump_data * iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask, 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 c31a62b8f925..174bfc66c285 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -2485,24 +2485,6 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, return 0; } -int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, - const void *buf, int dwords) -{ - int offs, ret = 0; - const u32 *vals = buf; - - if (iwl_trans_grab_nic_access(trans)) { - iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); - for (offs = 0; offs < dwords; offs++) - iwl_write32(trans, HBUS_TARG_MEM_WDAT, - vals ? vals[offs] : 0); - iwl_trans_release_nic_access(trans); - } else { - ret = -EBUSY; - } - return ret; -} - int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs, u32 *val) { 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 7abd7c7daa89..e39451d27a93 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -494,9 +494,9 @@ void iwl_pcie_tx_start(struct iwl_trans *trans) iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); /* reset context data, TX status and translation data */ - iwl_trans_pcie_write_mem(trans, trans_pcie->scd_base_addr + - SCD_CONTEXT_MEM_LOWER_BOUND, - NULL, clear_dwords); + iwl_trans_write_mem(trans, trans_pcie->scd_base_addr + + SCD_CONTEXT_MEM_LOWER_BOUND, + NULL, clear_dwords); iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, trans_pcie->txqs.scd_bc_tbls.dma >> 10); @@ -1292,9 +1292,8 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, if (configure_scd) { iwl_scd_txq_set_inactive(trans, txq_id); - iwl_trans_pcie_write_mem(trans, stts_addr, - (const void *)zero_val, - ARRAY_SIZE(zero_val)); + iwl_trans_write_mem(trans, stts_addr, (const void *)zero_val, + ARRAY_SIZE(zero_val)); } iwl_pcie_txq_unmap(trans, txq_id); From 877924979ef0c696ff3f9eecbb6e79d831f13fdf Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 12 Jun 2025 14:48:55 +0300 Subject: [PATCH 40/53] wifi: iwlwifi: mld: make iwl_mld_add_all_rekeys void No one checks its return value anyway. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.4c38fb4c48f4.Ia62100a54370b6af5e528ba10c8f21e177018096@changeid --- drivers/net/wireless/intel/iwlwifi/mld/d3.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index b156cf56a30d..d9af9a2b1e6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -868,7 +868,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, return true; } -static bool +static void iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, struct iwl_mld_wowlan_status *wowlan_status, struct iwl_mld_resume_key_iter_data *key_iter_data, @@ -881,21 +881,19 @@ iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, &wowlan_status->gtk[i], link_conf, key_iter_data->gtk_cipher)) - return false; + return; if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, &wowlan_status->igtk, link_conf, key_iter_data->igtk_cipher)) - return false; + return; 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 false; - - return true; + return; } static bool From dc6bc5112166390e0b64ff5f593bb8ff53b9c00e Mon Sep 17 00:00:00 2001 From: Rotem Kerem Date: Thu, 12 Jun 2025 14:48:56 +0300 Subject: [PATCH 41/53] wifi: iwlwifi: move _iwl_trans_set_bits_mask utilities Move set_bits_mask utility functions to utils.h as they are generic utilities and is not hardware-dependent. Signed-off-by: Rotem Kerem Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.4049f1eda9fa.Iddcb6f7437beee2cfe232315384d8517b40c56d1@changeid --- .../intel/iwlwifi/pcie/gen1_2/internal.h | 27 ------------------ .../intel/iwlwifi/pcie/gen1_2/trans.c | 28 +++++++++---------- .../wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 5 ++-- .../net/wireless/intel/iwlwifi/pcie/utils.h | 27 ++++++++++++++++++ 4 files changed, 44 insertions(+), 43 deletions(-) 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 007f63a8d3c8..23c0771a4231 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1034,33 +1034,6 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); } -static inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, - u32 reg, u32 mask, u32 value) -{ - u32 v; - -#ifdef CONFIG_IWLWIFI_DEBUG - WARN_ON_ONCE(value & ~mask); -#endif - - v = iwl_read32(trans, reg); - v &= ~mask; - v |= value; - iwl_write32(trans, reg, v); -} - -static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans, - u32 reg, u32 mask) -{ - __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0); -} - -static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans, - u32 reg, u32 mask) -{ - __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); -} - static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) { return (trans->dbg.dest_tlv || iwl_trans_dbg_ini_valid(trans)); 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 174bfc66c285..97e90cbeb6cd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -294,8 +294,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) u32 dl_cfg_reg; /* Force XTAL ON */ - __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); ret = iwl_trans_pcie_sw_reset(trans, true); @@ -304,8 +304,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) if (WARN_ON(ret)) { /* Release XTAL ON request */ - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); return; } @@ -356,12 +356,12 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* Activates XTAL resources monitor */ - __iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, - CSR_MONITOR_XTAL_RESOURCES); + iwl_trans_set_bit(trans, CSR_MONITOR_CFG_REG, + CSR_MONITOR_XTAL_RESOURCES); /* Release XTAL ON request */ - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); udelay(10); /* Release APMG XTAL */ @@ -2330,7 +2330,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) } /* this bit wakes up the NIC */ - __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, write); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, write); if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) udelay(2); @@ -2419,11 +2419,11 @@ iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) if (trans_pcie->cmd_hold_nic_awake) goto out; if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); else - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * Above we read the CSR_GP_CNTRL register, which will flush * any previous writes, but we need the write that clears the @@ -2604,7 +2604,7 @@ void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); spin_lock_bh(&trans_pcie->reg_lock); - __iwl_trans_pcie_set_bits_mask(trans, reg, mask, value); + _iwl_trans_set_bits_mask(trans, reg, mask, value); spin_unlock_bh(&trans_pcie->reg_lock); } 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 e39451d27a93..6b052b36dfa7 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 "pcie/utils.h" /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services @@ -203,8 +204,8 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) } trans_pcie->cmd_hold_nic_awake = false; - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock(&trans_pcie->reg_lock); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index af2a2eec7ec5..031dfdf4bba4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -8,4 +8,31 @@ 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, + u32 reg, u32 mask, u32 value) +{ + u32 v; + +#ifdef CONFIG_IWLWIFI_DEBUG + WARN_ON_ONCE(value & ~mask); +#endif + + v = iwl_read32(trans, reg); + v &= ~mask; + v |= value; + iwl_write32(trans, reg, v); +} + +static inline void iwl_trans_clear_bit(struct iwl_trans *trans, + u32 reg, u32 mask) +{ + _iwl_trans_set_bits_mask(trans, reg, mask, 0); +} + +static inline void iwl_trans_set_bit(struct iwl_trans *trans, + u32 reg, u32 mask) +{ + _iwl_trans_set_bits_mask(trans, reg, mask, mask); +} + #endif /* __iwl_pcie_utils_h__ */ From 0cdb8ff6ebbac55f38933f4621215784887b400e Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 12 Jun 2025 14:48:57 +0300 Subject: [PATCH 42/53] wifi: iwlwifi: mld: don't exit EMLSR when we shouldn't There is a requirement to exit EMLSR if there wasn't enough throughput in the secondary link. This is checked in check_tpt_wk, which runs every 5 seconds in a high throughput scenario (when the throughput blocker isn't set) It can happen that this worker is running immediately after we entered EMLSR, and in that case the secondary link didn't have a chance to have throughput. In that case we will exit EMLSR for no good reason. Fix this by tracking the time we entered EMLSR, and in the worker make sure that 5 seconds passed from when we entered EMLSR. If not, don't check the secondary link throughput. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.c680f8d7dc37.I8a02d1e8d99df3789da8d5714f19b31a865a61ff@changeid --- drivers/net/wireless/intel/iwlwifi/mld/iface.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 1 + drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index 874e9ef9e798..05dcb63701b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -87,6 +87,8 @@ enum iwl_mld_emlsr_exit { * @last_exit_reason: Reason for the last EMLSR exit * @last_exit_ts: Time of the last EMLSR exit (if @last_exit_reason is non-zero) * @exit_repeat_count: Number of times EMLSR was exited for the same reason + * @last_entry_ts: the time of the last EMLSR entry (if iwl_mld_emlsr_active() + * is true) * @unblock_tpt_wk: Unblock EMLSR because the throughput limit was reached * @check_tpt_wk: a worker to check if IWL_MLD_EMLSR_BLOCKED_TPT should be * added, for example if there is no longer enough traffic. @@ -105,6 +107,7 @@ struct iwl_mld_emlsr { enum iwl_mld_emlsr_exit last_exit_reason; unsigned long last_exit_ts; u8 exit_repeat_count; + unsigned long last_entry_ts; ); struct wiphy_work unblock_tpt_wk; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index a8b2e2046d76..8a24ca0e1e89 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1009,6 +1009,7 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw, /* Indicate to mac80211 that EML is enabled */ vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE; + mld_vif->emlsr.last_entry_ts = jiffies; if (vif->active_links & BIT(mld_vif->emlsr.selected_links)) mld_vif->emlsr.primary = mld_vif->emlsr.selected_primary; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index 8ed2c6de1282..be66a71a0fd7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -560,10 +560,12 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk) /* * TPT is unblocked, need to check if the TPT criteria is still met. * - * If EMLSR is active, then we also need to check the secondar link - * requirements. + * If EMLSR is active for at least 5 seconds, then we also + * need to check the secondary link requirements. */ - if (iwl_mld_emlsr_active(vif)) { + if (iwl_mld_emlsr_active(vif) && + time_is_before_jiffies(mld_vif->emlsr.last_entry_ts + + IWL_MLD_TPT_COUNT_WINDOW)) { sec_link_id = iwl_mld_get_other_link(vif, iwl_mld_get_primary_link(vif)); sec_link = iwl_mld_link_dereference_check(mld_vif, sec_link_id); if (WARN_ON_ONCE(!sec_link)) From 43049a3c00c8cb4af57b72ca77e3b09ae25b3ab4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Jun 2025 14:48:59 +0300 Subject: [PATCH 43/53] wifi: iwlwifi: pcie: fix non-MSIX handshake register When reading the interrupt status after a FW reset handshake timeout, read the actual value not the mask for the non-MSIX case. Fixes: ab606dea80c4 ("wifi: iwlwifi: pcie: add support for the reset handshake in MSI") Signed-off-by: Johannes Berg Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250612144708.83aafead6061.I2f8571aafa55aa3b936a30b938de9d260592a584@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b5e4b60f710c..0df8522ca410 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 @@ -125,7 +125,7 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) reset_done = inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE; } else { - inta_hw = iwl_read32(trans, CSR_INT_MASK); + inta_hw = iwl_read32(trans, CSR_INT); reset_done = inta_hw & CSR_INT_BIT_RESET_DONE; } From 6ae66c95d996ce32eaf5e94094d392edf0415bc8 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Apr 2025 11:26:07 +0300 Subject: [PATCH 44/53] MAINTAINERS: update iwlwifi git link The link is wrong, fix it. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250430112552.1eb2dee64e96.Ic462b7be21af71a3c27eddb5b56e1b46f07ac91d@changeid Signed-off-by: Miri Korenblit --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7d2074d16107..931e2c30bb1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12427,7 +12427,7 @@ M: Miri Korenblit L: linux-wireless@vger.kernel.org S: Supported W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi -T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git +T: git https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/ F: drivers/net/wireless/intel/iwlwifi/ INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER From 8bc63120b08486e9f19e2cdd927de82c801ce273 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Apr 2025 16:00:18 +0200 Subject: [PATCH 45/53] wifi: iwlwifi: mld: ftm: fix switch end indentation The terminating brace for the switch statement is erroneously not indented, fix that. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20250422160017.6d4cff49cbf4.I8e5570a6fe94faa9f17a89352b7ba645fc875e77@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c index f77ba21a174d..3464b3268712 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c @@ -94,7 +94,7 @@ iwl_mld_ftm_set_target_chandef(struct iwl_mld *mld, IWL_ERR(mld, "Unsupported BW in FTM request (%d)\n", peer->chandef.width); return -EINVAL; -} + } /* non EDCA based measurement must use HE preamble */ if (peer->ftm.trigger_based || peer->ftm.non_trigger_based) From c14bfe8d458175ccb388a2b11cbd3bf676803770 Mon Sep 17 00:00:00 2001 From: Zheng Yongjun Date: Wed, 9 Dec 2020 17:37:34 +0800 Subject: [PATCH 46/53] iwlwifi: fw: simplify the iwl_fw_dbg_collect_trig() Simplify the return expression. Signed-off-by: Zheng Yongjun Link: https://patch.msgid.link/20201209093734.20836-1-zhengyongjun3@huawei.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 98ad020014d9..fd60a6816150 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -3067,7 +3067,7 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, const char *fmt, ...) { - int ret, len = 0; + int len = 0; char buf[64]; if (iwl_trans_dbg_ini_valid(fwrt->trans)) @@ -3089,13 +3089,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, len = strlen(buf) + 1; } - ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, - trigger); - - if (ret) - return ret; - - return 0; + return iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, + trigger); } IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig); From 436a90d30c0ea84d01be918dc9f2390d335b761c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 14 Mar 2021 20:40:02 +0100 Subject: [PATCH 47/53] iwlwifi: use DECLARE_BITMAP macro Use DECLARE_BITMAP macro to simplify the code. Signed-off-by: Heiner Kallweit Link: https://patch.msgid.link/7dc766a7-7aca-5d24-955a-cf2a12039b31@gmail.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/img.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index f9de139561a0..e055f798a398 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -53,8 +53,8 @@ struct iwl_ucode_capabilities { u32 num_stations; u32 num_links; u32 num_beacons; - unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; - unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; + DECLARE_BITMAP(_api, NUM_IWL_UCODE_TLV_API); + DECLARE_BITMAP(_capa, NUM_IWL_UCODE_TLV_CAPA); const struct iwl_fw_cmd_version *cmd_versions; u32 n_cmd_versions; From b382523c840a032ae3a9987da9f2601977965962 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 11 Aug 2022 20:00:45 +0800 Subject: [PATCH 48/53] iwlwifi: Fix comment typo The double `only' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Link: https://patch.msgid.link/20220811120045.9422-1-wangborong@cdjrlc.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/dvm/commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h index 9eef2134392e..138b11f51d00 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h @@ -2026,7 +2026,7 @@ struct iwl_spectrum_notification { u8 channel; u8 type; /* see enum iwl_measurement_type */ u8 reserved1; - /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only + /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only * valid if applicable for measurement type requested. */ __le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */ __le32 cca_cck; /* cca fraction time in 44Mhz clock periods */ From b8b3e85ca45e483509e1e93cf8a61c5a41bee6ce Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Sun, 11 Sep 2022 17:02:41 +0800 Subject: [PATCH 49/53] iwlwifi: remove unused no_sleep_autoadjust declaration no_sleep_autoadjust has been removed since commit 84965795b290 ("iwlwifi: remove no_sleep_autoadjust"), so remove it. Signed-off-by: Gaosheng Cui Link: https://patch.msgid.link/20220911090241.3207201-3-cuigaosheng1@huawei.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/dvm/power.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.h b/drivers/net/wireless/intel/iwlwifi/dvm/power.h index f38201ce1e99..1a688d942bca 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.h @@ -23,6 +23,4 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, int iwl_power_update_mode(struct iwl_priv *priv, bool force); void iwl_power_initialize(struct iwl_priv *priv); -extern bool no_sleep_autoadjust; - #endif /* __iwl_power_setting_h__ */ From a2393f3a6908f23d21c05ba57bc1b2a6b19c06e1 Mon Sep 17 00:00:00 2001 From: Ruffalo Lavoisier Date: Mon, 19 Sep 2022 15:40:54 +0900 Subject: [PATCH 50/53] iwlwifi: api: delete repeated words - Delete the repeated word 'the' in the comment. Signed-off-by: Ruffalo Lavoisier Link: https://patch.msgid.link/20220919064055.17895-1-RuffaloLavoisier@gmail.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/tx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 557832563f89..62bd35a8f680 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -864,7 +864,7 @@ struct iwl_extended_beacon_notif { /** * enum iwl_dump_control - dump (flush) control flags - * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty + * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty * and the TFD queues are empty. */ enum iwl_dump_control { From ed2e916c890944633d6826dce267579334f63ea5 Mon Sep 17 00:00:00 2001 From: Xiu Jianfeng Date: Wed, 9 Nov 2022 11:52:13 +0800 Subject: [PATCH 51/53] wifi: iwlwifi: Fix memory leak in iwl_mvm_init() When iwl_opmode_register() fails, it does not unregster rate control, which will cause a memory leak issue, this patch fixes it. Fixes: 9f66a397c877 ("iwlwifi: mvm: rs: add ops for the new rate scaling in the FW") Signed-off-by: Xiu Jianfeng Link: https://patch.msgid.link/20221109035213.570-1-xiujianfeng@huawei.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index a2dc5c3b0596..1c05a3d8e424 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -61,8 +61,10 @@ static int __init iwl_mvm_init(void) } ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops); - if (ret) + if (ret) { pr_err("Unable to register MVM op_mode: %d\n", ret); + iwl_mvm_rate_control_unregister(); + } return ret; } From 90a0d9f339960448a3acc1437a46730f975efd6a Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 10 Jan 2023 09:48:48 +0800 Subject: [PATCH 52/53] iwlwifi: Add missing check for alloc_ordered_workqueue Add check for the return value of alloc_ordered_workqueue since it may return NULL pointer. Fixes: b481de9ca074 ("[IWLWIFI]: add iwlwifi wireless drivers") Signed-off-by: Jiasheng Jiang Link: https://patch.msgid.link/20230110014848.28226-1-jiasheng@iscas.ac.cn Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 1d619384c629..a940c23007ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1048,9 +1048,11 @@ static void iwl_bg_restart(struct work_struct *data) * *****************************************************************************/ -static void iwl_setup_deferred_work(struct iwl_priv *priv) +static int iwl_setup_deferred_work(struct iwl_priv *priv) { priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0); + if (!priv->workqueue) + return -ENOMEM; INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); @@ -1067,6 +1069,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) timer_setup(&priv->statistics_periodic, iwl_bg_statistics_periodic, 0); timer_setup(&priv->ucode_trace, iwl_bg_ucode_trace, 0); + + return 0; } void iwl_cancel_deferred_work(struct iwl_priv *priv) @@ -1461,7 +1465,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /******************** * 6. Setup services ********************/ - iwl_setup_deferred_work(priv); + if (iwl_setup_deferred_work(priv)) + goto out_uninit_drv; + iwl_setup_rx_handlers(priv); iwl_power_initialize(priv); @@ -1500,6 +1506,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, iwl_cancel_deferred_work(priv); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; +out_uninit_drv: iwl_uninit_drv(priv); out_free_eeprom_blob: kfree(priv->eeprom_blob); From e3ad987e9dc7d1e12e3f2f1e623f0e174cd0ca78 Mon Sep 17 00:00:00 2001 From: Rand Deeb Date: Wed, 13 Mar 2024 13:17:55 +0300 Subject: [PATCH 53/53] wifi: iwlwifi: dvm: fix potential overflow in rs_fill_link_cmd() The 'index' variable in the rs_fill_link_cmd() function can reach LINK_QUAL_MAX_RETRY_NUM during the execution of the inner loop. This variable is used as an index for the lq_cmd->rs_table array, which has a size of LINK_QUAL_MAX_RETRY_NUM, without proper validation. Modify the condition of the inner loop to ensure that the 'index' variable does not exceed LINK_QUAL_MAX_RETRY_NUM - 1, thereby preventing any potential overflow issues. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Rand Deeb Link: https://patch.msgid.link/20240313101755.269209-1-rand.sec96@gmail.com Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/dvm/rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index 8879e668ef0d..ed964103281e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -2899,7 +2899,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, /* Repeat initial/next rate. * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ - while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { + while (repeat_rate > 0 && index < (LINK_QUAL_MAX_RETRY_NUM - 1)) { if (is_legacy(tbl_type.lq_type)) { if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) ant_toggle_cnt++;