mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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
This commit is contained in:
parent
b9a572f471
commit
53096728b8
|
|
@ -283,7 +283,12 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
|
||||||
if (obj->funcs->close)
|
if (obj->funcs->close)
|
||||||
obj->funcs->close(obj, file_priv);
|
obj->funcs->close(obj, file_priv);
|
||||||
|
|
||||||
|
mutex_lock(&file_priv->prime.lock);
|
||||||
|
|
||||||
drm_prime_remove_buf_handle(&file_priv->prime, id);
|
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_vma_node_revoke(&obj->vma_node, file_priv);
|
||||||
|
|
||||||
drm_gem_object_handle_put_unlocked(obj);
|
drm_gem_object_handle_put_unlocked(obj);
|
||||||
|
|
@ -934,6 +939,57 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
||||||
return ret;
|
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
|
* drm_gem_open - initializes GEM file-private structures at devnode open time
|
||||||
* @dev: drm_device which is being opened by userspace
|
* @dev: drm_device which is being opened by userspace
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
|
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
|
||||||
void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
|
void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
|
||||||
|
int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
||||||
|
struct dma_buf *dma_buf, uint32_t handle);
|
||||||
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
||||||
uint32_t handle);
|
uint32_t handle);
|
||||||
|
|
||||||
|
|
@ -168,6 +170,8 @@ int drm_gem_close_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
|
int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv);
|
||||||
int drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
int drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
|
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
|
||||||
|
|
|
||||||
|
|
@ -653,6 +653,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
|
||||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW),
|
DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW),
|
||||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
|
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
|
||||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
|
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
|
||||||
|
DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_gem_change_handle_ioctl, DRM_RENDER_ALLOW),
|
||||||
|
|
||||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0),
|
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ struct drm_prime_member {
|
||||||
struct rb_node handle_rb;
|
struct rb_node handle_rb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
||||||
struct dma_buf *dma_buf, uint32_t handle)
|
struct dma_buf *dma_buf, uint32_t handle)
|
||||||
{
|
{
|
||||||
struct drm_prime_member *member;
|
struct drm_prime_member *member;
|
||||||
|
|
@ -190,8 +190,6 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
||||||
{
|
{
|
||||||
struct rb_node *rb;
|
struct rb_node *rb;
|
||||||
|
|
||||||
mutex_lock(&prime_fpriv->lock);
|
|
||||||
|
|
||||||
rb = prime_fpriv->handles.rb_node;
|
rb = prime_fpriv->handles.rb_node;
|
||||||
while (rb) {
|
while (rb) {
|
||||||
struct drm_prime_member *member;
|
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;
|
rb = rb->rb_left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&prime_fpriv->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
|
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
|
||||||
|
|
|
||||||
|
|
@ -625,6 +625,21 @@ struct drm_gem_open {
|
||||||
__u64 size;
|
__u64 size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct drm_gem_change_handle - Argument for &DRM_IOCTL_GEM_CHANGE_HANDLE ioctl.
|
||||||
|
* @handle: The handle of a gem object.
|
||||||
|
* @new_handle: An available gem handle.
|
||||||
|
*
|
||||||
|
* This ioctl changes the handle of a GEM object to the specified one.
|
||||||
|
* The new handle must be unused. On success the old handle is closed
|
||||||
|
* and all further IOCTL should refer to the new handle only.
|
||||||
|
* Calls to DRM_IOCTL_PRIME_FD_TO_HANDLE will return the new handle.
|
||||||
|
*/
|
||||||
|
struct drm_gem_change_handle {
|
||||||
|
__u32 handle;
|
||||||
|
__u32 new_handle;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRM_CAP_DUMB_BUFFER
|
* DRM_CAP_DUMB_BUFFER
|
||||||
*
|
*
|
||||||
|
|
@ -1309,6 +1324,14 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define DRM_IOCTL_SET_CLIENT_NAME DRM_IOWR(0xD1, struct drm_set_client_name)
|
#define DRM_IOCTL_SET_CLIENT_NAME DRM_IOWR(0xD1, struct drm_set_client_name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DRM_IOCTL_GEM_CHANGE_HANDLE - Move an object to a different handle
|
||||||
|
*
|
||||||
|
* Some applications (notably CRIU) need objects to have specific gem handles.
|
||||||
|
* This ioctl changes the object at one gem handle to use a new gem handle.
|
||||||
|
*/
|
||||||
|
#define DRM_IOCTL_GEM_CHANGE_HANDLE DRM_IOWR(0xD2, struct drm_gem_change_handle)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device specific ioctls should only be in their respective headers
|
* Device specific ioctls should only be in their respective headers
|
||||||
* The device specific ioctl range is from 0x40 to 0x9f.
|
* The device specific ioctl range is from 0x40 to 0x9f.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user