Add a helper to extract the first amdgpu_fence which has
not yet signalled and is thus guilty or at least collateral
damage.

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 31 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h  |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index a7a6db0bc6940..733e9b668ed8f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -831,6 +831,37 @@ void amdgpu_ring_backup_unprocessed_commands(struct 
amdgpu_ring *ring,
        } while (last_seq != seq);
 }
 
+struct amdgpu_fence *
+amdgpu_ring_find_guilty_fence(struct amdgpu_ring *ring)
+{
+       struct dma_fence *unprocessed;
+       struct dma_fence __rcu **ptr;
+       struct amdgpu_fence *fence;
+       u32 seq, last_seq;
+
+       last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask;
+       seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask;
+       ring->ring_backup_entries_to_copy = 0;
+
+       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);
+
+               if (unprocessed && !dma_fence_is_signaled(unprocessed)) {
+                       fence = container_of(unprocessed, struct amdgpu_fence, 
base);
+                       rcu_read_unlock();
+                       return fence;
+               }
+               rcu_read_unlock();
+       } while (last_seq != seq);
+
+       return NULL;
+}
+
 /*
  * Common fence implementation
  */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 9276a3bb69de1..71cd9bb12f75b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -589,6 +589,8 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
 bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
 void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
                                             struct amdgpu_fence *guilty_fence);
+struct amdgpu_fence *
+amdgpu_ring_find_guilty_fence(struct amdgpu_ring *ring);
 void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
                                    struct amdgpu_fence *guilty_fence);
 int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
-- 
2.54.0

Reply via email to