Falicitate implementing uapi representing a struct drm_pagemap as a file descriptor.
A drm_pagemap file descriptor holds, while open, a reference to the struct drm_pagemap and to the drm_pagemap_helper module. Signed-off-by: Thomas Hellström <thomas.hellst...@linux.intel.com> --- drivers/gpu/drm/drm_pagemap_util.c | 78 ++++++++++++++++++++++++++++++ include/drm/drm_pagemap_util.h | 4 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/gpu/drm/drm_pagemap_util.c b/drivers/gpu/drm/drm_pagemap_util.c index ae8f78cde4a7..4bcd7b8927ee 100644 --- a/drivers/gpu/drm/drm_pagemap_util.c +++ b/drivers/gpu/drm/drm_pagemap_util.c @@ -3,6 +3,8 @@ * Copyright © 2025 Intel Corporation */ +#include <linux/anon_inodes.h> +#include <linux/file.h> #include <linux/slab.h> #include <drm/drm_pagemap.h> @@ -123,3 +125,79 @@ int drm_pagemap_acquire_owner(struct drm_pagemap_peer *peer, return 0; } EXPORT_SYMBOL(drm_pagemap_acquire_owner); + +static int drm_pagemap_file_release(struct inode *inode, struct file *file) +{ + drm_pagemap_put(file->private_data); + + return 0; +} + +static const struct file_operations drm_pagemap_fops = { + .owner = THIS_MODULE, + .release = drm_pagemap_file_release, +}; + +/** + * drm_pagemap_fd() - Obtain an fd that can be used to reference a drm_pagemap. + * @dpagemap: The drm_pagemap for which to obtain an fd. + * + * Obtain an fd that can be used to reference a drm_pagemap using the function + * drm_pagemap_from_fd(). The fd has a reference count on the drm_pagemap, and + * on this module. When the fd is closed and the underlying struct file is + * released, the references are dropped. + */ +int drm_pagemap_fd(struct drm_pagemap *dpagemap) +{ + struct file *file; + int fd; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) + return fd; + + file = anon_inode_getfile("drm_pagemap_file", + &drm_pagemap_fops, + dpagemap, 0); + if (IS_ERR(file)) { + put_unused_fd(fd); + return PTR_ERR(file); + } + + drm_pagemap_get(dpagemap); + fd_install(fd, file); + + return fd; +} +EXPORT_SYMBOL(drm_pagemap_fd); + +/** + * drm_pagemap_from_fd() - Get a drm_pagemap from a file descriptor + * @fd: The file descriptor + * + * Return a reference-counted pointer to a drm_pagemap from + * a file-descriptor, typically obtained from drm_pagemap_fd(). + * The pagemap pointer should be put using drm_pagemap_put() when + * no longer in use. + * + * Return: A valid drm_pagemap pointer on success. Error pointer on failure. + */ +struct drm_pagemap *drm_pagemap_from_fd(unsigned int fd) +{ + struct file *file = fget(fd); + struct drm_pagemap *dpagemap; + + if (!file) + return ERR_PTR(-ENOENT); + + if (file->f_op != &drm_pagemap_fops) { + fput(file); + return ERR_PTR(-ENOENT); + } + + dpagemap = drm_pagemap_get(file->private_data); + fput(file); + + return dpagemap; +} +EXPORT_SYMBOL(drm_pagemap_from_fd); diff --git a/include/drm/drm_pagemap_util.h b/include/drm/drm_pagemap_util.h index 03731c79493f..8f9676a469fb 100644 --- a/include/drm/drm_pagemap_util.h +++ b/include/drm/drm_pagemap_util.h @@ -52,4 +52,8 @@ int drm_pagemap_acquire_owner(struct drm_pagemap_peer *peer, struct drm_pagemap_owner_list *owner_list, bool (*has_interconnect)(struct drm_pagemap_peer *peer1, struct drm_pagemap_peer *peer2)); + +int drm_pagemap_fd(struct drm_pagemap *dpagemap); + +struct drm_pagemap *drm_pagemap_from_fd(unsigned int fd); #endif -- 2.48.1