wifi: iwlwifi: updates - 2026-07-23

This comtains the usual features, fixes and cleanups. Notably:
 - Small fixes of bugs reported by LLMs
 - LARI command version 14 and 15
 - MCC command version 10
 - Support for core 107
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQM3A3Pv7vbm9vtjWbacY7uyt+OfQUCamJQLQAKCRDacY7uyt+O
 fc/cAQCHQ7F7RCO8iB5u+kFc71+0UpDpK8bYVN1lwvL26/7WkQD/YcRZ9L01EOJl
 DZQAP0WwHoHzK6DuPQoxnr88iiUYnAs=
 =PyTI
 -----END PGP SIGNATURE-----

Merge tag 'iwlwifi-next-2026-07-23' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

Miri Korenblit says:
====================
wifi: iwlwifi: updates - 2026-07-23

This comtains the usual features, fixes and cleanups. Notably:
- Small fixes of bugs reported by LLMs
- LARI command version 14 and 15
- MCC command version 10
- Support for core 107
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-07-28 15:59:30 +02:00
commit 905b418df8
43 changed files with 535 additions and 181 deletions

View File

@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
#define IWL_BZ_UCODE_CORE_MAX 106
#define IWL_BZ_UCODE_CORE_MAX 107
/* Lowest firmware core release supported */
#define IWL_BZ_UCODE_CORE_MIN 102

View File

@ -9,7 +9,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
#define IWL_DR_UCODE_CORE_MAX 106
#define IWL_DR_UCODE_CORE_MAX 107
/* Lowest firmware core release supported */
#define IWL_DR_UCODE_CORE_MIN 102

View File

@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
#define IWL_SC_UCODE_CORE_MAX 106
#define IWL_SC_UCODE_CORE_MAX 107
/* Lowest firmware core release supported */
#define IWL_SC_UCODE_CORE_MIN 102

View File

@ -1511,10 +1511,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
priv->workqueue = NULL;
out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom_blob:
kfree(priv->eeprom_blob);
out_free_eeprom:
kfree(priv->nvm_data);
out_free_eeprom_blob:
kfree(priv->eeprom_blob);
out_leave_trans:
iwl_trans_op_mode_leave(priv->trans);
out_free_hw:

View File

