diff mbox series

[RFC,15/19] drm/pagemap/util: Add file descriptors pointing to struct drm_pagemap

Message ID 20250312210416.3120-16-thomas.hellstrom@linux.intel.com (mailing list archive)
State New
Headers show
Series drm, drm/xe: Multi-device GPUSVM | expand

Commit Message

Thomas Hellström March 12, 2025, 9:04 p.m. UTC
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.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/drm_pagemap_util.c | 78 ++++++++++++++++++++++++++++++
 include/drm/drm_pagemap_util.h     |  4 ++
 2 files changed, 82 insertions(+)
diff mbox series

Patch

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