drivers/gpu/drm/i915/gvt/scheduler.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gvt/scheduler.c
Extension
.c
Size
49755 bytes
Lines
1796
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 (context_gpa == INTEL_GVT_INVALID_ADDR) {
			gvt_vgpu_err("Invalid guest context descriptor\n");
			return -EFAULT;
		}

		if (gpa_size == 0) {
			gpa_base = context_gpa;
			dst = context_base + (i << I915_GTT_PAGE_SHIFT);
		} else if (context_gpa != gpa_base + gpa_size)
			goto read;

		gpa_size += I915_GTT_PAGE_SIZE;

		if (i == context_page_num - 1)
			goto read;

		continue;

read:
		intel_gvt_read_gpa(vgpu, gpa_base, dst, gpa_size);
		gpa_base = context_gpa;
		gpa_size = I915_GTT_PAGE_SIZE;
		dst = context_base + (i << I915_GTT_PAGE_SHIFT);
	}
	ret = intel_gvt_scan_engine_context(workload);
	if (ret) {
		gvt_vgpu_err("invalid cmd found in guest context pages\n");
		return ret;
	}
	s->last_ctx[ring_id].valid = true;
	return 0;
}

static inline bool is_gvt_request(struct i915_request *rq)
{
	return intel_context_force_single_submission(rq->context);
}

static void save_ring_hw_state(struct intel_vgpu *vgpu,
			       const struct intel_engine_cs *engine)
{
	struct intel_uncore *uncore = engine->uncore;
	i915_reg_t reg;

	reg = RING_INSTDONE(engine->mmio_base);
	vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
		intel_uncore_read(uncore, reg);

	reg = RING_ACTHD(engine->mmio_base);
	vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
		intel_uncore_read(uncore, reg);

	reg = RING_ACTHD_UDW(engine->mmio_base);
	vgpu_vreg(vgpu, i915_mmio_reg_offset(reg)) =
		intel_uncore_read(uncore, reg);
}

static int shadow_context_status_change(struct notifier_block *nb,
		unsigned long action, void *data)
{
	struct i915_request *rq = data;
	struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
				shadow_ctx_notifier_block[rq->engine->id]);
	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
	enum intel_engine_id ring_id = rq->engine->id;
	struct intel_vgpu_workload *workload;
	unsigned long flags;

	if (!is_gvt_request(rq)) {
		spin_lock_irqsave(&scheduler->mmio_context_lock, flags);
		if (action == INTEL_CONTEXT_SCHEDULE_IN &&
		    scheduler->engine_owner[ring_id]) {
			/* Switch ring from vGPU to host. */
			intel_gvt_switch_mmio(scheduler->engine_owner[ring_id],
					      NULL, rq->engine);
			scheduler->engine_owner[ring_id] = NULL;
		}
		spin_unlock_irqrestore(&scheduler->mmio_context_lock, flags);

		return NOTIFY_OK;
	}

	workload = scheduler->current_workload[ring_id];
	if (unlikely(!workload))
		return NOTIFY_OK;

	switch (action) {
	case INTEL_CONTEXT_SCHEDULE_IN:
		spin_lock_irqsave(&scheduler->mmio_context_lock, flags);
		if (workload->vgpu != scheduler->engine_owner[ring_id]) {

Annotation

Implementation Notes