@ -604,8 +604,10 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
}
ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
if (ret)
if (ret) {
iwlagn_dealloc_agg_txq(priv, txq_id);
return ret;
}
spin_lock_bh(&priv->sta_lock);
tid_data = &priv->tid_data[sta_id][tid];

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2019-2025 Intel Corporation
* Copyright (C) 2019-2026 Intel Corporation
*/
#include <linux/uuid.h>
#include "iwl-drv.h"
@ -181,6 +181,7 @@ static int iwl_acpi_load_dsm_values(struct iwl_fw_runtime *fwrt)
fwrt->dsm_revision = ACPI_DSM_REV;
fwrt->dsm_source = BIOS_SOURCE_ACPI;
fwrt->dsm_values[DSM_FUNC_QUERY] = (u32)query_func_val;
IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
(u32)query_func_val);
@ -246,7 +247,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
BUILD_BUG_ON(ARRAY_SIZE(fwrt->dsm_values) != DSM_FUNC_NUM_FUNCS);
BUILD_BUG_ON(BITS_PER_TYPE(fwrt->dsm_funcs_valid) < DSM_FUNC_NUM_FUNCS);
if (WARN_ON(func >= ARRAY_SIZE(fwrt->dsm_values) || !func))
if (WARN_ON(func >= ARRAY_SIZE(fwrt->dsm_values)))
return -EINVAL;
if (!(fwrt->dsm_funcs_valid & BIT(func))) {
@ -1193,6 +1194,8 @@ int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
*value = wifi_pkg->package.elements[1].integer.value &
IWL_ACPI_WBEM_REV0_MASK;
fwrt->wbem_source = BIOS_SOURCE_ACPI;
fwrt->wbem_revision = tbl_rev;
IWL_DEBUG_RADIO(fwrt, "Loaded WBEM config from ACPI\n");
ret = 0;
out_free:

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2023, 2025 Intel Corporation
* Copyright (C) 2018-2023, 2025-2026 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@ -111,9 +111,6 @@
#define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \
ACPI_PPAG_NUM_BANDS_V3) + 2)
#define IWL_SAR_ENABLE_MSK BIT(0)
#define IWL_REDUCE_POWER_FLAGS_POS 1
/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */
#define UEFI_WIFI_GUID_UNLOCKED 0

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
*/
@ -46,6 +46,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
*/
MCC_ALLOWED_AP_TYPE_CMD = 0x5,
/**
* @LARI_CONFIG_EXTENSION: &struct iwl_lari_config_extension_cmd
*/
LARI_CONFIG_EXTENSION = 0x8,
/**
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
*/
@ -433,7 +438,10 @@ struct iwl_mcc_chub_notif {
__le16 mcc;
u8 source_id;
u8 reserved1;
} __packed; /* LAR_MCC_NOTIFY_S */
} __packed;
/* LAR_MCC_NOTIFY_S_VER_1
* LAR_MCC_NOTIFY_S_VER_2
*/
enum iwl_mcc_update_status {
MCC_RESP_NEW_CHAN_PROFILE,
@ -541,6 +549,27 @@ struct iwl_bios_config_hdr {
u8 reserved[2];
} __packed; /* BIOS_CONFIG_HDR_API_S_VER_1 */
/**
* struct iwl_lari_config_extension_cmd - extend LARI configuration
*
* LARI_CONFIG_CHANGE's version must remain stable for frozen firmware.
* Because the driver might not know this version but still load that
* frozen FW and then send some default old version of LARI, causing the FW to
* assert about the bad size of it. To handle this, we do the following:
* 1. For newer firmware: increase the LARI_CONFIG_CHANGE version to support the
* new firmware API with extra UHB bits.
* 2. For frozen firmware: add a special alternative API that doesn't require
* modifying the frozen LARI_CONFIG_CHANGE's version.
* @dsm_table_hdr: BIOS DSM table source and revision
* @oem_uhb_allow_extension_bitmap: extension bitmap for OEM UHB config
* @reserved: reserved
*/
struct iwl_lari_config_extension_cmd {
struct iwl_bios_config_hdr dsm_table_hdr;
__le32 oem_uhb_allow_extension_bitmap;
__le32 reserved[10];
} __packed; /* LARI_CONFIG_EXTENSION_CMD_API_S_VER_1 */
/**
* struct bios_value_u32 - BIOS configuration.
* @hdr: bios config header
@ -689,6 +718,14 @@ struct iwl_lari_config_change_cmd_v8 {
* get the data from the BIOS.
* @oem_unii9_enable: UNII-9 enablement as read from the BIOS
* @bios_hdr: bios config header
* @oem_uhb_allow_extension_bitmap: DSM Function 4 data as an extension of UHB
* enabled MCC sets
* @bios_wcpe_hdr: puncturing config header
* @wcpe_bitmap: bitmap of puncturing enablement per MCC
* @bios_wbem_hdr: 320 MHz per-MCC WBEM config header
* @reserved: reserved
* @oem_supported_dsm_bitmap: DSM function 0 bitmap describing supported
* DSM function indices
*/
struct iwl_lari_config_change_cmd {
__le32 config_bitmap;
@ -706,9 +743,19 @@ struct iwl_lari_config_change_cmd {
__le32 oem_unii9_enable;
/* since version 13 */
struct iwl_bios_config_hdr bios_hdr;
/* All the below are since version 14 */
__le32 oem_uhb_allow_extension_bitmap;
struct iwl_bios_config_hdr bios_wcpe_hdr;
__le32 wcpe_bitmap;
struct iwl_bios_config_hdr bios_wbem_hdr;
__le32 reserved[10];
/* since version 15 */
__le32 oem_supported_dsm_bitmap;
} __packed;
/* LARI_CHANGE_CONF_CMD_S_VER_12
* LARI_CHANGE_CONF_CMD_S_VER_13
* LARI_CHANGE_CONF_CMD_S_VER_14
* LARI_CHANGE_CONF_CMD_S_VER_15
*/
/* Activate UNII-1 (5.2GHz) for World Wide */

View File

@ -369,7 +369,7 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
{
struct iwl_pc_data *pc_data;
u8 count;
u32 count;
if (!iwl_trans_device_enabled(fwrt->trans)) {
IWL_ERR(fwrt,

View File

@ -352,7 +352,7 @@ struct iwl_fw_ini_error_dump_register {
* struct iwl_fw_ini_dump_cfg_name - configuration name
* @image_type: image type the configuration is related to
* @cfg_name_len: length of the configuration name
* @cfg_name: name of the configuraiton
* @cfg_name: name of the configuration
*/
struct iwl_fw_ini_dump_cfg_name {
__le32 image_type;

View File

@ -448,8 +448,9 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT: external FSEQ image support
* @IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT: FW reset handshake is needed
* during assert handling even if the dump isn't split
* @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of
* handling raw DSM table data.
* @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware can handle raw DSM
* table data. For LARI_CONFIG_CHANGE command version 13 and above, this
* capability is obsolete since raw DSM values are accepted by default.
* @IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT: Supports NAN synchronization
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used

View File

@ -205,6 +205,12 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
tlv_len);
if (tlv_len < sizeof(*tlv_sku_id)) {
IWL_ERR(trans, "invalid PNVM SKU TLV len: %u\n",
tlv_len);
return -EINVAL;
}
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
le32_to_cpu(tlv_sku_id->data[0]),
le32_to_cpu(tlv_sku_id->data[1]),

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2023-2025 Intel Corporation
* Copyright (C) 2023-2026 Intel Corporation
*/
#ifndef __fw_regulatory_h__
@ -30,6 +30,7 @@
#define BIOS_GEO_MIN_PROFILE_NUM 3
#define IWL_SAR_ENABLE_MSK BIT(0)
#define IWL_REDUCE_POWER_FLAGS_POS 1
/* PPAG gain value bounds in 1/8 dBm */
#define IWL_PPAG_MIN_LB -16

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2025 Intel Corporation
* Copyright (C) 2018-2026 Intel Corporation
*/
#ifndef __iwl_fw_runtime_h__
#define __iwl_fw_runtime_h__
@ -144,6 +144,11 @@ struct iwl_txf_iter_data {
* @tpc_enabled: TPC enabled
* @dsm_source: one of &enum bios_source. UEFI, ACPI or NONE
* @dsm_revision: the revision of the DSM table
* @wbem_source: one of &enum bios_source for the WBEM table
* @wbem_revision: the revision of the WBEM table
* @puncturing_source: one of &enum bios_source for the puncturing table
* @puncturing_revision: the revision of the puncturing table
* @bios_puncturing: per-country puncturing enablement bitmap from BIOS
*/
struct iwl_fw_runtime {
struct iwl_trans *trans;
@ -226,6 +231,12 @@ struct iwl_fw_runtime {
u32 dsm_funcs_valid;
u32 dsm_values[DSM_FUNC_NUM_FUNCS];
#endif
enum bios_source wbem_source;
u8 wbem_revision;
enum bios_source puncturing_source;
u8 puncturing_revision;
u32 bios_puncturing;
};
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright(c) 2021-2025 Intel Corporation
* Copyright(c) 2021-2026 Intel Corporation
*/
#include "iwl-drv.h"
@ -248,6 +248,12 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
tlv_len);
if (tlv_len < sizeof(*tlv_sku_id)) {
IWL_ERR(trans, "invalid PNVM SKU TLV len: %u\n",
tlv_len);
return -EINVAL;
}
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
le32_to_cpu(tlv_sku_id->data[0]),
le32_to_cpu(tlv_sku_id->data[1]),
@ -884,6 +890,8 @@ int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value)
goto out;
}
*value = data->wbem_320mhz_per_mcc & IWL_UEFI_WBEM_REV0_MASK;
fwrt->wbem_source = BIOS_SOURCE_UEFI;
fwrt->wbem_revision = data->revision;
IWL_DEBUG_RADIO(fwrt, "Loaded WBEM config from UEFI\n");
out:
kfree(data);
@ -919,7 +927,7 @@ static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt)
*/
fwrt->dsm_funcs_valid |= BIT(DSM_FUNC_QUERY);
for (int func = 1; func < ARRAY_SIZE(fwrt->dsm_values); func++) {
for (int func = 0; func < ARRAY_SIZE(fwrt->dsm_values); func++) {
if (!(fwrt->dsm_funcs_valid & BIT(func))) {
IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
func, fwrt->dsm_funcs_valid);
@ -970,29 +978,29 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_var_puncturing_data *data;
/* default value is not enabled if there is any issue in reading
* uefi variable or revision is not supported
*/
int puncturing = 0;
int ret = 0;
data = iwl_uefi_get_verified_variable(fwrt->trans,
IWL_UEFI_PUNCTURING_NAME,
"UefiCnvWlanPuncturing",
sizeof(*data), NULL);
if (IS_ERR(data))
return puncturing;
return -EINVAL;
if (data->revision != IWL_UEFI_PUNCTURING_REVISION) {
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PUNCTURING rev:%d\n",
data->revision);
ret = -EINVAL;
} else {
puncturing = data->puncturing & IWL_UEFI_PUNCTURING_REV0_MASK;
fwrt->puncturing_source = BIOS_SOURCE_UEFI;
fwrt->puncturing_revision = data->revision;
fwrt->bios_puncturing = data->puncturing;
IWL_DEBUG_RADIO(fwrt, "Loaded puncturing bits from UEFI: %d\n",
puncturing);
fwrt->bios_puncturing);
}
kfree(data);
return puncturing;
return ret;
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_puncturing);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright(c) 2021-2025 Intel Corporation
* Copyright(c) 2021-2026 Intel Corporation
*/
#ifndef __iwl_fw_uefi__
#define __iwl_fw_uefi__
@ -275,8 +275,6 @@ enum iwl_uefi_cnv_puncturing_flags {
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK = BIT(1),
};
#define IWL_UEFI_PUNCTURING_REV0_MASK (IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK | \
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK)
/**
* struct uefi_cnv_var_puncturing_data - controlling channel
* puncturing for few countries.

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2018-2025 Intel Corporation
* Copyright (C) 2018-2026 Intel Corporation
*/
#include <linux/firmware.h>
#include "iwl-drv.h"
@ -611,6 +611,9 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH))
return 0;
if (!fw_mon_cfg->req_size)
return -EIO;
num_frags = le32_to_cpu(fw_mon_cfg->max_frags_num);
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
@ -621,6 +624,9 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
return -EIO;
}
if (!num_frags)
return -EIO;
remain_pages = DIV_ROUND_UP(le32_to_cpu(fw_mon_cfg->req_size),
PAGE_SIZE);
num_frags = min_t(u32, num_frags, BUF_ALLOC_MAX_NUM_FRAGS);

