wifi: iwlwifi: fixes - 2026-05-31

This contains a few fixes:
 - Don't grab nic access in non-fast-resume
 - Don't send a large hcmd than transport supports
 - In AP mode, don't send tx power constraints command before activating
   the link
 - Don't do sw reset handshake on older firmwares.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQM3A3Pv7vbm9vtjWbacY7uyt+OfQUCahxB+wAKCRDacY7uyt+O
 fbPvAQDUKxERZJuf0FezGx4Z17XyibqhCPlPLrxuCOiWR5OObAD8DZ7do7sSJx/P
 r0r7rUfLW0eKkbQ/UthAhHx0jD7imgQ=
 =J9uk
 -----END PGP SIGNATURE-----

Merge tag 'iwlwifi-fixes-2026-05-31' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

wifi: iwlwifi: fixes - 2026-05-31

Miri Korenblit says:
====================
This contains a few fixes:
- Don't grab nic access in non-fast-resume
- Don't send a large hcmd than transport supports
- In AP mode, don't send tx power constraints command before activating
  the link
- Don't do sw reset handshake on older firmwares.
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-06-02 13:28:38 +02:00
commit 7752c54353
6 changed files with 68 additions and 35 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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();
}
}
}