[PATCH 09/13] drm/gem: Acquire reservation lock in drm_gem_{pin/unpin}()

Zack Rusin zack.rusin at broadcom.com
Wed Feb 28 03:52:10 UTC 2024


On Tue, Feb 27, 2024 at 6:39 AM Thomas Zimmermann <tzimmermann at suse.de> wrote:
>
> Acquire the buffer object's reservation lock in drm_gem_pin() and
> remove locking the drivers' GEM callbacks where necessary. Same for
> unpin().
>
> DRM drivers and memory managers modified by this patch will now have
> correct dma-buf locking semantics: the caller is responsible for
> holding the reservation lock when calling the pin or unpin callback.
>
> DRM drivers and memory managers that are not modified will now be
> protected against concurent invocation of their pin and unpin callbacks.
>
> PRIME does not implement struct dma_buf_ops.pin, which requires
> the caller to hold the reservation lock. It does implement struct
> dma_buf_ops.attach, which requires to callee to acquire the
> reservation lock. The PRIME code uses drm_gem_pin(), so locks
> are now taken as specified. Same for unpin and detach.
>
> The patch harmonizes GEM pin and unpin to have non-interruptible
> reservation locking across all drivers, as is already the case for
> vmap and vunmap. This affects gem-shmem, gem-vram, loongson, qxl and
> radeon.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> ---
>  drivers/gpu/drm/drm_gem.c               | 22 ++++++++++++++++++++--
>  drivers/gpu/drm/drm_gem_vram_helper.c   | 15 +--------------
>  drivers/gpu/drm/drm_internal.h          |  2 ++
>  drivers/gpu/drm/loongson/lsdc_gem.c     | 13 ++-----------
>  drivers/gpu/drm/msm/msm_gem_prime.c     |  4 ----
>  drivers/gpu/drm/nouveau/nouveau_prime.c | 11 -----------
>  drivers/gpu/drm/qxl/qxl_prime.c         | 14 +-------------
>  drivers/gpu/drm/radeon/radeon_prime.c   | 11 -----------
>  drivers/gpu/drm/vmwgfx/vmwgfx_gem.c     | 25 ++++++-------------------
>  include/drm/drm_gem_shmem_helper.h      | 11 +----------
>  10 files changed, 33 insertions(+), 95 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 44a948b80ee14..e0f80c6a7096f 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -1161,7 +1161,7 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
>                 obj->funcs->print_info(p, indent, obj);
>  }
>
> -int drm_gem_pin(struct drm_gem_object *obj)
> +int drm_gem_pin_locked(struct drm_gem_object *obj)
>  {
>         if (obj->funcs->pin)
>                 return obj->funcs->pin(obj);
> @@ -1169,12 +1169,30 @@ int drm_gem_pin(struct drm_gem_object *obj)
>         return 0;
>  }
>
> -void drm_gem_unpin(struct drm_gem_object *obj)
> +void drm_gem_unpin_locked(struct drm_gem_object *obj)
>  {
>         if (obj->funcs->unpin)
>                 obj->funcs->unpin(obj);
>  }
>
> +int drm_gem_pin(struct drm_gem_object *obj)
> +{
> +       int ret;
> +
> +       dma_resv_lock(obj->resv, NULL);
> +       ret = drm_gem_pin_locked(obj);
> +       dma_resv_unlock(obj->resv);
> +
> +       return ret;
> +}
> +
> +void drm_gem_unpin(struct drm_gem_object *obj)
> +{
> +       dma_resv_lock(obj->resv, NULL);
> +       drm_gem_unpin_locked(obj);
> +       dma_resv_unlock(obj->resv);
> +}
> +
>  int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map)
>  {
>         int ret;
> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
> index 15029d89badf8..5a16b3e0a4134 100644
> --- a/drivers/gpu/drm/drm_gem_vram_helper.c
> +++ b/drivers/gpu/drm/drm_gem_vram_helper.c
> @@ -774,11 +774,6 @@ EXPORT_SYMBOL(drm_gem_vram_simple_display_pipe_cleanup_fb);
>  static int drm_gem_vram_object_pin(struct drm_gem_object *gem)
>  {
>         struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
> -       int ret;
> -
> -       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
> -       if (ret)
> -               return ret;
>
>         /*
>          * Fbdev console emulation is the use case of these PRIME
> @@ -789,10 +784,7 @@ static int drm_gem_vram_object_pin(struct drm_gem_object *gem)
>          * the buffer to be pinned to VRAM, implement a callback that
>          * sets the flags accordingly.
>          */
> -       ret = drm_gem_vram_pin_locked(gbo, 0);
> -       ttm_bo_unreserve(&gbo->bo);
> -
> -       return ret;
> +       return drm_gem_vram_pin_locked(gbo, 0);
>  }
>
>  /**
> @@ -803,13 +795,8 @@ static int drm_gem_vram_object_pin(struct drm_gem_object *gem)
>  static void drm_gem_vram_object_unpin(struct drm_gem_object *gem)
>  {
>         struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
> -       int ret;
>
> -       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
> -       if (ret)
> -               return;
>         drm_gem_vram_unpin_locked(gbo);
> -       ttm_bo_unreserve(&gbo->bo);
>  }
>
>  /**
> diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
> index 8e4faf0a28e6c..40b2d3a274d6c 100644
> --- a/drivers/gpu/drm/drm_internal.h
> +++ b/drivers/gpu/drm/drm_internal.h
> @@ -170,6 +170,8 @@ void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
>  void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
>                         const struct drm_gem_object *obj);
>
> +int drm_gem_pin_locked(struct drm_gem_object *obj);
> +void drm_gem_unpin_locked(struct drm_gem_object *obj);
>  int drm_gem_pin(struct drm_gem_object *obj);
>  void drm_gem_unpin(struct drm_gem_object *obj);
>  int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map);
> diff --git a/drivers/gpu/drm/loongson/lsdc_gem.c b/drivers/gpu/drm/loongson/lsdc_gem.c
> index 04293df2f0de0..a720d8f532093 100644
> --- a/drivers/gpu/drm/loongson/lsdc_gem.c
> +++ b/drivers/gpu/drm/loongson/lsdc_gem.c
> @@ -19,33 +19,24 @@ static int lsdc_gem_prime_pin(struct drm_gem_object *obj)
>         struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);
>         int ret;
>
> -       ret = lsdc_bo_reserve(lbo);
> -       if (unlikely(ret))
> -               return ret;
> +       dma_resv_assert_held(obj->resv);
>
>         ret = lsdc_bo_pin(lbo, LSDC_GEM_DOMAIN_GTT, NULL);
>         if (likely(ret == 0))
>                 lbo->sharing_count++;
>
> -       lsdc_bo_unreserve(lbo);
> -
>         return ret;
>  }
>
>  static void lsdc_gem_prime_unpin(struct drm_gem_object *obj)
>  {
>         struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);
> -       int ret;
>
> -       ret = lsdc_bo_reserve(lbo);
> -       if (unlikely(ret))
> -               return;
> +       dma_resv_assert_held(obj->resv);
>
>         lsdc_bo_unpin(lbo);
>         if (lbo->sharing_count)
>                 lbo->sharing_count--;
> -
> -       lsdc_bo_unreserve(lbo);
>  }
>
>  static struct sg_table *lsdc_gem_prime_get_sg_table(struct drm_gem_object *obj)
> diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
> index 0d22df53ab98a..ee267490c9359 100644
> --- a/drivers/gpu/drm/msm/msm_gem_prime.c
> +++ b/drivers/gpu/drm/msm/msm_gem_prime.c
> @@ -53,11 +53,9 @@ int msm_gem_prime_pin(struct drm_gem_object *obj)
>         if (obj->import_attach)
>                 return 0;
>
> -       msm_gem_lock(obj);
>         pages = msm_gem_pin_pages_locked(obj);
>         if (IS_ERR(pages))
>                 ret = PTR_ERR(pages);
> -       msm_gem_unlock(obj);
>
>         return ret;
>  }
> @@ -67,7 +65,5 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)
>         if (obj->import_attach)
>                 return;
>
> -       msm_gem_lock(obj);
>         msm_gem_unpin_pages_locked(obj);
> -       msm_gem_unlock(obj);
>  }
> diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c
> index 774f9bd031102..b58ab595faf82 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_prime.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
> @@ -86,17 +86,12 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
>  int nouveau_gem_prime_pin(struct drm_gem_object *obj)
>  {
>         struct nouveau_bo *nvbo = nouveau_gem_object(obj);
> -       struct ttm_buffer_object *bo = &nvbo->bo;
>         int ret;
>
> -       ret = ttm_bo_reserve(bo, false, false, NULL);
> -       if (ret)
> -               return -EINVAL;
>         /* pin buffer into GTT */
>         ret = nouveau_bo_pin_locked(nvbo, NOUVEAU_GEM_DOMAIN_GART, false);
>         if (ret)
>                 ret = -EINVAL;
> -       ttm_bo_unreserve(bo);
>
>         return ret;
>  }
> @@ -104,14 +99,8 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj)
>  void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
>  {
>         struct nouveau_bo *nvbo = nouveau_gem_object(obj);
> -       struct ttm_buffer_object *bo = &nvbo->bo;
> -       int ret;
>
> -       ret = ttm_bo_reserve(bo, false, false, NULL);
> -       if (ret)
> -               return;
>         nouveau_bo_unpin_locked(nvbo);
> -       ttm_bo_unreserve(bo);
>  }
>
>  struct dma_buf *nouveau_gem_prime_export(struct drm_gem_object *gobj,
> diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
> index f2646603e12eb..19bf551a7b311 100644
> --- a/drivers/gpu/drm/qxl/qxl_prime.c
> +++ b/drivers/gpu/drm/qxl/qxl_prime.c
> @@ -31,27 +31,15 @@
>  int qxl_gem_prime_pin(struct drm_gem_object *obj)
>  {
>         struct qxl_bo *bo = gem_to_qxl_bo(obj);
> -       int r;
>
> -       r = qxl_bo_reserve(bo);
> -       if (r)
> -               return r;
> -       r = qxl_bo_pin_locked(bo);
> -       qxl_bo_unreserve(bo);
> -
> -       return r;
> +       return qxl_bo_pin_locked(bo);
>  }
>
>  void qxl_gem_prime_unpin(struct drm_gem_object *obj)
>  {
>         struct qxl_bo *bo = gem_to_qxl_bo(obj);
> -       int r;
>
> -       r = qxl_bo_reserve(bo);
> -       if (r)
> -               return;
>         qxl_bo_unpin_locked(bo);
> -       qxl_bo_unreserve(bo);
>  }
>
>  struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
> diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c
> index b3cfc99f4d7ed..a77881f035e7a 100644
> --- a/drivers/gpu/drm/radeon/radeon_prime.c
> +++ b/drivers/gpu/drm/radeon/radeon_prime.c
> @@ -73,32 +73,21 @@ int radeon_gem_prime_pin(struct drm_gem_object *obj)
>         struct radeon_bo *bo = gem_to_radeon_bo(obj);
>         int ret = 0;
>
> -       ret = radeon_bo_reserve(bo, false);
> -       if (unlikely(ret != 0))
> -               return ret;
> -
>         /* pin buffer into GTT */
>         ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL);
>         if (likely(ret == 0))
>                 bo->prime_shared_count++;
>
> -       radeon_bo_unreserve(bo);
>         return ret;
>  }
>
>  void radeon_gem_prime_unpin(struct drm_gem_object *obj)
>  {
>         struct radeon_bo *bo = gem_to_radeon_bo(obj);
> -       int ret = 0;
> -
> -       ret = radeon_bo_reserve(bo, false);
> -       if (unlikely(ret != 0))
> -               return;
>
>         radeon_bo_unpin(bo);
>         if (bo->prime_shared_count)
>                 bo->prime_shared_count--;
> -       radeon_bo_unreserve(bo);
>  }
>
>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
> index 12787bb9c111d..186150f41fbcc 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
> @@ -48,33 +48,20 @@ static void vmw_gem_object_close(struct drm_gem_object *obj,
>  {
>  }
>
> -static int vmw_gem_pin_private(struct drm_gem_object *obj, bool do_pin)
> +static int vmw_gem_object_pin(struct drm_gem_object *obj)
>  {
> -       struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj);
>         struct vmw_bo *vbo = to_vmw_bo(obj);
> -       int ret;
> -
> -       ret = ttm_bo_reserve(bo, false, false, NULL);
> -       if (unlikely(ret != 0))
> -               goto err;
> -
> -       vmw_bo_pin_reserved(vbo, do_pin);
> -
> -       ttm_bo_unreserve(bo);
> -
> -err:
> -       return ret;
> -}
>
> +       vmw_bo_pin_reserved(vbo, true);
>
> -static int vmw_gem_object_pin(struct drm_gem_object *obj)
> -{
> -       return vmw_gem_pin_private(obj, true);
> +       return 0;
>  }
>
>  static void vmw_gem_object_unpin(struct drm_gem_object *obj)
>  {
> -       vmw_gem_pin_private(obj, false);
> +       struct vmw_bo *vbo = to_vmw_bo(obj);
> +
> +       vmw_bo_pin_reserved(vbo, false);
>  }
>
>  static struct sg_table *vmw_gem_object_get_sg_table(struct drm_gem_object *obj)
> diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h
> index eb12aa9a8c556..efbc9f27312b5 100644
> --- a/include/drm/drm_gem_shmem_helper.h
> +++ b/include/drm/drm_gem_shmem_helper.h
> @@ -175,15 +175,8 @@ static inline void drm_gem_shmem_object_print_info(struct drm_printer *p, unsign
>  static inline int drm_gem_shmem_object_pin(struct drm_gem_object *obj)
>  {
>         struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
> -       int ret;
>
> -       ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
> -       if (ret)
> -               return ret;
> -       ret = drm_gem_shmem_pin_locked(shmem);
> -       dma_resv_unlock(shmem->base.resv);
> -
> -       return ret;
> +       return drm_gem_shmem_pin_locked(shmem);
>  }
>
>  /**
> @@ -197,9 +190,7 @@ static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj)
>  {
>         struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
>
> -       dma_resv_lock(shmem->base.resv, NULL);
>         drm_gem_shmem_unpin_locked(shmem);
> -       dma_resv_unlock(shmem->base.resv);
>  }
>
>

Ah, I see. Looks great.

Reviewed-by: Zack Rusin <zack.rusin at broadcom.com>


More information about the amd-gfx mailing list