Commit 05bc4583 authored by Jiri Kosina's avatar Jiri Kosina
Browse files

Merge branch 'for-6.20/intel-ish' into for-linus

- support for new firmware handling in intel-ish-hid (Vishnu Sankar)
parents 9be2c22b 698362f1
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -413,6 +413,10 @@ Vendors who wish to upstream their custom firmware should follow these guideline

- The firmware filename should use one of the following patterns:

  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_SKU_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_NAME_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin``
  - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}.bin``
@@ -420,16 +424,21 @@ Vendors who wish to upstream their custom firmware should follow these guideline

- ``${intel_plat_gen}`` indicates the Intel platform generation (e.g., ``lnlm`` for Lunar Lake) and must not exceed 8 characters in length.
- ``${SYS_VENDOR_CRC32}`` is the CRC32 checksum of the ``sys_vendor`` value from the DMI field ``DMI_SYS_VENDOR``.
- ``${PRODUCT_FAMILY_CRC32}`` is the CRC32 checksum of the ``product_family`` value from the DMI field ``DMI_PRODUCT_FAMILY``.
- ``${PRODUCT_NAME_CRC32}`` is the CRC32 checksum of the ``product_name`` value from the DMI field ``DMI_PRODUCT_NAME``.
- ``${PRODUCT_SKU_CRC32}`` is the CRC32 checksum of the ``product_sku`` value from the DMI field ``DMI_PRODUCT_SKU``.

During system boot, the ISH Linux driver will attempt to load the firmware in the following order, prioritizing custom firmware with more precise matching patterns:

1. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin``
2. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin``
3. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}.bin``
4. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}.bin``
5. ``intel/ish/ish_${intel_plat_gen}.bin``
1. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin``
2. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_SKU_CRC32}.bin``
3. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}_${PRODUCT_NAME_CRC32}.bin``
4. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_FAMILY_CRC32}.bin``
5. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin``
6. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin``
7. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}.bin``
8. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}.bin``
9. ``intel/ish/ish_${intel_plat_gen}.bin``

The driver will load the first matching firmware and skip the rest. If no matching firmware is found, it will proceed to the next pattern in the specified order. If all searches fail, the default Intel firmware, listed last in the order above, will be loaded.

+56 −2
Original line number Diff line number Diff line
@@ -195,13 +195,19 @@ static int prepare_dma_bufs(struct ishtp_device *dev,
	return 0;
}

/* Patterns with PRODUCT_FAMILY */
#define ISH_FW_FILE_VENDOR_FAMILY_NAME_SKU_FMT "intel/ish/ish_%s_%08x_%08x_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_FAMILY_SKU_FMT "intel/ish/ish_%s_%08x_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_FAMILY_NAME_FMT "intel/ish/ish_%s_%08x_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_FAMILY_FMT "intel/ish/ish_%s_%08x_%08x.bin"

#define ISH_FW_FILE_VENDOR_NAME_SKU_FMT "intel/ish/ish_%s_%08x_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_SKU_FMT "intel/ish/ish_%s_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_NAME_FMT "intel/ish/ish_%s_%08x_%08x.bin"
#define ISH_FW_FILE_VENDOR_FMT "intel/ish/ish_%s_%08x.bin"
#define ISH_FW_FILE_DEFAULT_FMT "intel/ish/ish_%s.bin"

#define ISH_FW_FILENAME_LEN_MAX 56
#define ISH_FW_FILENAME_LEN_MAX 72

#define ISH_CRC_INIT (~0u)
#define ISH_CRC_XOROUT (~0u)
@@ -228,6 +234,12 @@ static int _request_ish_firmware(const struct firmware **firmware_p,
 * for the given device in the following order, prioritizing custom firmware
 * with more precise matching patterns:
 *
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_FAMILY_CRC32)
 *   _$(PRODUCT_NAME_CRC32)_${PRODUCT_SKU_CRC32}.bin
 *
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_FAMILY_CRC32)_${PRODUCT_SKU_CRC32}.bin
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_FAMILY_CRC32)_$(PRODUCT_NAME_CRC32).bin
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_FAMILY_CRC32).bin
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_NAME_CRC32)_${PRODUCT_SKU_CRC32}.bin
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin
 *   ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_NAME_CRC32).bin
@@ -256,8 +268,9 @@ static int request_ish_firmware(const struct firmware **firmware_p,
				struct device *dev)
{
	const char *gen, *sys_vendor, *product_name, *product_sku;
	const char *product_family;
	struct ishtp_device *ishtp = dev_get_drvdata(dev);
	u32 vendor_crc, name_crc, sku_crc;
	u32 vendor_crc, name_crc, sku_crc, family_crc;
	char filename[ISH_FW_FILENAME_LEN_MAX];
	int ret;

@@ -265,14 +278,55 @@ static int request_ish_firmware(const struct firmware **firmware_p,
	sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
	product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
	product_sku = dmi_get_system_info(DMI_PRODUCT_SKU);
	product_family = dmi_get_system_info(DMI_PRODUCT_FAMILY);

	if (sys_vendor)
		vendor_crc = crc32(ISH_CRC_INIT, sys_vendor, strlen(sys_vendor)) ^ ISH_CRC_XOROUT;
	if (product_family)
		family_crc = crc32(ISH_CRC_INIT, product_family,
				   strlen(product_family)) ^ ISH_CRC_XOROUT;
	if (product_name)
		name_crc = crc32(ISH_CRC_INIT, product_name, strlen(product_name)) ^ ISH_CRC_XOROUT;
	if (product_sku)
		sku_crc = crc32(ISH_CRC_INIT, product_sku, strlen(product_sku)) ^ ISH_CRC_XOROUT;

	/* PRODUCT_FAMILY-extended matching */
	if (sys_vendor && product_family && product_name && product_sku) {
		snprintf(filename, sizeof(filename),
			 ISH_FW_FILE_VENDOR_FAMILY_NAME_SKU_FMT,
			 gen, vendor_crc, family_crc, name_crc, sku_crc);
		ret = _request_ish_firmware(firmware_p, filename, dev);
		if (!ret)
			return 0;
	}

	if (sys_vendor && product_family && product_sku) {
		snprintf(filename, sizeof(filename),
			 ISH_FW_FILE_VENDOR_FAMILY_SKU_FMT,
			 gen, vendor_crc, family_crc, sku_crc);
		ret = _request_ish_firmware(firmware_p, filename, dev);
		if (!ret)
			return 0;
	}

	if (sys_vendor && product_family && product_name) {
		snprintf(filename, sizeof(filename),
			 ISH_FW_FILE_VENDOR_FAMILY_NAME_FMT,
			 gen, vendor_crc, family_crc, name_crc);
		ret = _request_ish_firmware(firmware_p, filename, dev);
		if (!ret)
			return 0;
	}

	if (sys_vendor && product_family) {
		snprintf(filename, sizeof(filename),
			 ISH_FW_FILE_VENDOR_FAMILY_FMT,
			 gen, vendor_crc, family_crc);
		ret = _request_ish_firmware(firmware_p, filename, dev);
		if (!ret)
			return 0;
}

	if (sys_vendor && product_name && product_sku) {
		snprintf(filename, sizeof(filename), ISH_FW_FILE_VENDOR_NAME_SKU_FMT, gen,
			 vendor_crc, name_crc, sku_crc);