drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
Extension
.c
Size
41770 bytes
Lines
1387
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct fw_blobs_by_type {
	const struct uc_fw_platform_requirement *blobs;
	u32 count;
};

static const struct uc_fw_platform_requirement blobs_guc[] = {
	INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP)
};

static const struct uc_fw_platform_requirement blobs_huc[] = {
	INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC)
};

static const struct uc_fw_platform_requirement blobs_gsc[] = {
	INTEL_GSC_FIRMWARE_DEFS(MAKE_FW_LIST, GSC_FW_BLOB)
};

static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = {
	[INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
	[INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
	[INTEL_UC_FW_TYPE_GSC] = { blobs_gsc, ARRAY_SIZE(blobs_gsc) },
};

static void
__uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
{
	const struct uc_fw_platform_requirement *fw_blobs;
	enum intel_platform p = INTEL_INFO(i915)->platform;
	u32 fw_count;
	u8 rev = INTEL_REVID(i915);
	int i;
	bool found;

	/*
	 * The only difference between the ADL GuC FWs is the HWConfig support.
	 * ADL-N does not support HWConfig, so we should use the same binary as
	 * ADL-S, otherwise the GuC might attempt to fetch a config table that
	 * does not exist.
	 */
	if (IS_ALDERLAKE_P_N(i915))
		p = INTEL_ALDERLAKE_S;

	GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all));
	fw_blobs = blobs_all[uc_fw->type].blobs;
	fw_count = blobs_all[uc_fw->type].count;

	found = false;
	for (i = 0; i < fw_count && p <= fw_blobs[i].p; i++) {
		const struct uc_fw_blob *blob = &fw_blobs[i].blob;

		if (p != fw_blobs[i].p)
			continue;

		if (rev < fw_blobs[i].rev)
			continue;

		if (uc_fw->file_selected.path) {
			/*
			 * Continuing an earlier search after a found blob failed to load.
			 * Once the previously chosen path has been found, clear it out
			 * and let the search continue from there.
			 */
			if (uc_fw->file_selected.path == blob->path)
				uc_fw->file_selected.path = NULL;

			continue;
		}

		uc_fw->file_selected.path = blob->path;
		uc_fw->file_wanted.path = blob->path;
		uc_fw->file_wanted.ver.major = blob->major;
		uc_fw->file_wanted.ver.minor = blob->minor;
		uc_fw->file_wanted.ver.patch = blob->patch;
		uc_fw->has_gsc_headers = blob->has_gsc_headers;
		found = true;
		break;
	}

	if (!found && uc_fw->file_selected.path) {
		/* Failed to find a match for the last attempt?! */
		uc_fw->file_selected.path = NULL;
	}
}

static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_fw_type type)
{
	const struct uc_fw_platform_requirement *fw_blobs;
	u32 fw_count;
	int i, j;

Annotation

Implementation Notes