View File

@ -225,6 +225,18 @@ enum iwl_reg_capa_flags_v5 {
REG_CAPA_V5_11BN_DISABLED = BIT(17),
}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4, 5 */
/**
* enum iwl_reg_capa_flags_v6 - global capability flags,
* applicable from MCC response version 10 onwards.
* Response v6 includes all members of iwl_reg_capa_flags_v5; only v6-specific
* additions are listed here.
* @REG_CAPA_V6_EHT_PUNCTURING_ENABLED: EHT puncturing is enabled for this
* regulatory domain.
*/
enum iwl_reg_capa_flags_v6 {
REG_CAPA_V6_EHT_PUNCTURING_ENABLED = BIT(18),
}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_6 */
/*
* API v2 for reg_capa_flags is relevant from version 6 and onwards of the
* MCC update command response.
@ -236,6 +248,11 @@ enum iwl_reg_capa_flags_v5 {
*/
#define REG_CAPA_V4_RESP_VER 8
/* API v6 for reg_capa_flags is relevant from version 10 and onwards of the
* MCC update command response.
*/
#define REG_CAPA_V6_RESP_VER 10
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u32 flags)
{
@ -697,7 +714,8 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
.mac.mac_cap = {
[0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
IEEE80211_UHR_MAC_CAP0_DPS_SUPP,
[1] = IEEE80211_UHR_MAC_CAP1_DUO_SUPP,
[1] = IEEE80211_UHR_MAC_CAP1_DUO_SUPP |
IEEE80211_UHR_MAC_CAP1_DBE_SUPP,
},
},
},
@ -1687,6 +1705,13 @@ static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
{
struct iwl_reg_capa reg_capa = {};
if (resp_ver >= REG_CAPA_V6_RESP_VER) {
if (flags & REG_CAPA_V6_EHT_PUNCTURING_ENABLED)
reg_capa.puncturing_status = IWL_PUNCTURING_STATUS_ENABLED;
else
reg_capa.puncturing_status = IWL_PUNCTURING_STATUS_DISABLED;
}
if (resp_ver >= REG_CAPA_V4_RESP_VER) {
reg_capa.allow_40mhz = true;
reg_capa.allow_80mhz = flags & REG_CAPA_V5_80MHZ_ALLOWED;
@ -1713,7 +1738,8 @@ static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info, u32 cap, u8 resp_ver)
u16 geo_info, u32 cap, u8 resp_ver,
enum iwl_puncturing_status *puncturing_status)
{
const struct iwl_rf_cfg *cfg = trans->cfg;
struct device *dev = trans->dev;
@ -1776,6 +1802,9 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
/* parse regulatory capability flags */
reg_capa = iwl_get_reg_capa(cap, resp_ver);
if (puncturing_status)
*puncturing_status = reg_capa.puncturing_status;
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
enum nl80211_band band =
iwl_nl80211_band_from_channel_idx(ch_idx);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2015, 2018-2025 Intel Corporation
* Copyright (C) 2005-2015, 2018-2026 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_nvm_parse_h__
@ -21,6 +21,19 @@ enum iwl_nvm_sbands_flags {
IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1),
};
/**
* enum iwl_puncturing_status - EHT puncturing status from MCC capabilities
* @IWL_PUNCTURING_STATUS_UNKNOWN: puncturing status is not provided by FW
* or is not initialized yet
* @IWL_PUNCTURING_STATUS_ENABLED: puncturing is enabled for the current MCC
* @IWL_PUNCTURING_STATUS_DISABLED: puncturing is disabled for the current MCC
*/
enum iwl_puncturing_status {
IWL_PUNCTURING_STATUS_UNKNOWN,
IWL_PUNCTURING_STATUS_ENABLED,
IWL_PUNCTURING_STATUS_DISABLED,
};
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
@ -36,6 +49,8 @@ enum iwl_nvm_sbands_flags {
* @disable_11ax: 11ax is forbidden for this regulatory domain.
* @disable_11be: 11be is forbidden for this regulatory domain.
* @disable_11bn: UHR/11bn is not allowed for this regulatory domain
* @puncturing_status: EHT puncturing status for the current MCC.
* See &enum iwl_puncturing_status.
*/
struct iwl_reg_capa {
bool allow_40mhz;
@ -45,6 +60,7 @@ struct iwl_reg_capa {
bool disable_11ax;
bool disable_11be;
bool disable_11bn;
enum iwl_puncturing_status puncturing_status;
};
/**
@ -131,11 +147,13 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
* @geo_info: geo info value
* @cap: capability
* @resp_ver: FW response version
* @puncturing_status: FW puncturing status for current MCC, when available
*/
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info, u32 cap, u8 resp_ver);
u16 geo_info, u32 cap, u8 resp_ver,
enum iwl_puncturing_status *puncturing_status);
/**
* struct iwl_nvm_section - describes an NVM section in memory.

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2021-2024 Intel Corporation
* Copyright (C) 2026 Intel Corporation
*/
#include <linux/etherdevice.h>
@ -457,7 +458,7 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev,
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF];
q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr, q_sz);
ret = iwl_mei_write_cyclic_buf(cldev, notif_q, q_head, hdr, q_sz);
if (ret < 0)
return ret;
@ -1040,11 +1041,14 @@ static void iwl_mei_read_from_q(const u8 *q_head, u32 q_sz,
u32 rd = *_rd;
if (rd + len <= q_sz) {
memcpy(buf, q_head + rd, len);
if (buf)
memcpy(buf, q_head + rd, len);
rd += len;
} else {
memcpy(buf, q_head + rd, q_sz - rd);
memcpy(buf + q_sz - rd, q_head, len - (q_sz - rd));
if (buf) {
memcpy(buf, q_head + rd, q_sz - rd);
memcpy(buf + q_sz - rd, q_head, len - (q_sz - rd));
}
rd = len - (q_sz - rd);
}
@ -1085,24 +1089,29 @@ static void iwl_mei_handle_sap_data(struct mei_cl_device *cldev,
break;
}
valid_rx_sz -= len;
if (len < sizeof(*ethhdr)) {
dev_err(&cldev->dev,
"Data len is smaller than an ethernet header? len = %d\n",
len);
iwl_mei_read_from_q(q_head, q_sz, &rd, wr, NULL, len);
continue;
}
valid_rx_sz -= len;
if (le16_to_cpu(hdr.type) != SAP_MSG_DATA_PACKET) {
dev_err(&cldev->dev, "Unsupported Rx data: type %d, len %d\n",
le16_to_cpu(hdr.type), len);
iwl_mei_read_from_q(q_head, q_sz, &rd, wr, NULL, len);
continue;
}
/* We need enough room for the WiFi header + SNAP + IV */
skb = netdev_alloc_skb(netdev, len + QOS_HDR_IV_SNAP_LEN);
if (!skb)
if (!skb) {
iwl_mei_read_from_q(q_head, q_sz, &rd, wr, NULL, len);
continue;
}
skb_reserve(skb, QOS_HDR_IV_SNAP_LEN);
ethhdr = skb_push(skb, sizeof(*ethhdr));
@ -1147,6 +1156,11 @@ static void iwl_mei_handle_sap_rx_cmd(struct mei_cl_device *cldev,
iwl_mei_read_from_q(q_head, q_sz, &rd, wr, hdr, sizeof(*hdr));
valid_rx_sz -= sizeof(*hdr);
len = le16_to_cpu(hdr->len);
if (len + sizeof(*hdr) > PAGE_SIZE) {
dev_err(&cldev->dev,
"SAP message is too big: %u\n", len);
break;
}
if (valid_rx_sz < len)
break;

View File

@ -200,11 +200,11 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
struct iwl_mld_baid_data *baid_data;
struct iwl_mld_reorder_buffer *buffer;
struct iwl_mld_reorder_buf_entry *entries;
struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
struct iwl_mld_link_sta *mld_link_sta;
u32 reorder = le32_to_cpu(desc->reorder_data);
bool amsdu, last_subframe, is_old_sn, is_dup;
u8 tid = ieee80211_get_tid(hdr);
struct iwl_mld_sta *mld_sta;
u8 baid;
u16 nssn, sn;
u32 sta_mask = 0;
@ -228,10 +228,13 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
return IWL_MLD_PASS_SKB;
/* no sta yet */
if (WARN_ONCE(!sta,
"Got valid BAID without a valid station assigned\n"))
if (IWL_FW_CHECK(mld, !sta,
"Got valid BAID without a valid station assigned - %d\n",
baid))
return IWL_MLD_PASS_SKB;
mld_sta = iwl_mld_sta_from_mac80211(sta);
/* not a data packet */
if (!ieee80211_is_data_qos(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1))

View File

@ -59,6 +59,30 @@ struct iwl_mld_suspend_key_iter_data {
__le32 bigtk_cipher;
};
struct iwl_mld_wake_pkt_iter_data {
bool multicast;
u32 ivlen;
u32 icvlen;
};
static void
iwl_mld_wake_pkt_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key, void *_data)
{
struct iwl_mld_wake_pkt_iter_data *data = _data;
bool is_group_key = !sta;
/* ignore anything that is not a PTK / GTK */
if (key->keyidx > 3)
return;
if (is_group_key != data->multicast)
return;
data->ivlen = key->iv_len;
data->icvlen = key->icv_len;
}
struct iwl_mld_mcast_key_data {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 len;
@ -573,18 +597,42 @@ iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5,
}
}
static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld,
u32 len,
u32 expected_len,
u8 num_mlo_keys,
static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, u32 len,
const void *notif_data,
int version)
{
u32 len_with_mlo_keys;
u32 expected_len;
u8 num_mlo_keys;
if (IWL_FW_CHECK(mld, len < expected_len,
"Invalid wowlan_info_notif v%d (expected=%u got=%u)\n",
version, expected_len, len))
/* Extract num_mlo_keys from the void pointer based on version */
if (version == 5) {
const struct iwl_wowlan_info_notif_v5 *notif_v5 = notif_data;
expected_len = sizeof(*notif_v5);
if (IWL_FW_CHECK(mld, len < expected_len,
"Invalid wowlan_info_notif v5 (expected=%u got=%u)\n",
expected_len, len))
return false;
num_mlo_keys = notif_v5->num_mlo_link_keys;
} else if (version == 6) {
const struct iwl_wowlan_info_notif *notif = notif_data;
expected_len = sizeof(*notif);
if (IWL_FW_CHECK(mld, len < expected_len,
"Invalid wowlan_info_notif v6 (expected=%u got=%u)\n",
expected_len, len))
return false;
num_mlo_keys = notif->num_mlo_link_keys;
} else {
IWL_WARN(mld, "Unsupported wowlan_info_notif version %d\n",
version);
return false;
}
len_with_mlo_keys = expected_len +
(num_mlo_keys * sizeof(struct iwl_wowlan_mlo_gtk));
@ -616,16 +664,14 @@ iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
if (wowlan_info_ver == 5) {
/* v5 format - validate before conversion */
const struct iwl_wowlan_info_notif_v5 *notif_v5 = (void *)pkt->data;
const struct iwl_wowlan_info_notif_v5 *_notif =
(void *)pkt->data;
if (!iwl_mld_validate_wowlan_notif_size(mld, len,
sizeof(*notif_v5),
notif_v5->num_mlo_link_keys,
5))
if (!iwl_mld_validate_wowlan_notif_size(mld, len, _notif, 5))
return true;
converted_notif = kzalloc_flex(*converted_notif, mlo_gtks,
notif_v5->num_mlo_link_keys,
_notif->num_mlo_link_keys,
GFP_ATOMIC);
if (!converted_notif) {
IWL_ERR(mld,
@ -633,15 +679,12 @@ iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
return true;
}
iwl_mld_convert_wowlan_notif_v5(notif_v5,
converted_notif);
iwl_mld_convert_wowlan_notif_v5(_notif, converted_notif);
notif = converted_notif;
} else if (wowlan_info_ver == 6) {
notif = (void *)pkt->data;
if (!iwl_mld_validate_wowlan_notif_size(mld, len,
sizeof(*notif),
notif->num_mlo_link_keys,
6))
if (!iwl_mld_validate_wowlan_notif_size(mld, len, notif, 6))
return true;
} else {
/* smaller versions are not supported */
@ -686,7 +729,7 @@ iwl_mld_handle_wake_pkt_notif(struct iwl_mld *mld,
{
const struct iwl_wowlan_wake_pkt_notif *notif = (void *)pkt->data;
u32 actual_size, len = iwl_rx_packet_payload_len(pkt);
u32 expected_size = le32_to_cpu(notif->wake_packet_length);
u32 expected_size;
if (IWL_FW_CHECK(mld, len < sizeof(*notif),
"Invalid WoWLAN wake packet notification (expected size=%zu got=%u)\n",
@ -699,6 +742,7 @@ iwl_mld_handle_wake_pkt_notif(struct iwl_mld *mld,
wowlan_status->wakeup_reasons))
return true;
expected_size = le32_to_cpu(notif->wake_packet_length);
actual_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif,
wake_packet);
@ -723,11 +767,17 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
struct cfg80211_wowlan_wakeup *wakeup,
struct sk_buff **_pkt)
{
int pkt_bufsize = wowlan_status->wake_packet_bufsize;
int expected_pktlen = wowlan_status->wake_packet_length;
u32 pkt_bufsize = wowlan_status->wake_packet_bufsize;
u32 expected_pktlen = wowlan_status->wake_packet_length;
const u8 *pktdata = wowlan_status->wake_packet;
const struct ieee80211_hdr *hdr = (const void *)pktdata;
int truncated = expected_pktlen - pkt_bufsize;
u32 truncated;
if (IWL_FW_CHECK(mld, pkt_bufsize < sizeof(*hdr),
"pkt_bufsize is too short: %u\n", pkt_bufsize))
return;
truncated = expected_pktlen - pkt_bufsize;
if (ieee80211_is_data(hdr->frame_control)) {
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
@ -738,9 +788,18 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
if (!pkt)
return;
skb_put_data(pkt, pktdata, hdrlen);
pktdata += hdrlen;
pkt_bufsize -= hdrlen;
if (ieee80211_has_protected(hdr->frame_control)) {
struct iwl_mld_wake_pkt_iter_data iter_data = {
.multicast =
is_multicast_ether_addr(hdr->addr1),
};
ieee80211_iter_keys(mld->hw, vif,
iwl_mld_wake_pkt_key_iter,
&iter_data);
ivlen = iter_data.ivlen;
icvlen += iter_data.icvlen;
}
/* if truncated, FCS/ICV is (partially) gone */
if (truncated >= icvlen) {
@ -751,6 +810,13 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
truncated = 0;
}
if (IWL_FW_CHECK(mld, pkt_bufsize <= hdrlen + ivlen + icvlen,
"pkt_bufsize is too small %u\n", pkt_bufsize))
return;
skb_put_data(pkt, pktdata, hdrlen);
pktdata += hdrlen;
pkt_bufsize -= hdrlen;
pkt_bufsize -= ivlen + icvlen;
pktdata += ivlen;
@ -772,6 +838,11 @@ iwl_mld_set_wake_packet(struct iwl_mld *mld,
fcslen -= truncated;
truncated = 0;
}
if (IWL_FW_CHECK(mld, pkt_bufsize <= fcslen,
"pkt_bufsize is too small %u\n", pkt_bufsize))
return;
pkt_bufsize -= fcslen;
wakeup->packet = wowlan_status->wake_packet;
wakeup->packet_present_len = pkt_bufsize;
@ -1449,8 +1520,16 @@ static bool iwl_mld_handle_d3_notif(struct iwl_notif_wait_data *notif_wait,
}
case WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION): {
struct iwl_d3_end_notif *notif = (void *)pkt->data;
u32 len = iwl_rx_packet_payload_len(pkt);
if (IWL_FW_CHECK(mld, len < sizeof(*notif),
"Invalid D3_END notification (expected=%zu got=%u)\n",
sizeof(*notif), len)) {
resume_data->notif_handling_err = true;
} else {
resume_data->d3_end_flags = le32_to_cpu(notif->flags);
}
resume_data->d3_end_flags = le32_to_cpu(notif->flags);
resume_data->notifs_received |= IWL_D3_NOTIF_D3_END_NOTIF;
break;
}
@ -2140,6 +2219,9 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
ret = iwl_mld_wait_d3_notif(mld, &resume_data, true);
if (ret) {
IWL_ERR(mld, "Couldn't get the d3 notifs %d\n", ret);
if (bss_vif->cfg.assoc)
ieee80211_resume_disconnect(bss_vif);
goto err;
}

View File

@ -459,3 +459,24 @@ void iwl_mld_ftm_restart_cleanup(struct iwl_mld *mld)
mld->ftm_initiator.req, GFP_KERNEL);
iwl_mld_ftm_reset(mld);
}
void iwl_mld_ftm_abort(struct iwl_mld *mld, struct cfg80211_pmsr_request *req)
{
struct iwl_tof_range_abort_cmd cmd = {
.request_id = req->cookie,
};
lockdep_assert_wiphy(mld->wiphy);
if (req != mld->ftm_initiator.req)
return;
if (iwl_mld_send_cmd_pdu(mld, WIDE_ID(LOCATION_GROUP,
TOF_RANGE_ABORT_CMD),
&cmd))
IWL_ERR(mld, "failed to abort FTM process\n");
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_FTM_REQ,
mld->ftm_initiator.req->cookie);
iwl_mld_ftm_reset(mld);
}

View File

@ -25,5 +25,6 @@ int iwl_mld_ftm_start(struct iwl_mld *mld, struct ieee80211_vif *vif,
void iwl_mld_handle_ftm_resp_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);
void iwl_mld_ftm_restart_cleanup(struct iwl_mld *mld);
void iwl_mld_ftm_abort(struct iwl_mld *mld, struct cfg80211_pmsr_request *req);
#endif /* __iwl_mld_ftm_initiator_h__ */

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2024-2025 Intel Corporation
* Copyright (C) 2024-2026 Intel Corporation
*/
#ifndef __iwl_mld_hcmd_h__
#define __iwl_mld_hcmd_h__
@ -42,7 +42,12 @@ __iwl_mld_send_cmd_with_flags_pdu(struct iwl_mld *mld, u32 id,
#define _iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len, \
ignored...) \
__iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len)
({ \
BUILD_BUG_ON(__builtin_constant_p(len) && \
(u16)(len) > IWL_MAX_CMD_PAYLOAD_SIZE); \
__iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, \
data, len); \
})
#define iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, len...) \
_iwl_mld_send_cmd_with_flags_pdu(mld, id, flags, data, ##len, \
sizeof(*(data)))

