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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
Extension
.c
Size
11225 bytes
Lines
430
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 (!i915_sw_fence_signaled(&rq->submit)) {
			/*
			 * Not yet submitted, system is stalled.
			 *
			 * This more often happens for ring submission,
			 * where all contexts are funnelled into a common
			 * ringbuffer. If one context is blocked on an
			 * external fence, not only is it not submitted,
			 * but all other contexts, including the kernel
			 * context are stuck waiting for the signal.
			 */
		} else if (engine->sched_engine->schedule &&
			   rq->sched.attr.priority < I915_PRIORITY_BARRIER) {
			/*
			 * Gradually raise the priority of the heartbeat to
			 * give high priority work [which presumably desires
			 * low latency and no jitter] the chance to naturally
			 * complete before being preempted.
			 */
			attr.priority = I915_PRIORITY_NORMAL;
			if (rq->sched.attr.priority >= attr.priority)
				attr.priority = I915_PRIORITY_HEARTBEAT;
			if (rq->sched.attr.priority >= attr.priority)
				attr.priority = I915_PRIORITY_BARRIER;

			local_bh_disable();
			engine->sched_engine->schedule(rq, &attr);
			local_bh_enable();
		} else {
			reset_engine(engine, rq);
		}

		rq->emitted_jiffies = jiffies;
		goto out;
	}

	serial = READ_ONCE(engine->serial);
	if (engine->wakeref_serial == serial)
		goto out;

	if (!mutex_trylock(&ce->timeline->mutex)) {
		/* Unable to lock the kernel timeline, is the engine stuck? */
		if (xchg(&engine->heartbeat.blocked, serial) == serial)
			intel_gt_handle_error(engine->gt, engine->mask,
					      I915_ERROR_CAPTURE,
					      "no heartbeat on %s",
					      engine->name);
		goto out;
	}

	rq = heartbeat_create(ce, GFP_NOWAIT | __GFP_NOWARN);
	if (IS_ERR(rq))
		goto unlock;

	heartbeat_commit(rq, &attr);

unlock:
	mutex_unlock(&ce->timeline->mutex);
out:
	if (!engine->i915->params.enable_hangcheck || !next_heartbeat(engine)) {
		rq = xchg(&engine->heartbeat.systole, NULL);
		if (rq)
			i915_request_put(rq);
	}
	intel_engine_pm_put(engine);
}

void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine)
{
	if (!CONFIG_DRM_I915_HEARTBEAT_INTERVAL)
		return;

	next_heartbeat(engine);
}

void intel_engine_park_heartbeat(struct intel_engine_cs *engine)
{
	if (cancel_delayed_work(&engine->heartbeat.work)) {
		struct i915_request *rq;

		rq = xchg(&engine->heartbeat.systole, NULL);
		if (rq)
			i915_request_put(rq);
	}
}

void intel_gt_unpark_heartbeats(struct intel_gt *gt)
{
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

Annotation

Implementation Notes