From: Matthew Brost matthew.brost@intel.com
Help disconnect fences from the Xe module.
Signed-off-by: Matthew Brost matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_exec_queue.c | 2 +- drivers/gpu/drm/xe/xe_gt.c | 7 ++++-- drivers/gpu/drm/xe/xe_gt_types.h | 2 +- drivers/gpu/drm/xe/xe_hw_engine.c | 2 +- drivers/gpu/drm/xe/xe_hw_fence.c | 35 ++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_hw_fence.h | 2 +- drivers/gpu/drm/xe/xe_hw_fence_types.h | 4 +++ 7 files changed, 46 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 8724f8de67e2..68ec3ba4b995 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -140,7 +140,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, q->width = width; q->msix_vec = XE_IRQ_DEFAULT_MSIX; q->logical_mask = logical_mask; - q->fence_irq = >->fence_irq[hwe->class]; + q->fence_irq = gt->fence_irq[hwe->class]; q->ring_ops = gt->ring_ops[hwe->class]; q->ops = gt->exec_queue_ops; INIT_LIST_HEAD(&q->lr.link); diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 6d479948bf21..e0461a36771d 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -615,7 +615,8 @@ static void xe_gt_fini(void *arg) xe_pm_runtime_put(gt_to_xe(gt));
for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) - xe_hw_fence_irq_finish(>->fence_irq[i]); + if (gt->fence_irq[i]) + xe_hw_fence_irq_finish(gt->fence_irq[i]);
xe_gt_disable_host_l2_vram(gt); } @@ -629,7 +630,9 @@ int xe_gt_init(struct xe_gt *gt)
for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) { gt->ring_ops[i] = xe_ring_ops_get(gt, i); - xe_hw_fence_irq_init(>->fence_irq[i]); + gt->fence_irq[i] = xe_hw_fence_irq_init(); + if (!gt->fence_irq[i]) + return -ENOMEM; }
err = devm_add_action_or_reset(gt_to_xe(gt)->drm.dev, xe_gt_fini, gt); diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index 0a728180b6fe..88a05edab51b 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -240,7 +240,7 @@ struct xe_gt { const struct xe_ring_ops *ring_ops[XE_ENGINE_CLASS_MAX];
/** @fence_irq: fence IRQs (1 per engine class) */ - struct xe_hw_fence_irq fence_irq[XE_ENGINE_CLASS_MAX]; + struct xe_hw_fence_irq *fence_irq[XE_ENGINE_CLASS_MAX];
/** @default_lrc: default LRC state */ void *default_lrc[XE_ENGINE_CLASS_MAX]; diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 6a9e2a4272dd..480972c3da84 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -524,7 +524,7 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe, info->irq_offset; hwe->domain = info->domain; hwe->name = info->name; - hwe->fence_irq = >->fence_irq[info->class]; + hwe->fence_irq = gt->fence_irq[info->class]; hwe->engine_id = id;
hwe->eclass = >->eclass[hwe->class]; diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c index 5edcf057aceb..f5fad4426729 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.c +++ b/drivers/gpu/drm/xe/xe_hw_fence.c @@ -15,6 +15,25 @@ #include "xe_map.h" #include "xe_trace.h"
+static void xe_hw_fence_irq_destroy(struct kref *ref) +{ + struct xe_hw_fence_irq *irq = container_of(ref, typeof(*irq), refcount); + + kfree(irq); +} + +static void xe_hw_fence_irq_put(struct xe_hw_fence_irq *irq) +{ + if (irq) + kref_put(&irq->refcount, xe_hw_fence_irq_destroy); +} + +static struct xe_hw_fence_irq *xe_hw_fence_irq_get(struct xe_hw_fence_irq *irq) +{ + kref_get(&irq->refcount); + return irq; +} + static struct xe_hw_fence *fence_alloc(void) { return kzalloc(sizeof(struct xe_hw_fence), GFP_KERNEL); @@ -25,6 +44,7 @@ static void fence_free(struct rcu_head *rcu) struct xe_hw_fence *fence = container_of(rcu, struct xe_hw_fence, dma.rcu);
+ xe_hw_fence_irq_put(fence->irq); kfree(fence); }
@@ -52,12 +72,20 @@ static void hw_fence_irq_run_cb(struct irq_work *work) dma_fence_end_signalling(tmp); }
-void xe_hw_fence_irq_init(struct xe_hw_fence_irq *irq) +struct xe_hw_fence_irq *xe_hw_fence_irq_init(void) { + struct xe_hw_fence_irq *irq = kzalloc(sizeof(*irq), GFP_KERNEL); + + if (!irq) + return NULL; + + kref_init(&irq->refcount); spin_lock_init(&irq->lock); init_irq_work(&irq->work, hw_fence_irq_run_cb); INIT_LIST_HEAD(&irq->pending); irq->enabled = true; + + return irq; }
void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq) @@ -82,6 +110,8 @@ void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq)
/* Safe release of the irq->lock used in dma_fence_init. */ synchronize_rcu(); + + xe_hw_fence_irq_put(irq); }
void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq) @@ -233,13 +263,14 @@ void xe_hw_fence_free(struct dma_fence *fence) void xe_hw_fence_init(struct dma_fence *fence, struct xe_hw_fence_ctx *ctx, struct iosys_map seqno_map) { - struct xe_hw_fence *hw_fence = + struct xe_hw_fence *hw_fence = container_of(fence, typeof(*hw_fence), dma);
hw_fence->xe = gt_to_xe(ctx->gt); snprintf(hw_fence->name, sizeof(hw_fence->name), "%s", ctx->name); hw_fence->seqno_map = seqno_map; INIT_LIST_HEAD(&hw_fence->irq_link); + hw_fence->irq = xe_hw_fence_irq_get(ctx->irq);
dma_fence_init(fence, &xe_hw_fence_ops, &ctx->irq->lock, ctx->dma_fence_ctx, ctx->next_seqno++); diff --git a/drivers/gpu/drm/xe/xe_hw_fence.h b/drivers/gpu/drm/xe/xe_hw_fence.h index 96f34332fd8d..fa1620203b90 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.h +++ b/drivers/gpu/drm/xe/xe_hw_fence.h @@ -11,7 +11,7 @@ /* Cause an early wrap to catch wrapping errors */ #define XE_FENCE_INITIAL_SEQNO (-127)
-void xe_hw_fence_irq_init(struct xe_hw_fence_irq *irq); +struct xe_hw_fence_irq *xe_hw_fence_irq_init(void); void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq); void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq); void xe_hw_fence_irq_stop(struct xe_hw_fence_irq *irq); diff --git a/drivers/gpu/drm/xe/xe_hw_fence_types.h b/drivers/gpu/drm/xe/xe_hw_fence_types.h index 58a8d09afe5c..0682c12520e9 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence_types.h +++ b/drivers/gpu/drm/xe/xe_hw_fence_types.h @@ -28,6 +28,8 @@ struct xe_hw_fence_irq { struct irq_work work; /** @pending: list of pending xe_hw_fences */ struct list_head pending; + /** @refcount: ref count of this exec queue */ + struct kref refcount; /** @enabled: fence signaling enabled */ bool enabled; }; @@ -62,6 +64,8 @@ struct xe_hw_fence_ctx { struct xe_hw_fence { /** @dma: base dma fence for hardware fence context */ struct dma_fence dma; + /** @irq: fence irq handler */ + struct xe_hw_fence_irq *irq; /** @xe: Xe device for hw fence driver name */ struct xe_device *xe; /** @name: name of hardware fence context */