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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
Extension
.c
Size
127071 bytes
Lines
4177
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 virtual_engine {
	struct intel_engine_cs base;
	struct intel_context context;
	struct rcu_work rcu;

	/*
	 * We allow only a single request through the virtual engine at a time
	 * (each request in the timeline waits for the completion fence of
	 * the previous before being submitted). By restricting ourselves to
	 * only submitting a single request, each request is placed on to a
	 * physical to maximise load spreading (by virtue of the late greedy
	 * scheduling -- each real engine takes the next available request
	 * upon idling).
	 */
	struct i915_request *request;

	/*
	 * We keep a rbtree of available virtual engines inside each physical
	 * engine, sorted by priority. Here we preallocate the nodes we need
	 * for the virtual engine, indexed by physical_engine->id.
	 */
	struct ve_node {
		struct rb_node rb;
		int prio;
	} nodes[I915_NUM_ENGINES];

	/* And finally, which physical engines this virtual engine maps onto. */
	unsigned int num_siblings;
	struct intel_engine_cs *siblings[];
};

static struct virtual_engine *to_virtual_engine(struct intel_engine_cs *engine)
{
	GEM_BUG_ON(!intel_engine_is_virtual(engine));
	return container_of(engine, struct virtual_engine, base);
}

static struct intel_context *
execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
			 unsigned long flags);

static struct i915_request *
__active_request(const struct intel_timeline * const tl,
		 struct i915_request *rq,
		 int error)
{
	struct i915_request *active = rq;

	list_for_each_entry_from_reverse(rq, &tl->requests, link) {
		if (__i915_request_is_complete(rq))
			break;

		if (error) {
			i915_request_set_error_once(rq, error);
			__i915_request_skip(rq);
		}
		active = rq;
	}

	return active;
}

static struct i915_request *
active_request(const struct intel_timeline * const tl, struct i915_request *rq)
{
	return __active_request(tl, rq, 0);
}

static void ring_set_paused(const struct intel_engine_cs *engine, int state)
{
	/*
	 * We inspect HWS_PREEMPT with a semaphore inside
	 * engine->emit_fini_breadcrumb. If the dword is true,
	 * the ring is paused as the semaphore will busywait
	 * until the dword is false.
	 */
	engine->status_page.addr[I915_GEM_HWS_PREEMPT] = state;
	if (state)
		wmb();
}

static struct i915_priolist *to_priolist(struct rb_node *rb)
{
	return rb_entry(rb, struct i915_priolist, node);
}

static int rq_prio(const struct i915_request *rq)
{
	return READ_ONCE(rq->sched.attr.priority);
}

Annotation

Implementation Notes