drivers/gpu/drm/xe/xe_execlist.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_execlist.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_execlist.c
Extension
.c
Size
12209 bytes
Lines
492
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

while (!list_empty(&port->active[i])) {
			exl = list_first_entry(&port->active[i],
					       struct xe_execlist_exec_queue,
					       active_link);
			list_del(&exl->active_link);

			if (xe_execlist_is_idle(exl)) {
				exl->active_priority = XE_EXEC_QUEUE_PRIORITY_UNSET;
				continue;
			}

			list_add_tail(&exl->active_link, &port->active[i]);
			__xe_execlist_port_start(port, exl);
			return;
		}
	}

	__xe_execlist_port_idle(port);
}

static u64 read_execlist_status(struct xe_hw_engine *hwe)
{
	struct xe_gt *gt = hwe->gt;
	u32 hi, lo;

	lo = xe_mmio_read32(&gt->mmio, RING_EXECLIST_STATUS_LO(hwe->mmio_base));
	hi = xe_mmio_read32(&gt->mmio, RING_EXECLIST_STATUS_HI(hwe->mmio_base));

	return lo | (u64)hi << 32;
}

static void xe_execlist_port_irq_handler_locked(struct xe_execlist_port *port)
{
	u64 status;

	xe_execlist_port_assert_held(port);

	status = read_execlist_status(port->hwe);
	if (status & BIT(7))
		return;

	__xe_execlist_port_start_next_active(port);
}

static void xe_execlist_port_irq_handler(struct xe_hw_engine *hwe,
					 u16 intr_vec)
{
	struct xe_execlist_port *port = hwe->exl_port;

	spin_lock(&port->lock);
	xe_execlist_port_irq_handler_locked(port);
	spin_unlock(&port->lock);
}

static void xe_execlist_port_wake_locked(struct xe_execlist_port *port,
					 enum xe_exec_queue_priority priority)
{
	xe_execlist_port_assert_held(port);

	if (port->running_exl && port->running_exl->active_priority >= priority)
		return;

	__xe_execlist_port_start_next_active(port);
}

static void xe_execlist_make_active(struct xe_execlist_exec_queue *exl)
{
	struct xe_execlist_port *port = exl->port;
	enum xe_exec_queue_priority priority = exl->q->sched_props.priority;

	XE_WARN_ON(priority == XE_EXEC_QUEUE_PRIORITY_UNSET);
	XE_WARN_ON(priority < 0);
	XE_WARN_ON(priority >= ARRAY_SIZE(exl->port->active));

	spin_lock_irq(&port->lock);

	if (exl->active_priority != priority &&
	    exl->active_priority != XE_EXEC_QUEUE_PRIORITY_UNSET) {
		/* Priority changed, move it to the right list */
		list_del(&exl->active_link);
		exl->active_priority = XE_EXEC_QUEUE_PRIORITY_UNSET;
	}

	if (exl->active_priority == XE_EXEC_QUEUE_PRIORITY_UNSET) {
		exl->active_priority = priority;
		list_add_tail(&exl->active_link, &port->active[priority]);
	}

	xe_execlist_port_wake_locked(exl->port, priority);

Annotation

Implementation Notes