On 4/26/2025 12:08 AM, Alex Deucher wrote:
Add support for forcing completion of userq fences.
This is needed for userq resets and asic resets so that we
can set the error on the fence and force completion.

Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
---
  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   | 42 +++++++++++++++++++
  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.h   |  1 +
  2 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 3288c2ff692e7..3494ac9e9e9db 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -67,6 +67,14 @@ static u64 amdgpu_userq_fence_read(struct 
amdgpu_userq_fence_driver *fence_drv)
        return le64_to_cpu(*fence_drv->cpu_addr);
  }
+static void
+amdgpu_userq_fence_write(struct amdgpu_userq_fence_driver *fence_drv,
+                        u64 seq)
+{
+       if (fence_drv->cpu_addr)
+               *fence_drv->cpu_addr = cpu_to_le64(seq);
+}
+
  int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
                                    struct amdgpu_usermode_queue *userq)
  {
@@ -408,6 +416,40 @@ static void amdgpu_userq_fence_cleanup(struct dma_fence 
*fence)
        dma_fence_put(fence);
  }
+static void
+amdgpu_userq_fence_driver_set_error(struct amdgpu_userq_fence *fence,
+                                   int error)
+{
+       struct amdgpu_userq_fence_driver *fence_drv = fence->fence_drv;
+       unsigned long flags;
+       struct dma_fence *f;
+
+       spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
+
+       f = rcu_dereference_protected(&fence->base,
+                                     
lockdep_is_held(&fence_drv->fence_list_lock));
+       if (f && !dma_fence_is_signaled_locked(f))
+               dma_fence_set_error(f, error);
+       spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
+}
+
+void
+amdgpu_userq_fence_driver_force_completion(struct amdgpu_usermode_queue *userq)
+{
+       struct dma_fence *f = userq->last_fence;
+
+       if (f) {
+               struct amdgpu_userq_fence *fence = to_amdgpu_userq_fence(f);
+               struct amdgpu_userq_fence_driver *fence_drv = fence->fence_drv;

Do we want to declare there structures to beginning of the function ??

Regards
Sunil Khatri

+               u64 wptr = fence->base.seqno;
+
+               amdgpu_userq_fence_driver_set_error(fence, -ECANCELED);
+               amdgpu_userq_fence_write(fence_drv, wptr);
+               amdgpu_userq_fence_driver_process(fence_drv);
+
+       }
+}
+
  int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *filp)
  {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
index 97a125ab8a786..d76add2afc774 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
@@ -67,6 +67,7 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device 
*adev,
                                    struct amdgpu_usermode_queue *userq);
  void amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq);
  void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver 
*fence_drv);
+void amdgpu_userq_fence_driver_force_completion(struct amdgpu_usermode_queue 
*userq);
  void amdgpu_userq_fence_driver_destroy(struct kref *ref);
  int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *filp);

Reply via email to