drivers/gpu/drm/i915/selftests/i915_sw_fence.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/selftests/i915_sw_fence.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/selftests/i915_sw_fence.c
Extension
.c
Size
14941 bytes
Lines
768
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 task_ipc {
	struct work_struct work;
	struct completion started;
	struct i915_sw_fence *in, *out;
	int value;
};

static void task_ipc(struct work_struct *work)
{
	struct task_ipc *ipc = container_of(work, typeof(*ipc), work);

	complete(&ipc->started);

	i915_sw_fence_wait(ipc->in);
	smp_store_mb(ipc->value, 1);
	i915_sw_fence_commit(ipc->out);
}

static int test_ipc(void *arg)
{
	struct task_ipc ipc;
	struct workqueue_struct *wq;
	int ret = 0;

	wq = alloc_workqueue("i1915-selftest", WQ_PERCPU, 0);
	if (wq == NULL)
		return -ENOMEM;

	/* Test use of i915_sw_fence as an interprocess signaling mechanism */
	ipc.in = alloc_fence();
	if (!ipc.in) {
		ret = -ENOMEM;
		goto err_work;
	}
	ipc.out = alloc_fence();
	if (!ipc.out) {
		ret = -ENOMEM;
		goto err_in;
	}

	/* use a completion to avoid chicken-and-egg testing */
	init_completion(&ipc.started);

	ipc.value = 0;
	INIT_WORK_ONSTACK(&ipc.work, task_ipc);
	queue_work(wq, &ipc.work);

	wait_for_completion(&ipc.started);

	usleep_range(1000, 2000);
	if (READ_ONCE(ipc.value)) {
		pr_err("worker updated value before i915_sw_fence was signaled\n");
		ret = -EINVAL;
	}

	i915_sw_fence_commit(ipc.in);
	i915_sw_fence_wait(ipc.out);

	if (!READ_ONCE(ipc.value)) {
		pr_err("worker signaled i915_sw_fence before value was posted\n");
		ret = -EINVAL;
	}

	flush_work(&ipc.work);
	destroy_work_on_stack(&ipc.work);
	free_fence(ipc.out);
err_in:
	free_fence(ipc.in);
err_work:
	destroy_workqueue(wq);

	return ret;
}

static int test_timer(void *arg)
{
	unsigned long target, delay;
	struct timed_fence tf;

	preempt_disable();
	timed_fence_init(&tf, target = jiffies);
	if (!i915_sw_fence_done(&tf.fence)) {
		pr_err("Fence with immediate expiration not signaled\n");
		goto err;
	}
	preempt_enable();
	timed_fence_fini(&tf);

	for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) {
		preempt_disable();

Annotation

Implementation Notes