[PATCH v3 22/25] drm/xe: Add ULLS migration job support to ring ops

Matthew Brost
2026-02-28T01:35:33Z

Add preamble and postamble for ULLS migrations jobs. Preamble clears
current semaphore for reuse. Postamble waits on next semaphore which is
set upon next job submission. The last ULLS migration job skips BB
submission and postamble (clear current semaphore, write seqno, exit
ULLS).

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/xe/xe_ring_ops.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index 53d420d72164..4e233651beb9 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -422,6 +422,27 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
xe_lrc_write_ring(lrc, dw, i * sizeof(*dw));
}

+static int emit_ulls_preamble(struct xe_lrc *lrc, u32 *dw, int i, u32 seqno)
+{
+ u32 addr = xe_lrc_ulls_semaphore_ggtt_addr(lrc, seqno);
+
+ return emit_store_imm_ggtt(addr, LRC_MIGRATION_ULLS_SEMAPORE_CLEAR,
+ dw, i);
+}
+
+static int emit_ulls_postamble(struct xe_lrc *lrc, u32 *dw, int i, u32 seqno)
+{
+ dw[i++] = MI_SEMAPHORE_WAIT |
+ MI_SEMAPHORE_GLOBAL_GTT |
+ MI_SEMAPHORE_POLL |
+ MI_SEMAPHORE_SAD_EQ_SDD;
+ dw[i++] = LRC_MIGRATION_ULLS_SEMAPORE_SINGAL;
+ dw[i++] = xe_lrc_ulls_semaphore_ggtt_addr(lrc, seqno + 1);
+ dw[i++] = 0;
+
+ return i;
+}
+
static void emit_migration_job_gen12(struct xe_sched_job *job,
struct xe_lrc *lrc, u32 *head,
u32 seqno)
@@ -433,10 +454,16 @@ static void emit_migration_job_gen12(struct xe_sched_job *job,

*head = lrc->ring.tail;

+ if (job->is_ulls)
+ i = emit_ulls_preamble(lrc, dw, i, seqno);
+
i = emit_copy_timestamp(xe, lrc, dw, i);

i = emit_store_imm_ggtt(saddr, seqno, dw, i);

+ if (job->is_ulls_last || job->is_ulls_first)
+ goto seqno_write;
+
dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE; /* Enabled again below */

i = emit_bb_start(job->ptrs[0].batch_addr, BIT(8), dw, i);
@@ -447,12 +474,16 @@ static void emit_migration_job_gen12(struct xe_sched_job *job,

i = emit_bb_start(job->ptrs[1].batch_addr, BIT(8), dw, i);

+seqno_write:
i = emit_flush_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno,
job->migrate_flush_flags,
dw, i);

i = emit_user_interrupt(dw, i);

+ if (job->is_ulls && !job->is_ulls_last)
+ i = emit_ulls_postamble(lrc, dw, i, seqno);
+
xe_gt_assert(job->q->gt, i <= MAX_JOB_SIZE_DW);

xe_lrc_write_ring(lrc, dw, i * sizeof(*dw));
--
2.34.1