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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_engine_pm.c
Extension
.c
Size
10022 bytes
Lines
329
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

if (!IS_ERR(map)) {
			memset(map, CONTEXT_REDZONE, obj->base.size);
			i915_gem_object_flush_map(obj);
			i915_gem_object_unpin_map(obj);
		}
		i915_gem_object_unlock(obj);
	}
}

static int __engine_unpark(struct intel_wakeref *wf)
{
	struct intel_engine_cs *engine =
		container_of(wf, typeof(*engine), wakeref);
	struct intel_context *ce;

	ENGINE_TRACE(engine, "\n");

	engine->wakeref_track = intel_gt_pm_get(engine->gt);

	/* Discard stale context state from across idling */
	ce = engine->kernel_context;
	if (ce) {
		GEM_BUG_ON(test_bit(CONTEXT_VALID_BIT, &ce->flags));

		/* Flush all pending HW writes before we touch the context */
		while (unlikely(intel_context_inflight(ce)))
			intel_engine_flush_submission(engine);

		/* First poison the image to verify we never fully trust it */
		dbg_poison_ce(ce);

		/* Scrub the context image after our loss of control */
		ce->ops->reset(ce);

		CE_TRACE(ce, "reset { seqno:%x, *hwsp:%x, ring:%x }\n",
			 ce->timeline->seqno,
			 READ_ONCE(*ce->timeline->hwsp_seqno),
			 ce->ring->emit);
		GEM_BUG_ON(ce->timeline->seqno !=
			   READ_ONCE(*ce->timeline->hwsp_seqno));
	}

	if (engine->unpark)
		engine->unpark(engine);

	intel_breadcrumbs_unpark(engine->breadcrumbs);
	intel_engine_unpark_heartbeat(engine);
	return 0;
}

static void duration(struct dma_fence *fence, struct dma_fence_cb *cb)
{
	struct i915_request *rq = to_request(fence);

	ewma__engine_latency_add(&rq->engine->latency,
				 ktime_us_delta(rq->fence.timestamp,
						rq->duration.emitted));
}

static void
__queue_and_release_pm(struct i915_request *rq,
		       struct intel_timeline *tl,
		       struct intel_engine_cs *engine)
{
	struct intel_gt_timelines *timelines = &engine->gt->timelines;

	ENGINE_TRACE(engine, "parking\n");

	/*
	 * Open coded one half of intel_context_enter, which we have to omit
	 * here (see the large comment below) and because the other part must
	 * not be called due constructing directly with __i915_request_create
	 * which increments active count via intel_context_mark_active.
	 */
	GEM_BUG_ON(rq->context->active_count != 1);
	__intel_gt_pm_get(engine->gt);
	rq->context->wakeref = intel_wakeref_track(&engine->gt->wakeref);

	/*
	 * We have to serialise all potential retirement paths with our
	 * submission, as we don't want to underflow either the
	 * engine->wakeref.counter or our timeline->active_count.
	 *
	 * Equally, we cannot allow a new submission to start until
	 * after we finish queueing, nor could we allow that submitter
	 * to retire us before we are ready!
	 */
	spin_lock(&timelines->lock);

	/* Let intel_gt_retire_requests() retire us (acquired under lock) */

Annotation

Implementation Notes