View File

@ -543,8 +543,7 @@ iwl_mld_mac80211_tx(struct ieee80211_hw *hw,
iwl_mld_tx_skb(mld, skb, NULL);
}
static void
iwl_mld_restart_cleanup(struct iwl_mld *mld)
void iwl_mld_restart_cleanup(struct iwl_mld *mld)
{
iwl_cleanup_mld(mld);
@ -1281,11 +1280,13 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mld_tlc_update_phy(mld, vif, link);
/* in the non-MLO case, remove/re-add the link to clean up FW state.
* In MLO, it'll be done in drv_change_vif_link
* In MLO, it'll be done in drv_change_vif_link.
* Do not do so during restart or in case the device is dead.
*/
if (!ieee80211_vif_is_mld(vif) && !mld_vif->ap_sta &&
!WARN_ON_ONCE(vif->cfg.assoc) &&
vif->type != NL80211_IFTYPE_AP && !mld->fw_status.in_hw_restart) {
vif->type != NL80211_IFTYPE_AP && !mld->fw_status.in_hw_restart &&
!iwl_trans_is_dead(mld->trans)) {
iwl_mld_remove_link(mld, link);
iwl_mld_add_link(mld, link);
}
@ -2853,6 +2854,15 @@ static int iwl_mld_start_pmsr(struct ieee80211_hw *hw,
return iwl_mld_ftm_start(mld, vif, request);
}
static void iwl_mld_abort_pmsr(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
iwl_mld_ftm_abort(mld, 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)
@ -2974,6 +2984,7 @@ 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,
.abort_pmsr = iwl_mld_abort_pmsr,
.can_neg_ttlm = iwl_mld_can_neg_ttlm,
.start_nan = iwl_mld_start_nan,
.stop_nan = iwl_mld_stop_nan,

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2026 Intel Corporation
*/
#ifndef __iwl_mld_mac80211_h__
#define __iwl_mld_mac80211_h__
@ -9,5 +10,6 @@
int iwl_mld_register_hw(struct iwl_mld *mld);
void iwl_mld_recalc_multicast_filter(struct iwl_mld *mld);
void iwl_mld_restart_cleanup(struct iwl_mld *mld);
#endif /* __iwl_mld_mac80211_h__ */

View File

@ -95,6 +95,8 @@ iwl_mld_get_regdomain(struct iwl_mld *mld,
struct iwl_mcc_update_resp_v8 *resp;
u8 resp_ver = iwl_fw_lookup_notif_ver(mld->fw, IWL_ALWAYS_LONG_GROUP,
MCC_UPDATE_CMD, 0);
enum iwl_puncturing_status puncturing_status;
u16 mcc;
IWL_DEBUG_LAR(mld, "Getting regdomain data for %s from FW\n", alpha2);
@ -116,12 +118,13 @@ iwl_mld_get_regdomain(struct iwl_mld *mld,
}
IWL_DEBUG_LAR(mld, "MCC update response version: %d\n", resp_ver);
mcc = le16_to_cpu(resp->mcc);
regd = iwl_parse_nvm_mcc_info(mld->trans,
__le32_to_cpu(resp->n_channels),
resp->channels,
__le16_to_cpu(resp->mcc),
resp->channels, mcc,
__le16_to_cpu(resp->geo_info),
le32_to_cpu(resp->cap), resp_ver);
le32_to_cpu(resp->cap), resp_ver,
&puncturing_status);
if (IS_ERR(regd)) {
IWL_DEBUG_LAR(mld, "Could not get parse update from FW %ld\n",
@ -135,18 +138,25 @@ iwl_mld_get_regdomain(struct iwl_mld *mld,
mld->mcc_src = resp->source_id;
if (puncturing_status == IWL_PUNCTURING_STATUS_ENABLED)
__clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING,
mld->hw->flags);
else if (puncturing_status == IWL_PUNCTURING_STATUS_DISABLED)
ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
if (resp_ver >= 10)
goto out;
/* FM follows BIOS/MCC policy, WH disallows puncturing only in US/CA. */
if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM) {
if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing,
le16_to_cpu(resp->mcc)))
if (!iwl_puncturing_is_allowed_in_bios(mld->fwrt.bios_puncturing,
mcc))
ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
else
__clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING,
mld->hw->flags);
} else if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) ==
IWL_CFG_RF_TYPE_WH) {
u16 mcc = le16_to_cpu(resp->mcc);
IWL_CFG_RF_TYPE_WH) {
if (mcc == IWL_MCC_US || mcc == IWL_MCC_CANADA)
ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
else

View File

@ -212,6 +212,7 @@ static const struct iwl_hcmd_names iwl_mld_reg_and_nvm_names[] = {
HCMD_NAME(TAS_CONFIG),
HCMD_NAME(SAR_OFFSET_MAPPING_TABLE_CMD),
HCMD_NAME(MCC_ALLOWED_AP_TYPE_CMD),
HCMD_NAME(PNVM_INIT_COMPLETE_NTFY),
};
/* Please keep this array *SORTED* by hex value.
@ -418,8 +419,6 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
iwl_mld_construct_fw_runtime(mld, trans, fw, dbgfs_dir);
iwl_mld_get_bios_tables(mld);
iwl_uefi_get_sgom_table(trans, &mld->fwrt);
mld->bios_enable_puncturing = iwl_uefi_get_puncturing(&mld->fwrt);
iwl_mld_hw_set_regulatory(mld);
@ -446,6 +445,8 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
}
if (ret) {
/* wiphy memory is about to be freed, we should cancel any pending work */
wiphy_work_cancel(mld->wiphy, &mld->async_handlers_wk);
wiphy_unlock(mld->wiphy);
rtnl_unlock();
goto err;
@ -511,6 +512,7 @@ iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
iwl_mld_thermal_exit(mld);
wiphy_lock(mld->wiphy);
wiphy_work_cancel(mld->wiphy, &mld->async_handlers_wk);
iwl_mld_low_latency_stop(mld);
iwl_mld_deinit_time_sync(mld);
wiphy_unlock(mld->wiphy);
@ -745,6 +747,7 @@ static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
wiphy_lock(mld->wiphy);
iwl_mld_stop_fw(mld);
iwl_mld_restart_cleanup(mld);
mld->fw_status.in_d3 = false;
wiphy_unlock(mld->wiphy);
}

