From 0eaa1f245ac03ed0c6394159360532726f666811 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 29 May 2026 08:57:05 +0300 Subject: [PATCH 1/4] wifi: iwlwifi: mvm: don't support the reset handshake for old firmwares -77.ucode doesn't contain the fixes for this flow it seems. Don't use the firmware reset handshake even if the firmware claims support for it. Fixes: 906d4eb84408 ("iwlwifi: support firmware reset handshake") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220600 Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260529085453.9307b81d9b02.I21bba9e649f4cd0e35d3ea6cd97a03258be5832f@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index ae177477b201..384bed95835d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1416,6 +1416,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE); + /* Those firmware versions claim to support the fw_reset_handshake + * but they are buggy. + */ + if (IWL_UCODE_MAJOR(mvm->fw->ucode_ver) <= 77) + trans->conf.fw_reset_handshake = false; + trans->conf.queue_alloc_cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, From 9bf1b409afc7c4a1f0340f3975846c4f3278643a Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Fri, 29 May 2026 08:57:06 +0300 Subject: [PATCH 2/4] wifi: iwlwifi: mld: send tx power constraints before link activation TX power constraints must be sent to the firmware before link activation. If not, the firmware will use default power values. Fix this by moving the iwl_mld_send_ap_tx_power_constraint_cmd() call from iwl_mld_start_ap_ibss() to iwl_mld_assign_vif_chanctx(), before iwl_mld_activate_link() for AP interfaces. Also update the guard in the function to allow it to run before link activation for AP interfaces. Signed-off-by: Pagadala Yesu Anjaneyulu Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260529085453.06c94b01efd2.Id43bdfe5eb030061c23348779687ba71b5f58182@changeid --- drivers/net/wireless/intel/iwlwifi/mld/ap.c | 4 ---- drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 7 +++++++ drivers/net/wireless/intel/iwlwifi/mld/power.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ap.c b/drivers/net/wireless/intel/iwlwifi/mld/ap.c index 5c59acc8c4c5..6598d9333333 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ap.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ap.c @@ -9,7 +9,6 @@ #include "ap.h" #include "hcmd.h" #include "tx.h" -#include "power.h" #include "key.h" #include "phy.h" #include "iwl-utils.h" @@ -273,9 +272,6 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx; int ret; - if (vif->type == NL80211_IFTYPE_AP) - iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link); - ret = iwl_mld_update_beacon_template(mld, vif, link); if (ret) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index da6fd7471568..3c8daddc0bcb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1150,6 +1150,13 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw, if (iwl_mld_can_activate_link(mld, vif, link)) { iwl_mld_tlc_update_phy(mld, vif, link); + /* FW requires AP_TX_POWER_CONSTRAINTS_CMD before link + * activation for AP and after link activation for STA, + * for an unknown reason. + */ + if (vif->type == NL80211_IFTYPE_AP) + iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link); + ret = iwl_mld_activate_link(mld, link); if (ret) goto err; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c index 49b0d9f8f865..266fe16bb95d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c @@ -366,7 +366,7 @@ iwl_mld_send_ap_tx_power_constraint_cmd(struct iwl_mld *mld, lockdep_assert_wiphy(mld->wiphy); - if (!mld_link->active) + if (!mld_link->active && vif->type != NL80211_IFTYPE_AP) return; if (link->chanreq.oper.chan->band != NL80211_BAND_6GHZ) From e0c121d545134af886b28c4c26d91abf5dd39c17 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 29 May 2026 08:57:07 +0300 Subject: [PATCH 3/4] wifi: iwlwifi: mvm: avoid oversized UATS command copy MCC_ALLOWED_AP_TYPE_CMD exceeds the fixed copied host-command buffer and triggers warnings in the gen2 enqueue path when command 0xc05 is sent. Use IWL_HCMD_DFL_NOCOPY as it was done before the offending commit. Fixes: 078df640ef05 ("wifi: iwlwifi: mld: add support for iwl_mcc_allowed_ap_type_cmd v2") Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260529085453.9af349ab459b.I348df3980764c15efce0099a35fe8a88fb2a6ee2@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 28 ++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index f05df3a3300e..6e507d6dcdd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2025 Intel Corporation + * Copyright (C) 2012-2014, 2018-2026 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -459,9 +459,14 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm, static void iwl_mvm_uats_init(struct iwl_mvm *mvm) { + struct iwl_mcc_allowed_ap_type_cmd_v1 *cmd __free(kfree) = NULL; int cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP, MCC_ALLOWED_AP_TYPE_CMD); - struct iwl_mcc_allowed_ap_type_cmd_v1 cmd = {}; + struct iwl_host_cmd hcmd = { + .id = cmd_id, + .len[0] = sizeof(*cmd), + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; u8 cmd_ver; int ret; @@ -485,14 +490,25 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm) if (!mvm->fwrt.ap_type_cmd_valid) return; - BUILD_BUG_ON(sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map) != - sizeof(cmd.mcc_to_ap_type_map)); + /* Since we free the command immediately after iwl_mvm_send_cmd, we + * must send this command in SYNC mode. + */ + lockdep_assert_held(&mvm->mutex); - memcpy(cmd.mcc_to_ap_type_map, + cmd = kzalloc_obj(*cmd); + if (!cmd) + return; + + BUILD_BUG_ON(sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map) != + sizeof(cmd->mcc_to_ap_type_map)); + + memcpy(cmd->mcc_to_ap_type_map, mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map, sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map)); - ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); + hcmd.data[0] = cmd; + + ret = iwl_mvm_send_cmd(mvm, &hcmd); if (ret < 0) IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n", ret); From 093305d801fae6ff9b8bb531fd78b579794c4f80 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 31 May 2026 13:30:19 +0300 Subject: [PATCH 4/4] wifi: iwlwifi: pcie: simplify the resume flow if fast resume is not used In most distributions, NetworkManager shuts the device down before entering system suspend, so fast suspend is typically not used. On older devices, resume currently tries to grab NIC access to infer whether the device was powered off while suspended. That probe is only meaningful for the fast-suspend path where the device is expected to remain alive. Unfortunately, for unclear reasons, grabbing NIC access was harmful as reported in the bugzilla ticket below. Workaround this issue by simply not grabbing NIC access if fast suspend is not used. Cc: stable@vger.kernel.org Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221501 Assisted-by: GitHub Copilot:gpt-5.3-codex Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260531133005.e2ed9e0cd44f.If283625983a843933e0c01561a421daff184e9e9@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index dc99e7ac4726..eb3c5a6dd088 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1225,33 +1225,41 @@ static int _iwl_pci_resume(struct device *device, bool restore) if (!trans->op_mode) return 0; - /* - * Scratch value was altered, this means the device was powered off, we - * need to reset it completely. - * Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan, - * but not bits [15:8]. So if we have bits set in lower word, assume - * the device is alive. - * Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer - * have access to the device and consider it powered off. - * For older devices, just try silently to grab the NIC. - */ - if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); - - if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) || - scratch == ~0U) - device_was_powered_off = true; - } else { + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { /* - * bh are re-enabled by iwl_trans_pcie_release_nic_access, - * so re-enable them if _iwl_trans_pcie_grab_nic_access fails. + * Scratch value was altered, this means the device was powered + * off, we need to reset it completely. + * Note: MAC (bits 0:7) will be cleared upon suspend even with + * wowlan, but not bits [15:8]. So if we have bits set in lower + * word, assume the device is alive. + * Alternatively, if the scratch value is 0xFFFFFFFF, then we + * no longer have access to the device and consider it powered + * off. + * For older devices, just try silently to grab the NIC. */ - local_bh_disable(); - if (_iwl_trans_pcie_grab_nic_access(trans, true)) { - iwl_trans_pcie_release_nic_access(trans); + if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { + u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); + + if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) || + scratch == ~0U) { + IWL_DEBUG_WOWLAN(trans, + "Scratch 0x%08x indicates device was powered off\n", + scratch); + device_was_powered_off = true; + } } else { - device_was_powered_off = true; - local_bh_enable(); + /* + * bh are re-enabled by iwl_trans_pcie_release_nic_access, + * so re-enable them if _iwl_trans_pcie_grab_nic_access + * fails. + */ + local_bh_disable(); + if (_iwl_trans_pcie_grab_nic_access(trans, true)) { + iwl_trans_pcie_release_nic_access(trans); + } else { + device_was_powered_off = true; + local_bh_enable(); + } } }