drivers/gpu/drm/xe/xe_gt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_gt.c
Extension
.c
Size
26580 bytes
Lines
1187
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (xe_gt_is_media_type(gt)) {
			xe_mmio_rmw32(&gt->mmio, XE2_GAMWALK_CTRL_MEDIA, 0, EN_CMP_1WCOH_GW);
		} else {
			reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMWALK_CTRL_3D);
			reg |= EN_CMP_1WCOH_GW;
			xe_gt_mcr_multicast_write(gt, XE2_GAMWALK_CTRL_3D, reg);
		}
	}
}

static void gt_reset_worker(struct work_struct *w);

static int emit_job_sync(struct xe_exec_queue *q, struct xe_bb *bb,
			 long timeout_jiffies, bool force_reset)
{
	struct xe_sched_job *job;
	struct dma_fence *fence;
	long timeout;

	job = xe_bb_create_job(q, bb);
	if (IS_ERR(job))
		return PTR_ERR(job);

	job->ring_ops_force_reset = force_reset;

	xe_sched_job_arm(job);
	fence = dma_fence_get(&job->drm.s_fence->finished);
	xe_sched_job_push(job);

	timeout = dma_fence_wait_timeout(fence, false, timeout_jiffies);
	dma_fence_put(fence);
	if (timeout < 0)
		return timeout;
	else if (!timeout)
		return -ETIME;

	return 0;
}

static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q)
{
	struct xe_bb *bb;
	int ret;

	bb = xe_bb_new(gt, 4, false);
	if (IS_ERR(bb))
		return PTR_ERR(bb);

	ret = emit_job_sync(q, bb, HZ, false);
	xe_bb_free(bb, NULL);

	return ret;
}

/* Dwords required to emit a RMW of a register */
#define EMIT_RMW_DW 20

static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
{
	struct xe_hw_engine *hwe = q->hwe;
	struct xe_reg_sr *sr = &hwe->reg_lrc;
	struct xe_reg_sr_entry *entry;
	int count_rmw = 0, count_rmw_mcr = 0, count = 0, ret;
	unsigned long idx;
	struct xe_bb *bb;
	size_t bb_len = 0;
	u32 *cs;

	/* count RMW registers as those will be handled separately */
	xa_for_each(&sr->xa, idx, entry) {
		if (entry->reg.masked || entry->clr_bits == ~0)
			++count;
		else if (entry->reg.mcr)
			++count_rmw_mcr;
		else
			++count_rmw;
	}

	if (count)
		bb_len += count * 2 + 1;

	/*
	 * RMW of MCR registers is the same as a normal RMW, except an
	 * additional LRI (3 dwords) is required per register to steer the read
	 * to a nom-terminated instance.
	 *
	 * We could probably shorten the batch slightly by eliding the
	 * steering for consecutive MCR registers that have the same
	 * group/instance target, but it's not worth the extra complexity to do
	 * so.

Annotation

Implementation Notes