View File

@ -172,7 +172,6 @@
* @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
* @fw_id_to_ba: maps a fw (BA) id to a corresponding Block Ack session data.
* @num_rx_ba_sessions: tracks the number of active Rx Block Ack (BA) sessions.
* the driver ensures that new BA sessions are blocked once the maximum
@ -279,7 +278,6 @@ struct iwl_mld {
struct led_classdev led;
#endif
enum iwl_mcc_source mcc_src;
bool bios_enable_puncturing;
struct iwl_mld_baid_data __rcu *fw_id_to_ba[IWL_MAX_BAID];
u8 num_rx_ba_sessions;

View File

@ -298,7 +298,8 @@ CMD_VERSIONS(channel_survey_notif,
CMD_VERSIONS(mfuart_notif,
CMD_VER_ENTRY(2, iwl_mfuart_load_notif))
CMD_VERSIONS(update_mcc,
CMD_VER_ENTRY(1, iwl_mcc_chub_notif))
CMD_VER_ENTRY(1, iwl_mcc_chub_notif)
CMD_VER_ENTRY(2, iwl_mcc_chub_notif))
CMD_VERSIONS(session_prot_notif,
CMD_VER_ENTRY(3, iwl_session_prot_notif))
CMD_VERSIONS(missed_beacon_notif,
@ -517,7 +518,7 @@ iwl_mld_notif_is_valid(struct iwl_mld *mld, struct iwl_rx_packet *pkt,
handler->cmd_id, notif_ver,
handler->sizes[handler->n_sizes - 1].ver);
return size < handler->sizes[handler->n_sizes - 1].size;
return false;
}
struct iwl_async_handler_entry {

View File

@ -13,6 +13,26 @@
#include "mld.h"
#include "hcmd.h"
static ssize_t iwl_mld_get_lari_config_cmd_size(u8 cmd_ver)
{
switch (cmd_ver) {
case 15:
return sizeof(struct iwl_lari_config_change_cmd);
case 14:
return offsetof(struct iwl_lari_config_change_cmd,
oem_supported_dsm_bitmap);
case 13:
return offsetof(struct iwl_lari_config_change_cmd,
oem_uhb_allow_extension_bitmap);
case 12:
return offsetof(struct iwl_lari_config_change_cmd,
oem_11bn_allow_bitmap);
default:
WARN(true, "unsupported version: %d", cmd_ver);
return -EINVAL;
}
}
void iwl_mld_get_bios_tables(struct iwl_mld *mld)
{
int ret;
@ -67,6 +87,9 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)
iwl_uefi_get_uneb_table(mld->trans, &mld->fwrt);
iwl_bios_get_phy_filters(&mld->fwrt);
iwl_uefi_get_sgom_table(mld->trans, &mld->fwrt);
iwl_uefi_get_puncturing(&mld->fwrt);
}
static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
@ -325,11 +348,23 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
struct iwl_lari_config_change_cmd cmd = {
.config_bitmap = iwl_mld_get_lari_config_bitmap(fwrt),
};
bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE), 12);
/*
* For LARI_CONFIG_CHANGE command version 13 and above, firmware accepts
* raw DSM values by default and this TLV is no longer needed.
*/
bool has_raw_dsm_capa = cmd_ver >= 13 ||
fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
ssize_t cmd_len = iwl_mld_get_lari_config_cmd_size(cmd_ver);
int ret;
u32 value;
if (cmd_len < 0)
return;
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
if (!ret) {
if (!has_raw_dsm_capa)
@ -371,8 +406,11 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
}
ret = iwl_bios_get_wbem(fwrt, &value);
if (!ret)
if (!ret) {
cmd.oem_320mhz_allow_bitmap = cpu_to_le32(value);
cmd.bios_wbem_hdr.table_source = fwrt->wbem_source;
cmd.bios_wbem_hdr.table_revision = fwrt->wbem_revision;
}
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value);
if (!ret)
@ -386,8 +424,21 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
if (!ret)
cmd.oem_unii9_enable = cpu_to_le32(value);
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG, &value);
if (!ret)
cmd.oem_uhb_allow_extension_bitmap = cpu_to_le32(value);
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_QUERY, &value);
if (!ret)
cmd.oem_supported_dsm_bitmap = cpu_to_le32(value);
cmd.bios_wcpe_hdr.table_source = fwrt->puncturing_source;
cmd.bios_wcpe_hdr.table_revision = fwrt->puncturing_revision;
cmd.wcpe_bitmap = cpu_to_le32(fwrt->bios_puncturing);
if (!cmd.config_bitmap &&
!cmd.oem_uhb_allow_bitmap &&
!cmd.oem_uhb_allow_extension_bitmap &&
!cmd.oem_11ax_allow_bitmap &&
!cmd.oem_unii4_allow_bitmap &&
!cmd.chan_state_active_bitmap &&
@ -396,7 +447,9 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
!cmd.oem_320mhz_allow_bitmap &&
!cmd.oem_11be_allow_bitmap &&
!cmd.oem_11bn_allow_bitmap &&
!cmd.oem_unii9_enable)
!cmd.oem_unii9_enable &&
!cmd.wcpe_bitmap &&
!cmd.oem_supported_dsm_bitmap)
return;
cmd.bios_hdr.table_source = fwrt->dsm_source;
@ -414,6 +467,9 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
le32_to_cpu(cmd.oem_uhb_allow_bitmap),
le32_to_cpu(cmd.force_disable_channels_bitmap));
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_extension_bitmap=0x%x\n",
le32_to_cpu(cmd.oem_uhb_allow_extension_bitmap));
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n",
le32_to_cpu(cmd.edt_bitmap),
@ -427,22 +483,16 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, oem_unii9_enable=0x%x\n",
le32_to_cpu(cmd.oem_unii9_enable));
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, wcpe_bitmap=0x%x\n",
le32_to_cpu(cmd.wcpe_bitmap));
IWL_DEBUG_RADIO(mld,
"sending LARI_CONFIG_CHANGE, oem_supported_dsm_bitmap=0x%x\n",
le32_to_cpu(cmd.oem_supported_dsm_bitmap));
if (iwl_fw_lookup_cmd_ver(mld->fw,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE), 12) == 12) {
int cmd_size = offsetof(typeof(cmd), oem_11bn_allow_bitmap);
ret = iwl_mld_send_cmd_pdu(mld,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE),
&cmd, cmd_size);
} else {
ret = iwl_mld_send_cmd_pdu(mld,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE),
&cmd);
}
ret = iwl_mld_send_cmd_pdu(mld,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE), &cmd, cmd_len);
if (ret)
IWL_DEBUG_RADIO(mld,
"Failed to send LARI_CONFIG_CHANGE (%d)\n",
@ -488,6 +538,8 @@ void iwl_mld_init_ap_type_tables(struct iwl_mld *mld)
if (ret)
IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n",
ret);
else
IWL_DEBUG_RADIO(mld, "MCC_ALLOWED_AP_TYPE_CMD sent to FW\n");
}
void iwl_mld_init_tas(struct iwl_mld *mld)

