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 90cbc95f8e2e..4ba33fdd34ad 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -139,7 +139,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 89808b33d0a8..d12b4669ebb6 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -608,7 +608,8 @@ static void xe_gt_fini(void *arg)
int i;
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);
}
@@ -622,7 +623,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 d93faa1eedef..132b4fdbed49 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -312,7 +312,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 */
--
2.34.1