From: Pagadala Yesu Anjaneyulu Date: Fri, 20 Mar 2026 08:09:10 +0000 (+0200) Subject: wifi: iwlwifi: fw: Add TLV support for BIOS revision of command X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3fd645e6a153e2ce45928ec32442ab4719c3afa6;p=thirdparty%2Flinux.git wifi: iwlwifi: fw: Add TLV support for BIOS revision of command Add support for newer firmware API versions that support multiple BIOS revisions. Use the new TLV provided by firmware to determine which BIOS revision it supports. Future patches will use this information to either drop commands when the BIOS revision is higher than supported or convert commands based on the command specific implementation. Since we are including now nvm-reg.h in img.h, this causes a re-definition error of IWL_NUM_CHANNELS which is also defined in eeprom.c, so rename IWL_NUM_CHANNELS to IWL_NUM_CHANNELS_V2 Signed-off-by: Pagadala Yesu Anjaneyulu Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260320100746.76c8a9589ea0.I7f9157115de702e07511f2c3ed5fcb9ae4c667aa@changeid --- diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 25c860a05b0e9..443a9a4163252 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -204,7 +204,7 @@ struct iwl_nvm_get_info_phy { } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ #define IWL_NUM_CHANNELS_V1 51 -#define IWL_NUM_CHANNELS 110 +#define IWL_NUM_CHANNELS_V2 110 /** * struct iwl_nvm_get_info_regulatory_v1 - regulatory information @@ -227,7 +227,7 @@ struct iwl_nvm_get_info_regulatory_v1 { struct iwl_nvm_get_info_regulatory { __le32 lar_enabled; __le32 n_channels; - __le32 channel_profile[IWL_NUM_CHANNELS]; + __le32 channel_profile[IWL_NUM_CHANNELS_V2]; } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 378788de1d74f..f7a6f21267e9d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -103,6 +103,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67, IWL_UCODE_TLV_CURRENT_PC = 68, IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72, + IWL_UCODE_TLV_CMD_BIOS_TABLE = 73, /* contains sub-sections like PNVM file does (did) */ IWL_UCODE_TLV_PNVM_DATA = 74, @@ -1040,6 +1041,20 @@ struct iwl_fw_cmd_version { u8 notif_ver; } __packed; +/** + * struct iwl_fw_cmd_bios_table - firmware command BIOS revision entry + * @cmd: command ID + * @group: group ID + * @max_acpi_revision: max supported ACPI revision of command. + * @max_uefi_revision: max supported UEFI revision of command. + */ +struct iwl_fw_cmd_bios_table { + u8 cmd; + u8 group; + u8 max_acpi_revision; + u8 max_uefi_revision; +} __packed; + struct iwl_fw_tcm_error_addr { __le32 addr; }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c index c2f4fc83a22cd..3cc1e3ae08589 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c @@ -1,11 +1,41 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright(c) 2019 - 2021 Intel Corporation - * Copyright(c) 2024 Intel Corporation + * Copyright(c) 2024 - 2025 Intel Corporation */ #include #include "img.h" +u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw, + enum bios_source table_source, + u32 cmd_id, u8 def) +{ + const struct iwl_fw_cmd_bios_table *entry; + /* prior to LONG_GROUP, we never used this CMD version API */ + u8 grp = iwl_cmd_groupid(cmd_id) ?: LONG_GROUP; + u8 cmd = iwl_cmd_opcode(cmd_id); + + if (table_source != BIOS_SOURCE_ACPI && + table_source != BIOS_SOURCE_UEFI) + return def; + + if (!fw->ucode_capa.cmd_bios_tables || + !fw->ucode_capa.n_cmd_bios_tables) + return def; + + entry = fw->ucode_capa.cmd_bios_tables; + for (int i = 0; i < fw->ucode_capa.n_cmd_bios_tables; i++, entry++) { + if (entry->group == grp && entry->cmd == cmd) { + if (table_source == BIOS_SOURCE_ACPI) + return entry->max_acpi_revision; + return entry->max_uefi_revision; + } + } + + return def; +} +EXPORT_SYMBOL_GPL(iwl_fw_lookup_cmd_bios_supported_revision); + u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def) { const struct iwl_fw_cmd_version *entry; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 045a3e0094291..94113d1db8e13 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -9,6 +9,7 @@ #include #include "api/dbg-tlv.h" +#include "api/nvm-reg.h" #include "file.h" #include "error-dump.h" @@ -57,6 +58,9 @@ struct iwl_ucode_capabilities { const struct iwl_fw_cmd_version *cmd_versions; u32 n_cmd_versions; + + const struct iwl_fw_cmd_bios_table *cmd_bios_tables; + u32 n_cmd_bios_tables; }; static inline bool @@ -274,6 +278,10 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type) return &fw->img[ucode_type]; } +u8 iwl_fw_lookup_cmd_bios_supported_revision(const struct iwl_fw *fw, + enum bios_source table_source, + u32 cmd_id, u8 def); + u8 iwl_fw_lookup_cmd_ver(const struct iwl_fw *fw, u32 cmd_id, u8 def); u8 iwl_fw_lookup_notif_ver(const struct iwl_fw *fw, u8 grp, u8 cmd, u8 def); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 475b3e417efa8..4cdd0fe1b788f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -133,6 +133,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) kfree(drv->fw.dbg.mem_tlv); kfree(drv->fw.iml); kfree(drv->fw.ucode_capa.cmd_versions); + kfree(drv->fw.ucode_capa.cmd_bios_tables); kfree(drv->fw.phy_integration_ver); kfree(drv->trans->dbg.pc_data); drv->trans->dbg.pc_data = NULL; @@ -1426,6 +1427,26 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, return -ENOMEM; drv->fw.pnvm_size = tlv_len; break; + case IWL_UCODE_TLV_CMD_BIOS_TABLE: + if (tlv_len % sizeof(struct iwl_fw_cmd_bios_table)) { + IWL_ERR(drv, + "Invalid length for command bios table: %u\n", + tlv_len); + return -EINVAL; + } + + if (capa->cmd_bios_tables) { + IWL_ERR(drv, "Duplicate TLV type 0x%02X detected\n", + tlv_type); + return -EINVAL; + } + capa->cmd_bios_tables = kmemdup(tlv_data, tlv_len, + GFP_KERNEL); + if (!capa->cmd_bios_tables) + return -ENOMEM; + capa->n_cmd_bios_tables = + tlv_len / sizeof(struct iwl_fw_cmd_bios_table); + break; default: IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 6d235c417fdd1..e5b08c4e7f159 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -2031,7 +2031,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, if (empty_otp) IWL_INFO(trans, "OTP is empty\n"); - nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS); + nvm = kzalloc_flex(*nvm, channels, IWL_NUM_CHANNELS_V2); if (!nvm) { ret = -ENOMEM; goto out;