This should allow amdgpu_fences to outlive the amdgpu module.
Signed-off-by: Christian König <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 63 +++++++----------------
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 -
2 files changed, 20 insertions(+), 44 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index c7843e336310..990fcbbe90a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -112,8 +112,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct
amdgpu_fence *af,
af->ring = ring;
seq = ++ring->fence_drv.sync_seq;
- dma_fence_init(fence, &amdgpu_fence_ops,
- &ring->fence_drv.lock,
+ dma_fence_init(fence, &amdgpu_fence_ops, NULL,
adev->fence_context + ring->idx, seq);
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
@@ -467,7 +466,6 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
timer_setup(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback, 0);
ring->fence_drv.num_fences_mask = ring->num_hw_submission * 2 - 1;
- spin_lock_init(&ring->fence_drv.lock);
ring->fence_drv.fences = kcalloc(ring->num_hw_submission * 2,
sizeof(void *),
GFP_KERNEL);
@@ -654,16 +652,20 @@ void amdgpu_fence_driver_set_error(struct amdgpu_ring
*ring, int error)
struct amdgpu_fence_driver *drv = &ring->fence_drv;
unsigned long flags;
- spin_lock_irqsave(&drv->lock, flags);
+ rcu_read_lock();
for (unsigned int i = 0; i <= drv->num_fences_mask; ++i) {
struct dma_fence *fence;
- fence = rcu_dereference_protected(drv->fences[i],
- lockdep_is_held(&drv->lock));
- if (fence && !dma_fence_is_signaled_locked(fence))
+ fence = dma_fence_get_rcu(drv->fences[i]);
+ if (!fence)
+ continue;
+
+ dma_fence_lock_irqsave(fence, flags);
+ if (!dma_fence_is_signaled_locked(fence))
dma_fence_set_error(fence, error);
+ dma_fence_unlock_irqrestore(fence, flags);
}
- spin_unlock_irqrestore(&drv->lock, flags);
+ rcu_read_unlock();
}
/**
@@ -714,16 +716,19 @@ void amdgpu_fence_driver_guilty_force_completion(struct
amdgpu_fence *af)
seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask;
/* mark all fences from the guilty context with an error */
- spin_lock_irqsave(&ring->fence_drv.lock, flags);
+ rcu_read_lock();
do {
last_seq++;
last_seq &= ring->fence_drv.num_fences_mask;
ptr = &ring->fence_drv.fences[last_seq];
- rcu_read_lock();
- unprocessed = rcu_dereference(*ptr);
+ unprocessed = dma_fence_get_rcu(*ptr);
+
+ if (!unprocessed)
+ continue;
- if (unprocessed && !dma_fence_is_signaled_locked(unprocessed)) {
+ dma_fence_lock_irqsave(unprocessed, flags);
+ if (dma_fence_is_signaled_locked(unprocessed)) {
fence = container_of(unprocessed, struct amdgpu_fence,
base);
if (fence == af)
@@ -731,9 +736,10 @@ void amdgpu_fence_driver_guilty_force_completion(struct
amdgpu_fence *af)
else if (fence->context == af->context)
dma_fence_set_error(&fence->base, -ECANCELED);
}
- rcu_read_unlock();
+ dma_fence_unlock_irqrestore(unprocessed, flags);
+ dma_fence_put(unprocessed);
} while (last_seq != seq);
- spin_unlock_irqrestore(&ring->fence_drv.lock, flags);
+ rcu_read_unlock();
/* signal the guilty fence */
amdgpu_fence_write(ring, (u32)af->base.seqno);
amdgpu_fence_process(ring);
@@ -823,39 +829,10 @@ static bool amdgpu_fence_enable_signaling(struct
dma_fence *f)
return true;
}
-/**
- * amdgpu_fence_free - free up the fence memory
- *
- * @rcu: RCU callback head
- *
- * Free up the fence memory after the RCU grace period.
- */
-static void amdgpu_fence_free(struct rcu_head *rcu)
-{
- struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
-
- /* free fence_slab if it's separated fence*/
- kfree(to_amdgpu_fence(f));
-}
-
-/**
- * amdgpu_fence_release - callback that fence can be freed
- *
- * @f: fence
- *
- * This function is called when the reference count becomes zero.
- * It just RCU schedules freeing up the fence.
- */
-static void amdgpu_fence_release(struct dma_fence *f)
-{
- call_rcu(&f->rcu, amdgpu_fence_free);
-}
-
static const struct dma_fence_ops amdgpu_fence_ops = {
.get_driver_name = amdgpu_fence_get_driver_name,
.get_timeline_name = amdgpu_fence_get_timeline_name,
.enable_signaling = amdgpu_fence_enable_signaling,
- .release = amdgpu_fence_release,
};
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 7a27c6c4bb44..9cbf63454004 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -125,7 +125,6 @@ struct amdgpu_fence_driver {
unsigned irq_type;
struct timer_list fallback_timer;
unsigned num_fences_mask;
- spinlock_t lock;
struct dma_fence **fences;
};
--
2.43.0