drivers/gpu/drm/i915/i915_sw_fence.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/i915_sw_fence.c
Extension
.c
Size
14283 bytes
Lines
611
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 i915_sw_dma_fence_cb_timer {
	struct i915_sw_dma_fence_cb base;
	struct dma_fence *dma;
	struct timer_list timer;
	struct irq_work work;
	struct rcu_head rcu;
};

static void dma_i915_sw_fence_wake(struct dma_fence *dma,
				   struct dma_fence_cb *data)
{
	struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);

	i915_sw_fence_set_error_once(cb->fence, dma->error);
	i915_sw_fence_complete(cb->fence);
	kfree(cb);
}

static void timer_i915_sw_fence_wake(struct timer_list *t)
{
	struct i915_sw_dma_fence_cb_timer *cb = timer_container_of(cb, t,
								   timer);
	struct i915_sw_fence *fence;
	const char __rcu *timeline;
	const char __rcu *driver;

	fence = xchg(&cb->base.fence, NULL);
	if (!fence)
		return;

	rcu_read_lock();
	driver = dma_fence_driver_name(cb->dma);
	timeline = dma_fence_timeline_name(cb->dma);
	pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%ps)\n",
		  rcu_dereference(driver),
		  rcu_dereference(timeline),
		  cb->dma->seqno,
		  i915_sw_fence_debug_hint(fence));
	rcu_read_unlock();

	i915_sw_fence_set_error_once(fence, -ETIMEDOUT);
	i915_sw_fence_complete(fence);
}

static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma,
					 struct dma_fence_cb *data)
{
	struct i915_sw_dma_fence_cb_timer *cb =
		container_of(data, typeof(*cb), base.base);
	struct i915_sw_fence *fence;

	fence = xchg(&cb->base.fence, NULL);
	if (fence) {
		i915_sw_fence_set_error_once(fence, dma->error);
		i915_sw_fence_complete(fence);
	}

	irq_work_queue(&cb->work);
}

static void irq_i915_sw_fence_work(struct irq_work *wrk)
{
	struct i915_sw_dma_fence_cb_timer *cb =
		container_of(wrk, typeof(*cb), work);

	timer_shutdown_sync(&cb->timer);
	dma_fence_put(cb->dma);

	kfree_rcu(cb, rcu);
}

int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
				  struct dma_fence *dma,
				  unsigned long timeout,
				  gfp_t gfp)
{
	struct i915_sw_dma_fence_cb *cb;
	dma_fence_func_t func;
	int ret;

	debug_fence_assert(fence);
	might_sleep_if(gfpflags_allow_blocking(gfp));

	if (dma_fence_is_signaled(dma)) {
		i915_sw_fence_set_error_once(fence, dma->error);
		return 0;
	}

	cb = kmalloc(timeout ?
		     sizeof(struct i915_sw_dma_fence_cb_timer) :

Annotation

Implementation Notes