From: Matthew Brost <[email protected]>

Help disconnect fences from the Xe module.

Signed-off-by: Matthew Brost <[email protected]>
---
 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 = &gt->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(&gt->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(&gt->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 = &gt->fence_irq[info->class];
+       hwe->fence_irq = gt->fence_irq[info->class];
        hwe->engine_id = id;
 
        hwe->eclass = &gt->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 */
-- 
2.43.0

Reply via email to