View File

@ -1681,7 +1681,8 @@ iwl_mld_scan_send_abort_cmd_status(struct iwl_mld *mld, int uid, u32 *status)
static int
iwl_mld_scan_abort(struct iwl_mld *mld, int type, int uid, bool *wait)
{
enum iwl_umac_scan_abort_status status;
enum iwl_umac_scan_abort_status status =
IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND;
int ret;
*wait = true;

View File

@ -355,10 +355,9 @@ static void iwl_mld_fill_pkt_ext(struct iwl_mld *mld,
for (int i = 0; i < MAX_HE_SUPP_NSS; i++) {
for (int bw = 0;
bw < ARRAY_SIZE(*pkt_ext->pkt_ext_qam_th[i]);
bw < ARRAY_SIZE(pkt_ext->pkt_ext_qam_th[i]);
bw++) {
u8 *qam_th =
&pkt_ext->pkt_ext_qam_th[i][bw][0];
u8 *qam_th = pkt_ext->pkt_ext_qam_th[i][bw];
IWL_DEBUG_HT(mld,
"PPE table: nss[%d] bw[%d] PPET8 = %d, PPET16 = %d\n",

View File

@ -1517,12 +1517,48 @@ static int iwl_mvm_fill_lari_config(struct iwl_fw_runtime *fwrt,
return 0;
}
static void iwl_mvm_send_lari_cfg_extension(struct iwl_mvm *mvm)
{
struct iwl_fw_runtime *fwrt = &mvm->fwrt;
struct iwl_lari_config_extension_cmd cmd = {};
u32 cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_EXTENSION);
u32 value;
int ret;
if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) < 1)
return;
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG, &value);
if (ret)
return;
cmd.dsm_table_hdr.table_source = fwrt->dsm_source;
cmd.dsm_table_hdr.table_revision = fwrt->dsm_revision;
cmd.oem_uhb_allow_extension_bitmap = cpu_to_le32(value);
IWL_DEBUG_RADIO(mvm,
"sending LARI_CONFIG_EXTENSION, oem_uhb_allow_extension_bitmap=0x%x\n",
le32_to_cpu(cmd.oem_uhb_allow_extension_bitmap));
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
if (ret < 0)
IWL_DEBUG_RADIO(mvm,
"Failed to send LARI_CONFIG_EXTENSION (%d)\n",
ret);
}
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
{
struct iwl_lari_config_change_cmd cmd;
size_t cmd_size;
int ret;
/*
* LARI_CONFIG_CHANGE triggers a profile update, so send
* LARI_CONFIG_EXTENSION first to make sure its data is applied
* in the same update.
*/
iwl_mvm_send_lari_cfg_extension(mvm);
ret = iwl_mvm_fill_lari_config(&mvm->fwrt, &cmd, &cmd_size);
if (!ret) {
ret = iwl_mvm_send_cmd_pdu(mvm,

View File

@ -152,7 +152,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
resp->channels,
__le16_to_cpu(resp->mcc),
__le16_to_cpu(resp->geo_info),
le32_to_cpu(resp->cap), resp_ver);
le32_to_cpu(resp->cap), resp_ver, NULL);
/* Store the return source id */
src_id = resp->source_id;
if (IS_ERR_OR_NULL(regd)) {
@ -1127,7 +1127,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
}
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
iwl_mvm_stop_device(mvm);
@ -2350,10 +2350,9 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
int bw;
for (bw = 0;
bw < ARRAY_SIZE(*pkt_ext->pkt_ext_qam_th[i]);
bw < ARRAY_SIZE(pkt_ext->pkt_ext_qam_th[i]);
bw++) {
u8 *qam_th =
&pkt_ext->pkt_ext_qam_th[i][bw][0];
u8 *qam_th = pkt_ext->pkt_ext_qam_th[i][bw];
IWL_DEBUG_HT(mvm,
"PPE table: nss[%d] bw[%d] PPET8 = %d, PPET16 = %d\n",

View File

@ -1657,6 +1657,7 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
u8 iwl_mvm_rate_idx_to_fw_idx(const struct iwl_fw *fw, int rate_idx);
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm);
static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
{
@ -1672,14 +1673,24 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm);
/* Tx / Host Commands */
int iwl_mvm_send_cmd(struct iwl_mvm *mvm,
struct iwl_host_cmd *cmd);
int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
u32 flags, u16 len, const void *data);
int _iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
u32 flags, u16 len, const void *data);
#define iwl_mvm_send_cmd_pdu(mvm, id, flags, len, data) ({ \
BUILD_BUG_ON(__builtin_constant_p(len) && \
(u16)(len) > IWL_MAX_CMD_PAYLOAD_SIZE); \
_iwl_mvm_send_cmd_pdu(mvm, id, flags, len, data); \
})
int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm,
struct iwl_host_cmd *cmd,
u32 *status);
int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id,
u16 len, const void *data,
u32 *status);
int _iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id,
u16 len, const void *data,
u32 *status);
#define iwl_mvm_send_cmd_pdu_status(mvm, id, len, data, status) ({ \
BUILD_BUG_ON(__builtin_constant_p(len) && \
(u16)(len) > IWL_MAX_CMD_PAYLOAD_SIZE); \
_iwl_mvm_send_cmd_pdu_status(mvm, id, len, data, status); \
})
int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
@ -2392,14 +2403,12 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
bool sync,
const void *data, u32 size);
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid);
bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm);
#define MVM_TCM_PERIOD_MSEC 500
#define MVM_TCM_PERIOD (HZ * MVM_TCM_PERIOD_MSEC / 1000)
#define MVM_LL_PERIOD (10 * HZ)
void iwl_mvm_tcm_work(struct work_struct *work);
void iwl_mvm_recalc_tcm(struct iwl_mvm *mvm);
void iwl_mvm_pause_tcm(struct iwl_mvm *mvm, bool with_cancel);
void iwl_mvm_resume_tcm(struct iwl_mvm *mvm);
void iwl_mvm_tcm_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

