drivers/gpu/drm/i915/gt/selftest_lrc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/selftest_lrc.c
Extension
.c
Size
41892 bytes
Lines
1995
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 lrc_timestamp {
	struct intel_engine_cs *engine;
	struct intel_context *ce[2];
	u32 poison;
};

static bool timestamp_advanced(u32 start, u32 end)
{
	return (s32)(end - start) > 0;
}

static int __lrc_timestamp(const struct lrc_timestamp *arg, bool preempt)
{
	u32 *slot = memset32(arg->engine->status_page.addr + 1000, 0, 4);
	struct i915_request *rq;
	u32 timestamp;
	int err = 0;

	arg->ce[0]->lrc_reg_state[CTX_TIMESTAMP] = arg->poison;
	rq = create_timestamp(arg->ce[0], slot, 1);
	if (IS_ERR(rq))
		return PTR_ERR(rq);

	err = wait_for_submit(rq->engine, rq, HZ / 2);
	if (err)
		goto err;

	if (preempt) {
		arg->ce[1]->lrc_reg_state[CTX_TIMESTAMP] = 0xdeadbeef;
		err = emit_semaphore_signal(arg->ce[1], slot);
		if (err)
			goto err;
	} else {
		slot[0] = 1;
		wmb();
	}

	/* And wait for switch to kernel (to save our context to memory) */
	err = context_flush(arg->ce[0], HZ / 2);
	if (err)
		goto err;

	if (!timestamp_advanced(arg->poison, slot[1])) {
		pr_err("%s(%s): invalid timestamp on restore, context:%x, request:%x\n",
		       arg->engine->name, preempt ? "preempt" : "simple",
		       arg->poison, slot[1]);
		err = -EINVAL;
	}

	timestamp = READ_ONCE(arg->ce[0]->lrc_reg_state[CTX_TIMESTAMP]);
	if (!timestamp_advanced(slot[1], timestamp)) {
		pr_err("%s(%s): invalid timestamp on save, request:%x, context:%x\n",
		       arg->engine->name, preempt ? "preempt" : "simple",
		       slot[1], timestamp);
		err = -EINVAL;
	}

err:
	memset32(slot, -1, 4);
	i915_request_put(rq);
	return err;
}

static int live_lrc_timestamp(void *arg)
{
	struct lrc_timestamp data = {};
	struct intel_gt *gt = arg;
	enum intel_engine_id id;
	const u32 poison[] = {
		0,
		S32_MAX,
		(u32)S32_MAX + 1,
		U32_MAX,
	};

	/*
	 * This test was designed to isolate a hardware bug.
	 * The bug was found and fixed in future generations but
	 * now the test pollutes our CI on previous generation.
	 */
	if (GRAPHICS_VER(gt->i915) == 12)
		return 0;

	/*
	 * We want to verify that the timestamp is saved and restore across
	 * context switches and is monotonic.
	 *
	 * So we do this with a little bit of LRC poisoning to check various
	 * boundary conditions, and see what happens if we preempt the context
	 * with a second request (carrying more poison into the timestamp).

Annotation

Implementation Notes