diff options
| author | David Francis <David.Francis@amd.com> | 2025-07-17 10:35:55 -0400 |
|---|---|---|
| committer | Christian König <christian.koenig@amd.com> | 2025-07-18 08:59:24 +0200 |
| commit | 53096728b8910c6916ecc6c46a5abc5c678b58d9 (patch) | |
| tree | 4b64a70ad3874d8da30000aee8370e899a69159d /drivers/gpu/drm/drm_gem.c | |
| parent | drm: document DRM_MODE_PAGE_FLIP_EVENT interactions with atomic (diff) | |
| download | linux-53096728b8910c6916ecc6c46a5abc5c678b58d9.tar.gz linux-53096728b8910c6916ecc6c46a5abc5c678b58d9.zip | |
drm: Add DRM prime interface to reassign GEM handle
CRIU restore of drm buffer objects requires the ability to create
or import a buffer object with a specific gem handle.
Add new drm ioctl DRM_IOCTL_GEM_CHANGE_HANDLE, which takes
the gem handle of an object and moves that object to a
specified new gem handle.
This ioctl needs to call drm_prime_remove_buf_handle,
but that function acquires the prime lock, which the ioctl
needs to hold for other purposes.
Make drm_prime_remove_buf_handle not acquire the prime lock,
and change its other caller to reflect this.
The rest of the kernel patches required to enable CRIU can be
found at
https://lore.kernel.org/dri-devel/20250617194536.538681-1-David.Francis@amd.com/
v2 - Move documentation to UAPI headers
v3 - Always return 0 on success
Signed-off-by: David Francis <David.Francis@amd.com>
Acked-by: Felix Kuehling <felix.kuehling@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Link: https://lore.kernel.org/r/20250717143556.857893-2-David.Francis@amd.com
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
| -rw-r--r-- | drivers/gpu/drm/drm_gem.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 0905ef6786e9..480f91db2e15 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -283,7 +283,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); @@ -934,6 +939,57 @@ err: return ret; } +int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_gem_change_handle *args = data; + struct drm_gem_object *obj; + int ret; + + if (!drm_core_check_feature(dev, DRIVER_GEM)) + return -EOPNOTSUPP; + + obj = drm_gem_object_lookup(file_priv, args->handle); + if (!obj) + return -ENOENT; + + if (args->handle == args->new_handle) + return 0; + + mutex_lock(&file_priv->prime.lock); + + spin_lock(&file_priv->table_lock); + ret = idr_alloc(&file_priv->object_idr, obj, + args->new_handle, args->new_handle + 1, GFP_NOWAIT); + spin_unlock(&file_priv->table_lock); + + if (ret < 0) + goto out_unlock; + + if (obj->dma_buf) { + ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf, args->new_handle); + if (ret < 0) { + spin_lock(&file_priv->table_lock); + idr_remove(&file_priv->object_idr, args->new_handle); + spin_unlock(&file_priv->table_lock); + goto out_unlock; + } + + drm_prime_remove_buf_handle(&file_priv->prime, args->handle); + } + + ret = 0; + + spin_lock(&file_priv->table_lock); + idr_remove(&file_priv->object_idr, args->handle); + spin_unlock(&file_priv->table_lock); + +out_unlock: + mutex_unlock(&file_priv->prime.lock); + + return ret; +} + /** * drm_gem_open - initializes GEM file-private structures at devnode open time * @dev: drm_device which is being opened by userspace |
