drivers/gpu/drm/i915/i915_request.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/i915_request.c
Extension
.c
Size
68143 bytes
Lines
2316
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 execute_cb {
	struct irq_work work;
	struct i915_sw_fence *fence;
};

static struct kmem_cache *slab_requests;
static struct kmem_cache *slab_execute_cbs;

static const char *i915_fence_get_driver_name(struct dma_fence *fence)
{
	return dev_name(to_request(fence)->i915->drm.dev);
}

static const char *i915_fence_get_timeline_name(struct dma_fence *fence)
{
	const struct i915_gem_context *ctx;

	/*
	 * The timeline struct (as part of the ppgtt underneath a context)
	 * may be freed when the request is no longer in use by the GPU.
	 * We could extend the life of a context to beyond that of all
	 * fences, possibly keeping the hw resource around indefinitely,
	 * or we just give them a false name. Since
	 * dma_fence_ops.get_timeline_name is a debug feature, the occasional
	 * lie seems justifiable.
	 */
	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
		return "signaled";

	ctx = i915_request_gem_context(to_request(fence));
	if (!ctx)
		return "[" DRIVER_NAME "]";

	return ctx->name;
}

static bool i915_fence_signaled(struct dma_fence *fence)
{
	return i915_request_completed(to_request(fence));
}

static bool i915_fence_enable_signaling(struct dma_fence *fence)
{
	return i915_request_enable_breadcrumb(to_request(fence));
}

static signed long i915_fence_wait(struct dma_fence *fence,
				   bool interruptible,
				   signed long timeout)
{
	return i915_request_wait_timeout(to_request(fence),
					 interruptible | I915_WAIT_PRIORITY,
					 timeout);
}

struct kmem_cache *i915_request_slab_cache(void)
{
	return slab_requests;
}

static void i915_fence_release(struct dma_fence *fence)
{
	struct i915_request *rq = to_request(fence);

	GEM_BUG_ON(rq->guc_prio != GUC_PRIO_INIT &&
		   rq->guc_prio != GUC_PRIO_FINI);

	i915_request_free_capture_list(fetch_and_zero(&rq->capture_list));
	if (rq->batch_res) {
		i915_vma_resource_put(rq->batch_res);
		rq->batch_res = NULL;
	}

	/*
	 * The request is put onto a RCU freelist (i.e. the address
	 * is immediately reused), mark the fences as being freed now.
	 * Otherwise the debugobjects for the fences are only marked as
	 * freed when the slab cache itself is freed, and so we would get
	 * caught trying to reuse dead objects.
	 */
	i915_sw_fence_fini(&rq->submit);
	i915_sw_fence_fini(&rq->semaphore);

	/*
	 * Keep one request on each engine for reserved use under mempressure.
	 *
	 * We do not hold a reference to the engine here and so have to be
	 * very careful in what rq->engine we poke. The virtual engine is
	 * referenced via the rq->context and we released that ref during
	 * i915_request_retire(), ergo we must not dereference a virtual

Annotation

Implementation Notes