View File

@ -155,8 +155,8 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
if (notif->type != cpu_to_le32(IWL_DP_MON_NOTIF_TYPE_EXT_CCA))
return;
/* FIXME: should fetch the link and not the vif */
vif = iwl_mvm_get_vif_by_macid(mvm, notif->link_id);
/* mac_id = link_id since we don't support MLO */
vif = iwl_mvm_rcu_dereference_vif_id(mvm, notif->link_id, false);
if (!vif || vif->type != NL80211_IFTYPE_STATION)
return;
@ -707,6 +707,7 @@ static const struct iwl_hcmd_names iwl_mvm_regulatory_and_nvm_names[] = {
HCMD_NAME(NVM_ACCESS_COMPLETE),
HCMD_NAME(NVM_GET_INFO),
HCMD_NAME(TAS_CONFIG),
HCMD_NAME(LARI_CONFIG_EXTENSION),
};
/* Please keep this array *SORTED* by hex value.
@ -954,7 +955,7 @@ static void iwl_mvm_frob_txf_key_iter(struct ieee80211_hw *hw,
}
match++;
if (match == keylen) {
memset(txf->buf + i - keylen, 0xAA, keylen);
memset(txf->buf + i + 1 - keylen, 0xAA, keylen);
match = 0;
}
}
@ -1535,6 +1536,7 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
iwl_fw_cancel_timestamp(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
mvm->sf_state = SF_UNINIT;
iwl_mvm_pause_tcm(mvm, false);
@ -2090,7 +2092,7 @@ static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
mutex_lock(&mvm->mutex);
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
iwl_mvm_stop_device(mvm);
iwl_mvm_restart_cleanup(mvm);
mvm->fast_resume = false;
mutex_unlock(&mvm->mutex);
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2022 Intel Corporation
* Copyright (C) 2026 Intel Corporation
*/
#ifndef __TIME_SYNC_H__
#define __TIME_SYNC_H__
@ -19,6 +20,9 @@ int iwl_mvm_time_sync_config(struct iwl_mvm *mvm, const u8 *addr,
static inline
bool iwl_mvm_time_sync_frame(struct iwl_mvm *mvm, struct sk_buff *skb, u8 *addr)
{
if (!mvm->time_sync.active)
return false;
if (ether_addr_equal(mvm->time_sync.peer_addr, addr) &&
(ieee80211_is_timing_measurement(skb) || ieee80211_is_ftm(skb))) {
skb_queue_tail(&mvm->time_sync.frame_list, skb);

View File

@ -73,8 +73,8 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
return ret;
}
int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
u32 flags, u16 len, const void *data)
int _iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
u32 flags, u16 len, const void *data)
{
struct iwl_host_cmd cmd = {
.id = id,
@ -137,8 +137,8 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
/*
* We assume that the caller set the status to the sucess value
*/
int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,
const void *data, u32 *status)
int _iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,
const void *data, u32 *status)
{
struct iwl_host_cmd cmd = {
.id = id,
@ -689,36 +689,6 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
return bss_iter_data.vif;
}
struct iwl_bss_find_iter_data {
struct ieee80211_vif *vif;
u32 macid;
};
static void iwl_mvm_bss_find_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_bss_find_iter_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (mvmvif->id == data->macid)
data->vif = vif;
}
struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid)
{
struct iwl_bss_find_iter_data data = {
.macid = macid,
};
lockdep_assert_held(&mvm->mutex);
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bss_find_iface_iterator, &data);
return data.vif;
}
struct iwl_sta_iter_data {
bool assoc;
};
@ -1055,7 +1025,7 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
/*
* If the current load isn't low we need to force re-evaluation
* in the TCM period, so that we can return to low load if there
* was no traffic at all (and thus iwl_mvm_recalc_tcm didn't get
* was no traffic at all (and thus iwl_mvm_tcm_work() didn't get
* triggered by traffic).
*/
if (load != IWL_MVM_TRAFFIC_LOW)
@ -1081,8 +1051,11 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
return 0;
}
void iwl_mvm_recalc_tcm(struct iwl_mvm *mvm)
void iwl_mvm_tcm_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
struct iwl_mvm *mvm = container_of(delayed_work, struct iwl_mvm,
tcm.work);
unsigned long ts = jiffies;
bool handle_uapsd =
time_after(ts, mvm->tcm.uapsd_nonagg_ts +
@ -1119,15 +1092,6 @@ void iwl_mvm_recalc_tcm(struct iwl_mvm *mvm)
iwl_mvm_tcm_results(mvm);
}
void iwl_mvm_tcm_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
struct iwl_mvm *mvm = container_of(delayed_work, struct iwl_mvm,
tcm.work);
iwl_mvm_recalc_tcm(mvm);
}
void iwl_mvm_pause_tcm(struct iwl_mvm *mvm, bool with_cancel)
{
spin_lock_bh(&mvm->tcm.lock);

View File

@ -548,6 +548,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_mac_cfg)},
{IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_mac_cfg)},
{IWL_PCI_DEVICE(0xD240, PCI_ANY_ID, iwl_sc_mac_cfg)},
{IWL_PCI_DEVICE(0x9327, PCI_ANY_ID, iwl_sc_mac_cfg)},
#endif /* CONFIG_IWLMVM || CONFIG_IWLMLD */
{0}

View File

@ -773,6 +773,8 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
tfd = iwl_txq_gen2_build_tfd(trans, txq, dev_cmd, skb, out_meta);
if (!tfd) {
txq->entries[idx].skb = NULL;
txq->entries[idx].cmd = NULL;
spin_unlock(&txq->lock);
return -1;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2003-2014, 2018-2021, 2023-2025 Intel Corporation
* Copyright (C) 2003-2014, 2018-2021, 2023-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -1149,10 +1149,17 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
unsigned int wdg_timeout)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id];
struct iwl_txq *txq;
int fifo = -1;
bool scd_bug = false;
if (WARN_ONCE(txq_id < 0 ||
txq_id >= trans->mac_cfg->base->num_of_queues,
"queue %d out of range", txq_id))
return false;
txq = trans_pcie->txqs.txq[txq_id];
if (test_and_set_bit(txq_id, trans_pcie->txqs.queue_used))
WARN_ONCE(1, "queue %d already used - expect issues", txq_id);