On 9/7/26 10:47, Yogesh Mohan Marimuthu wrote:
> If in userq_signal_ioctl only bo_write_handles is passed and
> num_bo_read_handles is zero then if there is contention the code is stuck
> in drm_exec_until_all_locked()
> 
> This happens because read bo's are handled first and then write bo's in
> drm_exec_until_all_locked loop. When there is contention in one of the
> write bo, exec->contended bo is set and the loop is retried, but
> read bo is zero, still drm_exec_retry_on_contention() macro for read bo
> is executed without drm_exec_lock_contended() getting executed.
> drm_exec_retry_on_contention will keep going to beginning of the loop
> causing infinite loop.

Well that is a really good find but clear NAK to the solution.

This if this causes an infinite loop there is a bug somewhere in the drm_exec 
object.

My educated guess is that drm_exec_prepare_array() needs to call 
drm_exec_lock_contended() even when num_objects is zero.

Regards,
Christian.

> 
> Fix this by only locking and reserving fence for bo only if there are
> bo passed userq_signal_ioctl.
> 
> Observed this issue when testing with MR
> https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40808
> 
> Signed-off-by: Yogesh Mohan Marimuthu <[email protected]>
> ---
>  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   | 24 +++++++++++--------
>  1 file changed, 14 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> index c270635c9..135e77837 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> @@ -572,17 +572,21 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, 
> void *data,
>                     (num_read_bo_handles + num_write_bo_handles));
>  
>       drm_exec_until_all_locked(&exec) {
> -             r = drm_exec_prepare_array(&exec, gobj_read,
> -                                        num_read_bo_handles, 1);
> -             drm_exec_retry_on_contention(&exec);
> -             if (r)
> -                     goto exec_fini;
> +             if (num_read_bo_handles) {
> +                     r = drm_exec_prepare_array(&exec, gobj_read,
> +                                                num_read_bo_handles, 1);
> +                     drm_exec_retry_on_contention(&exec);
> +                     if (r)
> +                             goto exec_fini;
> +             }
>  
> -             r = drm_exec_prepare_array(&exec, gobj_write,
> -                                        num_write_bo_handles, 1);
> -             drm_exec_retry_on_contention(&exec);
> -             if (r)
> -                     goto exec_fini;
> +             if (num_write_bo_handles) {
> +                     r = drm_exec_prepare_array(&exec, gobj_write,
> +                                                num_write_bo_handles, 1);
> +                     drm_exec_retry_on_contention(&exec);
> +                     if (r)
> +                             goto exec_fini;
> +             }
>       }
>  
>       /* And publish the new fence in the BOs and syncobj */

Reply via email to