On 4/30/25 17:48, 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. > > Cc: Christian König <christian.koe...@amd.com> > Reviewed-by: Sunil Khatri <sunil.kha...@amd.com> > 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);
It would be *much* more cleaner if the FW would do that as part of their reset prodcedure, but that is probably to much to ask. > +} > + > 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)); Hui? That rcu_dereference_protected doesn't really make sense here and will most likely result in complains by automated checkers. Just using &fence->base should be sufficient. Regards, Christian. > + 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; > + 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);