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 <pagadala.yesu.anjaneyulu@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260320100746.76c8a9589ea0.I7f9157115de702e07511f2c3ed5fcb9ae4c667aa@changeid
} __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
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 */
/**
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,
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 */
// 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 <fw/api/commands.h>
#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;
#include <linux/types.h>
#include "api/dbg-tlv.h"
+#include "api/nvm-reg.h"
#include "file.h"
#include "error-dump.h"
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
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);
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;
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;
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;