[PATCH v3 1/3] drm: Add DRM prime interfaces to reassign GEM handle
Christian König
christian.koenig at amd.com
Mon Mar 31 08:24:04 UTC 2025
Am 28.03.25 um 19:06 schrieb David Francis:
> CRIU restore of drm buffer objects requires the ability to create
> a buffer object with a specific gem handle.
>
> Add function drm_prime_change_buf_handle to change the gem handle
> of a specified buffer object.
>
> This function calls drm_gem_object_release_handle.
> drm_gem_object_release_handle is an internal function with one caller;
> make it not acquire the prime lock.
>
> Signed-off-by: David Francis <David.Francis at amd.com>
> ---
> drivers/gpu/drm/drm_gem.c | 5 ++++
> drivers/gpu/drm/drm_prime.c | 47 +++++++++++++++++++++++++++++++++----
> include/drm/drm_prime.h | 2 ++
> 3 files changed, 50 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index ee811764c3df..f56eeed808d2 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -282,7 +282,12 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
> if (obj->funcs->close)
> obj->funcs->close(obj, file_priv);
>
> + mutex_lock(&file_priv->prime.lock);
> +
> drm_prime_remove_buf_handle(&file_priv->prime, id);
> +
> + mutex_unlock(&file_priv->prime.lock);
> +
> drm_vma_node_revoke(&obj->vma_node, file_priv);
>
> drm_gem_object_handle_put_unlocked(obj);
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index 0e3f8adf162f..08205b291825 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -190,8 +190,6 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
> {
> struct rb_node *rb;
>
> - mutex_lock(&prime_fpriv->lock);
> -
> rb = prime_fpriv->handles.rb_node;
> while (rb) {
> struct drm_prime_member *member;
> @@ -210,8 +208,6 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
> rb = rb->rb_left;
> }
> }
> -
> - mutex_unlock(&prime_fpriv->lock);
> }
>
> void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
> @@ -1084,3 +1080,46 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
> dma_buf_put(dma_buf);
> }
> EXPORT_SYMBOL(drm_prime_gem_destroy);
> +
> +/**
> + * drm_prime_change_buf_handle - function to change the gem handle of a bo
> + * @file_priv: drm file-private structure
> + * @gem_obj: gem object whose handle should be changed
> + * @newhandle: handle to change to
> + *
> + * Will fail if the gem object cannot be found or if the new handle
> + * is already in use.
> + */
> +int drm_prime_change_buf_handle(struct drm_file *file_priv, struct drm_gem_object *gem_obj, int newhandle)
> +{
> + int oldhandle = -1;
> + int ret;
> +
> + mutex_lock(&file_priv->prime.lock);
> +
> + ret = drm_prime_lookup_buf_handle(&file_priv->prime, gem_obj->dma_buf, &oldhandle);
> + if (ret < 0)
> + goto out_unlock;
> +
> + drm_prime_remove_buf_handle(&file_priv->prime, oldhandle);
That won't work like this. If this is the only handle (which is likely directly after creation) then that would potentially destroy the DMA-buf.
> +
> + spin_lock(&file_priv->table_lock);
> +
> + idr_remove(&file_priv->object_idr, oldhandle);
> + ret = idr_alloc(&file_priv->object_idr, gem_obj, newhandle, newhandle + 1, GFP_NOWAIT);
> +
> + spin_unlock(&file_priv->table_lock);
> +
> + if (ret < 0)
> + goto out_unlock;
> +
> + ret = drm_prime_add_buf_handle(&file_priv->prime, gem_obj->dma_buf, newhandle);
> + if (ret < 0)
> + goto out_unlock;
> +
> +out_unlock:
> + mutex_unlock(&file_priv->prime.lock);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(drm_prime_change_buf_handle);
This needs to be an IOCTL and not an exported function. Re-ordering handles *must* be separate to re-creating the buffers.
Regards,
Christian.
> \ No newline at end of file
> diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
> index fa085c44d4ca..5a9288493dd7 100644
> --- a/include/drm/drm_prime.h
> +++ b/include/drm/drm_prime.h
> @@ -112,5 +112,7 @@ int drm_prime_sg_to_page_array(struct sg_table *sgt, struct page **pages,
> int max_pages);
> int drm_prime_sg_to_dma_addr_array(struct sg_table *sgt, dma_addr_t *addrs,
> int max_pages);
> +int drm_prime_change_buf_handle(struct drm_file *file_priv,
> + struct drm_gem_object *gem_obj, int newhandle);
>
> #endif /* __DRM_PRIME_H__ */
More information about the amd-gfx
mailing list