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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
Extension
.c
Size
9797 bytes
Lines
359
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

if (!intel_gsc_uc_fw_init_done(gsc)) {
			gt_err(gt, "Proxy request received with GSC not loaded!\n");
			goto out_put;
		}

		ret = intel_gsc_proxy_request_handler(gsc);
		if (ret) {
			if (actions & GSC_ACTION_FW_LOAD) {
				/*
				 * A proxy failure right after firmware load means the proxy-init
				 * step has failed so mark GSC as not usable after this
				 */
				gt_err(gt, "GSC proxy handler failed to init\n");
				intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
			}
			goto out_put;
		}

		/* mark the GSC FW init as done the first time we run this */
		if (actions & GSC_ACTION_FW_LOAD) {
			/*
			 * If there is a proxy establishment error, the GSC might still
			 * complete the request handling cleanly, so we need to check the
			 * status register to check if the proxy init was actually successful
			 */
			if (intel_gsc_uc_fw_proxy_init_done(gsc, false)) {
				gt_dbg(gt, "GSC Proxy initialized\n");
				intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING);
			} else {
				gt_err(gt, "GSC status reports proxy init not complete\n");
				intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
			}
		}
	}

out_put:
	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
}

static bool gsc_engine_supported(struct intel_gt *gt)
{
	intel_engine_mask_t mask;

	/*
	 * We reach here from i915_driver_early_probe for the primary GT before
	 * its engine mask is set, so we use the device info engine mask for it.
	 * For other GTs we expect the GT-specific mask to be set before we
	 * call this function.
	 */
	GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask);

	if (gt_is_root(gt))
		mask = INTEL_INFO(gt->i915)->platform_engine_mask;
	else
		mask = gt->info.engine_mask;

	return __HAS_ENGINE(mask, GSC0);
}

void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc)
{
	struct intel_gt *gt = gsc_uc_to_gt(gsc);

	/*
	 * GSC FW needs to be copied to a dedicated memory allocations for
	 * loading (see gsc->local), so we don't need to GGTT map the FW image
	 * itself into GGTT.
	 */
	intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC, false);
	INIT_WORK(&gsc->work, gsc_work);

	/* we can arrive here from i915_driver_early_probe for primary
	 * GT with it being not fully setup hence check device info's
	 * engine mask
	 */
	if (!gsc_engine_supported(gt)) {
		intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
		return;
	}

	gsc->wq = alloc_ordered_workqueue("i915_gsc", 0);
	if (!gsc->wq) {
		gt_err(gt, "failed to allocate WQ for GSC, disabling FW\n");
		intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
	}
}

static int gsc_allocate_and_map_vma(struct intel_gsc_uc *gsc, u32 size)
{
	struct intel_gt *gt = gsc_uc_to_gt(gsc);

Annotation

Implementation Notes