On 4/10/25 12:55, Ian Forbes wrote:
> There was a possible race in vmw_update_seqno. Because of this race it
> was possible for last_read_seqno to go backwards. Remove this function
> and replace it with vmw_update_fences which now sets and returns the
> last_read_seqno while holding the fence lock. This serialization via the
> fence lock ensures that last_read_seqno is monotonic again.
> 
> Signed-off-by: Ian Forbes <ian.for...@broadcom.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c     |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.h     |  1 -
>  drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |  3 +--
>  drivers/gpu/drm/vmwgfx/vmwgfx_fence.c   | 18 +++++++++---------
>  drivers/gpu/drm/vmwgfx/vmwgfx_fence.h   |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_irq.c     | 12 +-----------
>  6 files changed, 13 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
> index dd4ca6a9c690..8fe02131a6c4 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
> @@ -544,7 +544,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, 
> uint32_t *seqno)
>       cmd_fence = (struct svga_fifo_cmd_fence *) fm;
>       cmd_fence->fence = *seqno;
>       vmw_cmd_commit_flush(dev_priv, bytes);
> -     vmw_update_seqno(dev_priv);
> +     vmw_fences_update(dev_priv->fman);
>  
>  out_err:
>       return ret;
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> index 594af8eb04c6..6d4a68f0ae37 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> @@ -1006,7 +1006,6 @@ extern int vmw_fallback_wait(struct vmw_private 
> *dev_priv,
>                            uint32_t seqno,
>                            bool interruptible,
>                            unsigned long timeout);
> -extern void vmw_update_seqno(struct vmw_private *dev_priv);
>  extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
>  extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
>  extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> index e831e324e737..90ce5372343b 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> @@ -3878,8 +3878,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private 
> *dev_priv,
>  
>               fence_rep.handle = fence_handle;
>               fence_rep.seqno = fence->base.seqno;
> -             vmw_update_seqno(dev_priv);
> -             fence_rep.passed_seqno = dev_priv->last_read_seqno;
> +             fence_rep.passed_seqno = vmw_fences_update(dev_priv->fman);
>       }
>  
>       /*
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> index 588d50ababf6..9d1465558839 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
> @@ -172,7 +172,7 @@ vmwgfx_wait_cb(struct dma_fence *fence, struct 
> dma_fence_cb *cb)
>       wake_up_process(wait->task);
>  }
>  
> -static void __vmw_fences_update(struct vmw_fence_manager *fman);
> +static u32 __vmw_fences_update(struct vmw_fence_manager *fman);
>  
>  static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long 
> timeout)
>  {
> @@ -457,7 +457,7 @@ static bool vmw_fence_goal_check_locked(struct 
> vmw_fence_obj *fence)
>       return true;
>  }
>  
> -static void __vmw_fences_update(struct vmw_fence_manager *fman)
> +static u32 __vmw_fences_update(struct vmw_fence_manager *fman)
>  {
>       struct vmw_fence_obj *fence, *next_fence;
>       struct list_head action_list;
> @@ -495,13 +495,16 @@ static void __vmw_fences_update(struct 
> vmw_fence_manager *fman)
>  
>       if (!list_empty(&fman->cleanup_list))
>               (void) schedule_work(&fman->work);
> +     return (fman->dev_priv->last_read_seqno = seqno);

Should this be WRITE_ONCE(fman->dev_priv->last_read_seqno) = seqno ?

>  }
>  
> -void vmw_fences_update(struct vmw_fence_manager *fman)
> +u32 vmw_fences_update(struct vmw_fence_manager *fman)
>  {
> +     u32 seqno;
>       spin_lock(&fman->lock);
> -     __vmw_fences_update(fman);
> +     seqno = __vmw_fences_update(fman);
>       spin_unlock(&fman->lock);
> +     return seqno;
>  }
>  
>  bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence)
> @@ -778,7 +781,6 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, 
> void *data,
>               (struct drm_vmw_fence_signaled_arg *) data;
>       struct ttm_base_object *base;
>       struct vmw_fence_obj *fence;
> -     struct vmw_fence_manager *fman;
>       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
>       struct vmw_private *dev_priv = vmw_priv(dev);
>  
> @@ -787,14 +789,12 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device 
> *dev, void *data,
>               return PTR_ERR(base);
>  
>       fence = &(container_of(base, struct vmw_user_fence, base)->fence);
> -     fman = fman_from_fence(fence);
>  
>       arg->signaled = vmw_fence_obj_signaled(fence);
>  
>       arg->signaled_flags = arg->flags;
> -     spin_lock(&fman->lock);
> -     arg->passed_seqno = dev_priv->last_read_seqno;
> -     spin_unlock(&fman->lock);
> +     arg->passed_seqno = READ_ONCE(dev_priv->last_read_seqno);
> +
>  
>       ttm_base_object_unref(&base);
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
> index a7eee579c76a..10264dab5f6a 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
> @@ -86,7 +86,7 @@ vmw_fence_obj_reference(struct vmw_fence_obj *fence)
>       return fence;
>  }
>  
> -extern void vmw_fences_update(struct vmw_fence_manager *fman);
> +u32 vmw_fences_update(struct vmw_fence_manager *fman);
>  
>  extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence);
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
> index 086e69a130d4..548ef2f86508 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
> @@ -123,16 +123,6 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, 
> uint32_t seqno)
>       return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0);
>  }
>  
> -void vmw_update_seqno(struct vmw_private *dev_priv)
> -{
> -     uint32_t seqno = vmw_fence_read(dev_priv);
> -
> -     if (dev_priv->last_read_seqno != seqno) {
> -             dev_priv->last_read_seqno = seqno;
> -             vmw_fences_update(dev_priv->fman);
> -     }
> -}
> -
>  bool vmw_seqno_passed(struct vmw_private *dev_priv,
>                        uint32_t seqno)
>  {
> @@ -141,7 +131,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv,
>       if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
>               return true;
>  
> -     vmw_update_seqno(dev_priv);
> +     vmw_fences_update(dev_priv->fman);
>       if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
>               return true;
>  


-- 
Maaz Mombasawala <maaz.mombasaw...@broadcom.com>

Reply via email to