[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:22 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 Freedreno
mailing list