Commit 264eecdb authored by Niranjana Vishwanathapura's avatar Niranjana Vishwanathapura Committed by Matthew Brost

drm/xe: Decouple xe_exec_queue and xe_lrc

Decouple xe_lrc from xe_exec_queue and reference count xe_lrc.
Removing hard coupling between xe_exec_queue and xe_lrc allows
flexible design where the user interface xe_exec_queue can be
destroyed independent of the hardware/firmware interface xe_lrc.

v2: Fix lrc indexing in wq_item_append()
Signed-off-by: default avatarNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: default avatarMatthew Brost <matthew.brost@intel.com>
Signed-off-by: default avatarMatthew Brost <matthew.brost@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240530032211.29299-1-niranjana.vishwanathapura@intel.com
parent 0568a408
...@@ -86,7 +86,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, ...@@ -86,7 +86,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
if (extensions) { if (extensions) {
/* /*
* may set q->usm, must come before xe_lrc_init(), * may set q->usm, must come before xe_lrc_create(),
* may overwrite q->sched_props, must come before q->ops->init() * may overwrite q->sched_props, must come before q->ops->init()
*/ */
err = exec_queue_user_extensions(xe, q, extensions, 0); err = exec_queue_user_extensions(xe, q, extensions, 0);
...@@ -104,10 +104,12 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) ...@@ -104,10 +104,12 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
int i, err; int i, err;
for (i = 0; i < q->width; ++i) { for (i = 0; i < q->width; ++i) {
err = xe_lrc_init(q->lrc + i, q->hwe, q, q->vm, SZ_16K); q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K);
if (err) if (IS_ERR(q->lrc[i])) {
err = PTR_ERR(q->lrc[i]);
goto err_lrc; goto err_lrc;
} }
}
err = q->ops->init(q); err = q->ops->init(q);
if (err) if (err)
...@@ -117,7 +119,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) ...@@ -117,7 +119,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
err_lrc: err_lrc:
for (i = i - 1; i >= 0; --i) for (i = i - 1; i >= 0; --i)
xe_lrc_finish(q->lrc + i); xe_lrc_put(q->lrc[i]);
return err; return err;
} }
...@@ -198,7 +200,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q) ...@@ -198,7 +200,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
int i; int i;
for (i = 0; i < q->width; ++i) for (i = 0; i < q->width; ++i)
xe_lrc_finish(q->lrc + i); xe_lrc_put(q->lrc[i]);
__xe_exec_queue_free(q); __xe_exec_queue_free(q);
} }
...@@ -701,7 +703,7 @@ bool xe_exec_queue_is_lr(struct xe_exec_queue *q) ...@@ -701,7 +703,7 @@ bool xe_exec_queue_is_lr(struct xe_exec_queue *q)
static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q) static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q)
{ {
return q->lrc->fence_ctx.next_seqno - xe_lrc_seqno(q->lrc) - 1; return q->lrc[0]->fence_ctx.next_seqno - xe_lrc_seqno(q->lrc[0]) - 1;
} }
/** /**
...@@ -712,7 +714,7 @@ static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q) ...@@ -712,7 +714,7 @@ static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q)
*/ */
bool xe_exec_queue_ring_full(struct xe_exec_queue *q) bool xe_exec_queue_ring_full(struct xe_exec_queue *q)
{ {
struct xe_lrc *lrc = q->lrc; struct xe_lrc *lrc = q->lrc[0];
s32 max_job = lrc->ring.size / MAX_JOB_SIZE_BYTES; s32 max_job = lrc->ring.size / MAX_JOB_SIZE_BYTES;
return xe_exec_queue_num_job_inflight(q) >= max_job; return xe_exec_queue_num_job_inflight(q) >= max_job;
...@@ -738,16 +740,16 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q) ...@@ -738,16 +740,16 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q)
int i; int i;
for (i = 0; i < q->width; ++i) { for (i = 0; i < q->width; ++i) {
if (xe_lrc_seqno(&q->lrc[i]) != if (xe_lrc_seqno(q->lrc[i]) !=
q->lrc[i].fence_ctx.next_seqno - 1) q->lrc[i]->fence_ctx.next_seqno - 1)
return false; return false;
} }
return true; return true;
} }
return xe_lrc_seqno(&q->lrc[0]) == return xe_lrc_seqno(q->lrc[0]) ==
q->lrc[0].fence_ctx.next_seqno - 1; q->lrc[0]->fence_ctx.next_seqno - 1;
} }
/** /**
...@@ -779,7 +781,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) ...@@ -779,7 +781,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
* the LRCs and reading them in different time could also introduce * the LRCs and reading them in different time could also introduce
* errors. * errors.
*/ */
lrc = &q->lrc[0]; lrc = q->lrc[0];
new_ts = xe_lrc_update_timestamp(lrc, &old_ts); new_ts = xe_lrc_update_timestamp(lrc, &old_ts);
q->run_ticks += (new_ts - old_ts) * q->width; q->run_ticks += (new_ts - old_ts) * q->width;
} }
......
...@@ -146,7 +146,7 @@ struct xe_exec_queue { ...@@ -146,7 +146,7 @@ struct xe_exec_queue {
/** @run_ticks: hw engine class run time in ticks for this exec queue */ /** @run_ticks: hw engine class run time in ticks for this exec queue */
u64 run_ticks; u64 run_ticks;
/** @lrc: logical ring context for this exec queue */ /** @lrc: logical ring context for this exec queue */
struct xe_lrc lrc[]; struct xe_lrc *lrc[];
}; };
/** /**
......
...@@ -109,7 +109,7 @@ static void __xe_execlist_port_start(struct xe_execlist_port *port, ...@@ -109,7 +109,7 @@ static void __xe_execlist_port_start(struct xe_execlist_port *port,
port->last_ctx_id = 1; port->last_ctx_id = 1;
} }
__start_lrc(port->hwe, exl->q->lrc, port->last_ctx_id); __start_lrc(port->hwe, exl->q->lrc[0], port->last_ctx_id);
port->running_exl = exl; port->running_exl = exl;
exl->has_run = true; exl->has_run = true;
} }
...@@ -123,14 +123,14 @@ static void __xe_execlist_port_idle(struct xe_execlist_port *port) ...@@ -123,14 +123,14 @@ static void __xe_execlist_port_idle(struct xe_execlist_port *port)
if (!port->running_exl) if (!port->running_exl)
return; return;
xe_lrc_write_ring(&port->hwe->kernel_lrc, noop, sizeof(noop)); xe_lrc_write_ring(port->hwe->kernel_lrc, noop, sizeof(noop));
__start_lrc(port->hwe, &port->hwe->kernel_lrc, 0); __start_lrc(port->hwe, port->hwe->kernel_lrc, 0);
port->running_exl = NULL; port->running_exl = NULL;
} }
static bool xe_execlist_is_idle(struct xe_execlist_exec_queue *exl) static bool xe_execlist_is_idle(struct xe_execlist_exec_queue *exl)
{ {
struct xe_lrc *lrc = exl->q->lrc; struct xe_lrc *lrc = exl->q->lrc[0];
return lrc->ring.tail == lrc->ring.old_tail; return lrc->ring.tail == lrc->ring.old_tail;
} }
...@@ -333,7 +333,7 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q) ...@@ -333,7 +333,7 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q)
exl->q = q; exl->q = q;
err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1,
q->lrc[0].ring.size / MAX_JOB_SIZE_BYTES, q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES,
XE_SCHED_HANG_LIMIT, XE_SCHED_JOB_TIMEOUT, XE_SCHED_HANG_LIMIT, XE_SCHED_JOB_TIMEOUT,
NULL, NULL, q->hwe->name, NULL, NULL, q->hwe->name,
gt_to_xe(q->gt)->drm.dev); gt_to_xe(q->gt)->drm.dev);
......
...@@ -297,8 +297,8 @@ int xe_gt_record_default_lrcs(struct xe_gt *gt) ...@@ -297,8 +297,8 @@ int xe_gt_record_default_lrcs(struct xe_gt *gt)
} }
xe_map_memcpy_from(xe, default_lrc, xe_map_memcpy_from(xe, default_lrc,
&q->lrc[0].bo->vmap, &q->lrc[0]->bo->vmap,
xe_lrc_pphwsp_offset(&q->lrc[0]), xe_lrc_pphwsp_offset(q->lrc[0]),
xe_gt_lrc_size(gt, hwe->class)); xe_gt_lrc_size(gt, hwe->class));
gt->default_lrc[hwe->class] = default_lrc; gt->default_lrc[hwe->class] = default_lrc;
......
...@@ -490,7 +490,7 @@ static void __register_mlrc_exec_queue(struct xe_guc *guc, ...@@ -490,7 +490,7 @@ static void __register_mlrc_exec_queue(struct xe_guc *guc,
action[len++] = info->hwlrca_hi; action[len++] = info->hwlrca_hi;
for (i = 1; i < q->width; ++i) { for (i = 1; i < q->width; ++i) {
struct xe_lrc *lrc = q->lrc + i; struct xe_lrc *lrc = q->lrc[i];
action[len++] = lower_32_bits(xe_lrc_descriptor(lrc)); action[len++] = lower_32_bits(xe_lrc_descriptor(lrc));
action[len++] = upper_32_bits(xe_lrc_descriptor(lrc)); action[len++] = upper_32_bits(xe_lrc_descriptor(lrc));
...@@ -527,7 +527,7 @@ static void register_exec_queue(struct xe_exec_queue *q) ...@@ -527,7 +527,7 @@ static void register_exec_queue(struct xe_exec_queue *q)
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct xe_lrc *lrc = q->lrc; struct xe_lrc *lrc = q->lrc[0];
struct guc_ctxt_registration_info info; struct guc_ctxt_registration_info info;
xe_assert(xe, !exec_queue_registered(q)); xe_assert(xe, !exec_queue_registered(q));
...@@ -586,7 +586,7 @@ static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size) ...@@ -586,7 +586,7 @@ static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size)
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct iosys_map map = xe_lrc_parallel_map(q->lrc); struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]);
unsigned int sleep_period_ms = 1; unsigned int sleep_period_ms = 1;
#define AVAILABLE_SPACE \ #define AVAILABLE_SPACE \
...@@ -614,7 +614,7 @@ static int wq_noop_append(struct xe_exec_queue *q) ...@@ -614,7 +614,7 @@ static int wq_noop_append(struct xe_exec_queue *q)
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct iosys_map map = xe_lrc_parallel_map(q->lrc); struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]);
u32 len_dw = wq_space_until_wrap(q) / sizeof(u32) - 1; u32 len_dw = wq_space_until_wrap(q) / sizeof(u32) - 1;
if (wq_wait_for_space(q, wq_space_until_wrap(q))) if (wq_wait_for_space(q, wq_space_until_wrap(q)))
...@@ -634,7 +634,7 @@ static void wq_item_append(struct xe_exec_queue *q) ...@@ -634,7 +634,7 @@ static void wq_item_append(struct xe_exec_queue *q)
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct iosys_map map = xe_lrc_parallel_map(q->lrc); struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]);
#define WQ_HEADER_SIZE 4 /* Includes 1 LRC address too */ #define WQ_HEADER_SIZE 4 /* Includes 1 LRC address too */
u32 wqi[XE_HW_ENGINE_MAX_INSTANCE + (WQ_HEADER_SIZE - 1)]; u32 wqi[XE_HW_ENGINE_MAX_INSTANCE + (WQ_HEADER_SIZE - 1)];
u32 wqi_size = (q->width + (WQ_HEADER_SIZE - 1)) * sizeof(u32); u32 wqi_size = (q->width + (WQ_HEADER_SIZE - 1)) * sizeof(u32);
...@@ -650,12 +650,12 @@ static void wq_item_append(struct xe_exec_queue *q) ...@@ -650,12 +650,12 @@ static void wq_item_append(struct xe_exec_queue *q)
wqi[i++] = FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_MULTI_LRC) | wqi[i++] = FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_MULTI_LRC) |
FIELD_PREP(WQ_LEN_MASK, len_dw); FIELD_PREP(WQ_LEN_MASK, len_dw);
wqi[i++] = xe_lrc_descriptor(q->lrc); wqi[i++] = xe_lrc_descriptor(q->lrc[0]);
wqi[i++] = FIELD_PREP(WQ_GUC_ID_MASK, q->guc->id) | wqi[i++] = FIELD_PREP(WQ_GUC_ID_MASK, q->guc->id) |
FIELD_PREP(WQ_RING_TAIL_MASK, q->lrc->ring.tail / sizeof(u64)); FIELD_PREP(WQ_RING_TAIL_MASK, q->lrc[0]->ring.tail / sizeof(u64));
wqi[i++] = 0; wqi[i++] = 0;
for (j = 1; j < q->width; ++j) { for (j = 1; j < q->width; ++j) {
struct xe_lrc *lrc = q->lrc + j; struct xe_lrc *lrc = q->lrc[j];
wqi[i++] = lrc->ring.tail / sizeof(u64); wqi[i++] = lrc->ring.tail / sizeof(u64);
} }
...@@ -670,7 +670,7 @@ static void wq_item_append(struct xe_exec_queue *q) ...@@ -670,7 +670,7 @@ static void wq_item_append(struct xe_exec_queue *q)
xe_device_wmb(xe); xe_device_wmb(xe);
map = xe_lrc_parallel_map(q->lrc); map = xe_lrc_parallel_map(q->lrc[0]);
parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail); parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail);
} }
...@@ -679,7 +679,7 @@ static void submit_exec_queue(struct xe_exec_queue *q) ...@@ -679,7 +679,7 @@ static void submit_exec_queue(struct xe_exec_queue *q)
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct xe_lrc *lrc = q->lrc; struct xe_lrc *lrc = q->lrc[0];
u32 action[3]; u32 action[3];
u32 g2h_len = 0; u32 g2h_len = 0;
u32 num_g2h = 0; u32 num_g2h = 0;
...@@ -1236,7 +1236,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) ...@@ -1236,7 +1236,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
msecs_to_jiffies(q->sched_props.job_timeout_ms); msecs_to_jiffies(q->sched_props.job_timeout_ms);
err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops, err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
get_submit_wq(guc), get_submit_wq(guc),
q->lrc[0].ring.size / MAX_JOB_SIZE_BYTES, 64, q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, 64,
timeout, guc_to_gt(guc)->ordered_wq, NULL, timeout, guc_to_gt(guc)->ordered_wq, NULL,
q->name, gt_to_xe(q->gt)->drm.dev); q->name, gt_to_xe(q->gt)->drm.dev);
if (err) if (err)
...@@ -1464,7 +1464,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) ...@@ -1464,7 +1464,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
ban = true; ban = true;
} }
} else if (xe_exec_queue_is_lr(q) && } else if (xe_exec_queue_is_lr(q) &&
(xe_lrc_ring_head(q->lrc) != xe_lrc_ring_tail(q->lrc))) { (xe_lrc_ring_head(q->lrc[0]) != xe_lrc_ring_tail(q->lrc[0]))) {
ban = true; ban = true;
} }
...@@ -1529,7 +1529,7 @@ static void guc_exec_queue_start(struct xe_exec_queue *q) ...@@ -1529,7 +1529,7 @@ static void guc_exec_queue_start(struct xe_exec_queue *q)
trace_xe_exec_queue_resubmit(q); trace_xe_exec_queue_resubmit(q);
for (i = 0; i < q->width; ++i) for (i = 0; i < q->width; ++i)
xe_lrc_set_ring_head(q->lrc + i, q->lrc[i].ring.tail); xe_lrc_set_ring_head(q->lrc[i], q->lrc[i]->ring.tail);
xe_sched_resubmit_jobs(sched); xe_sched_resubmit_jobs(sched);
} }
...@@ -1775,7 +1775,7 @@ guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q, ...@@ -1775,7 +1775,7 @@ guc_exec_queue_wq_snapshot_capture(struct xe_exec_queue *q,
{ {
struct xe_guc *guc = exec_queue_to_guc(q); struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc); struct xe_device *xe = guc_to_xe(guc);
struct iosys_map map = xe_lrc_parallel_map(q->lrc); struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]);
int i; int i;
snapshot->guc.wqi_head = q->guc->wqi_head; snapshot->guc.wqi_head = q->guc->wqi_head;
...@@ -1855,7 +1855,7 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q) ...@@ -1855,7 +1855,7 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q)
if (snapshot->lrc) { if (snapshot->lrc) {
for (i = 0; i < q->width; ++i) { for (i = 0; i < q->width; ++i) {
struct xe_lrc *lrc = q->lrc + i; struct xe_lrc *lrc = q->lrc[i];
snapshot->lrc[i] = xe_lrc_snapshot_capture(lrc); snapshot->lrc[i] = xe_lrc_snapshot_capture(lrc);
} }
......
...@@ -268,7 +268,7 @@ static void hw_engine_fini(struct drm_device *drm, void *arg) ...@@ -268,7 +268,7 @@ static void hw_engine_fini(struct drm_device *drm, void *arg)
if (hwe->exl_port) if (hwe->exl_port)
xe_execlist_port_destroy(hwe->exl_port); xe_execlist_port_destroy(hwe->exl_port);
xe_lrc_finish(&hwe->kernel_lrc); xe_lrc_put(hwe->kernel_lrc);
hwe->gt = NULL; hwe->gt = NULL;
} }
...@@ -527,9 +527,11 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe, ...@@ -527,9 +527,11 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
goto err_name; goto err_name;
} }
err = xe_lrc_init(&hwe->kernel_lrc, hwe, NULL, NULL, SZ_16K); hwe->kernel_lrc = xe_lrc_create(hwe, NULL, SZ_16K);
if (err) if (IS_ERR(hwe->kernel_lrc)) {
err = PTR_ERR(hwe->kernel_lrc);
goto err_hwsp; goto err_hwsp;
}
if (!xe_device_uc_enabled(xe)) { if (!xe_device_uc_enabled(xe)) {
hwe->exl_port = xe_execlist_port_create(xe, hwe); hwe->exl_port = xe_execlist_port_create(xe, hwe);
...@@ -554,7 +556,7 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe, ...@@ -554,7 +556,7 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
return drmm_add_action_or_reset(&xe->drm, hw_engine_fini, hwe); return drmm_add_action_or_reset(&xe->drm, hw_engine_fini, hwe);
err_kernel_lrc: err_kernel_lrc:
xe_lrc_finish(&hwe->kernel_lrc); xe_lrc_put(hwe->kernel_lrc);
err_hwsp: err_hwsp:
xe_bo_unpin_map_no_vm(hwe->hwsp); xe_bo_unpin_map_no_vm(hwe->hwsp);
err_name: err_name:
......
...@@ -137,7 +137,7 @@ struct xe_hw_engine { ...@@ -137,7 +137,7 @@ struct xe_hw_engine {
/** @hwsp: hardware status page buffer object */ /** @hwsp: hardware status page buffer object */
struct xe_bo *hwsp; struct xe_bo *hwsp;
/** @kernel_lrc: Kernel LRC (should be replaced /w an xe_engine) */ /** @kernel_lrc: Kernel LRC (should be replaced /w an xe_engine) */
struct xe_lrc kernel_lrc; struct xe_lrc *kernel_lrc;
/** @exl_port: execlists port */ /** @exl_port: execlists port */
struct xe_execlist_port *exl_port; struct xe_execlist_port *exl_port;
/** @fence_irq: fence IRQ to run when a hw engine IRQ is received */ /** @fence_irq: fence IRQ to run when a hw engine IRQ is received */
......
...@@ -808,11 +808,20 @@ static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) ...@@ -808,11 +808,20 @@ static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm)
xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc)); xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc));
} }
static void xe_lrc_finish(struct xe_lrc *lrc)
{
xe_hw_fence_ctx_finish(&lrc->fence_ctx);
xe_bo_lock(lrc->bo, false);
xe_bo_unpin(lrc->bo);
xe_bo_unlock(lrc->bo);
xe_bo_put(lrc->bo);
}
#define PVC_CTX_ASID (0x2e + 1) #define PVC_CTX_ASID (0x2e + 1)
#define PVC_CTX_ACC_CTR_THOLD (0x2a + 1) #define PVC_CTX_ACC_CTR_THOLD (0x2a + 1)
int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
struct xe_exec_queue *q, struct xe_vm *vm, u32 ring_size) struct xe_vm *vm, u32 ring_size)
{ {
struct xe_gt *gt = hwe->gt; struct xe_gt *gt = hwe->gt;
struct xe_tile *tile = gt_to_tile(gt); struct xe_tile *tile = gt_to_tile(gt);
...@@ -823,6 +832,7 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, ...@@ -823,6 +832,7 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
u32 lrc_size; u32 lrc_size;
int err; int err;
kref_init(&lrc->refcount);
lrc->flags = 0; lrc->flags = 0;
lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class);
if (xe_gt_has_indirect_ring_state(gt)) if (xe_gt_has_indirect_ring_state(gt))
...@@ -935,13 +945,31 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, ...@@ -935,13 +945,31 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
return err; return err;
} }
void xe_lrc_finish(struct xe_lrc *lrc) struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
u32 ring_size)
{ {
xe_hw_fence_ctx_finish(&lrc->fence_ctx); struct xe_lrc *lrc;
xe_bo_lock(lrc->bo, false); int err;
xe_bo_unpin(lrc->bo);
xe_bo_unlock(lrc->bo); lrc = kzalloc(sizeof(*lrc), GFP_KERNEL);
xe_bo_put(lrc->bo); if (!lrc)
return ERR_PTR(-ENOMEM);
err = xe_lrc_init(lrc, hwe, vm, ring_size);
if (err) {
kfree(lrc);
return ERR_PTR(err);
}
return lrc;
}
void xe_lrc_destroy(struct kref *ref)
{
struct xe_lrc *lrc = container_of(ref, struct xe_lrc, refcount);
xe_lrc_finish(lrc);
kfree(lrc);
} }
void xe_lrc_set_ring_tail(struct xe_lrc *lrc, u32 tail) void xe_lrc_set_ring_tail(struct xe_lrc *lrc, u32 tail)
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/types.h> #include <linux/types.h>
#include "xe_lrc_types.h"
struct drm_printer; struct drm_printer;
struct xe_bb; struct xe_bb;
struct xe_device; struct xe_device;
...@@ -20,9 +22,20 @@ struct xe_vm; ...@@ -20,9 +22,20 @@ struct xe_vm;
#define LRC_PPHWSP_SCRATCH_ADDR (0x34 * 4) #define LRC_PPHWSP_SCRATCH_ADDR (0x34 * 4)
int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
struct xe_exec_queue *q, struct xe_vm *vm, u32 ring_size); u32 ring_size);
void xe_lrc_finish(struct xe_lrc *lrc); void xe_lrc_destroy(struct kref *ref);
static inline struct xe_lrc *xe_lrc_get(struct xe_lrc *lrc)
{
kref_get(&lrc->refcount);
return lrc;
}
static inline void xe_lrc_put(struct xe_lrc *lrc)
{
kref_put(&lrc->refcount, xe_lrc_destroy);
}
size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class); size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class);
u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc); u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc);
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#ifndef _XE_LRC_TYPES_H_ #ifndef _XE_LRC_TYPES_H_
#define _XE_LRC_TYPES_H_ #define _XE_LRC_TYPES_H_
#include <linux/kref.h>
#include "xe_hw_fence_types.h" #include "xe_hw_fence_types.h"
struct xe_bo; struct xe_bo;
...@@ -30,6 +32,9 @@ struct xe_lrc { ...@@ -30,6 +32,9 @@ struct xe_lrc {
#define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1
u32 flags; u32 flags;
/** @refcount: ref count of this lrc */
struct kref refcount;
/** @ring: submission ring state */ /** @ring: submission ring state */
struct { struct {
/** @ring.size: size of submission ring */ /** @ring.size: size of submission ring */
......
...@@ -396,7 +396,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job) ...@@ -396,7 +396,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job)
xe_gt_assert(gt, job->q->width <= 1); /* no parallel submission for GSCCS */ xe_gt_assert(gt, job->q->width <= 1); /* no parallel submission for GSCCS */
__emit_job_gen12_simple(job, job->q->lrc, __emit_job_gen12_simple(job, job->q->lrc[0],
job->ptrs[0].batch_addr, job->ptrs[0].batch_addr,
xe_sched_job_lrc_seqno(job)); xe_sched_job_lrc_seqno(job));
} }
...@@ -406,13 +406,13 @@ static void emit_job_gen12_copy(struct xe_sched_job *job) ...@@ -406,13 +406,13 @@ static void emit_job_gen12_copy(struct xe_sched_job *job)
int i; int i;
if (xe_sched_job_is_migration(job->q)) { if (xe_sched_job_is_migration(job->q)) {
emit_migration_job_gen12(job, job->q->lrc, emit_migration_job_gen12(job, job->q->lrc[0],
xe_sched_job_lrc_seqno(job)); xe_sched_job_lrc_seqno(job));
return; return;
} }
for (i = 0; i < job->q->width; ++i) for (i = 0; i < job->q->width; ++i)
__emit_job_gen12_simple(job, job->q->lrc + i, __emit_job_gen12_simple(job, job->q->lrc[i],
job->ptrs[i].batch_addr, job->ptrs[i].batch_addr,
xe_sched_job_lrc_seqno(job)); xe_sched_job_lrc_seqno(job));
} }
...@@ -423,7 +423,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job) ...@@ -423,7 +423,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job)
/* FIXME: Not doing parallel handshake for now */ /* FIXME: Not doing parallel handshake for now */
for (i = 0; i < job->q->width; ++i) for (i = 0; i < job->q->width; ++i)
__emit_job_gen12_video(job, job->q->lrc + i, __emit_job_gen12_video(job, job->q->lrc[i],
job->ptrs[i].batch_addr, job->ptrs[i].batch_addr,
xe_sched_job_lrc_seqno(job)); xe_sched_job_lrc_seqno(job));
} }
...@@ -433,7 +433,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job) ...@@ -433,7 +433,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job)
int i; int i;
for (i = 0; i < job->q->width; ++i) for (i = 0; i < job->q->width; ++i)
__emit_job_gen12_render_compute(job, job->q->lrc + i, __emit_job_gen12_render_compute(job, job->q->lrc[i],
job->ptrs[i].batch_addr, job->ptrs[i].batch_addr,
xe_sched_job_lrc_seqno(job)); xe_sched_job_lrc_seqno(job));
} }
......
...@@ -216,7 +216,7 @@ void xe_sched_job_set_error(struct xe_sched_job *job, int error) ...@@ -216,7 +216,7 @@ void xe_sched_job_set_error(struct xe_sched_job *job, int error)
bool xe_sched_job_started(struct xe_sched_job *job) bool xe_sched_job_started(struct xe_sched_job *job)
{ {
struct xe_lrc *lrc = job->q->lrc; struct xe_lrc *lrc = job->q->lrc[0];
return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job), return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job),
xe_lrc_start_seqno(lrc), xe_lrc_start_seqno(lrc),
...@@ -225,7 +225,7 @@ bool xe_sched_job_started(struct xe_sched_job *job) ...@@ -225,7 +225,7 @@ bool xe_sched_job_started(struct xe_sched_job *job)
bool xe_sched_job_completed(struct xe_sched_job *job) bool xe_sched_job_completed(struct xe_sched_job *job)
{ {
struct xe_lrc *lrc = job->q->lrc; struct xe_lrc *lrc = job->q->lrc[0];
/* /*
* Can safely check just LRC[0] seqno as that is last seqno written when * Can safely check just LRC[0] seqno as that is last seqno written when
...@@ -265,7 +265,7 @@ void xe_sched_job_arm(struct xe_sched_job *job) ...@@ -265,7 +265,7 @@ void xe_sched_job_arm(struct xe_sched_job *job)
struct dma_fence_chain *chain; struct dma_fence_chain *chain;
fence = job->ptrs[i].lrc_fence; fence = job->ptrs[i].lrc_fence;
xe_lrc_init_seqno_fence(&q->lrc[i], fence); xe_lrc_init_seqno_fence(q->lrc[i], fence);
job->ptrs[i].lrc_fence = NULL; job->ptrs[i].lrc_fence = NULL;
if (!i) { if (!i) {
job->lrc_seqno = fence->seqno; job->lrc_seqno = fence->seqno;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment