[PATCH 5/7] drm/vgem: prime export support

Ben Widawsky ben at bwidawsk.net
Wed Feb 22 11:29:18 PST 2012


dma-buf export implementation. Heavily influenced by Dave Airlie's proof
of concept work.

Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
Cc: Dave Airlie <airlied at redhat.com>
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 drivers/gpu/drm/vgem/Makefile       |    2 +-
 drivers/gpu/drm/vgem/vgem_dma_buf.c |  128 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vgem/vgem_drv.c     |    6 ++
 drivers/gpu/drm/vgem/vgem_drv.h     |    7 ++
 4 files changed, 142 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/vgem/vgem_dma_buf.c

diff --git a/drivers/gpu/drm/vgem/Makefile b/drivers/gpu/drm/vgem/Makefile
index 3f4c7b8..1055cb7 100644
--- a/drivers/gpu/drm/vgem/Makefile
+++ b/drivers/gpu/drm/vgem/Makefile
@@ -1,4 +1,4 @@
 ccflags-y := -Iinclude/drm
-vgem-y := vgem_drv.o
+vgem-y := vgem_drv.o vgem_dma_buf.o
 
 obj-$(CONFIG_DRM_VGEM)	+= vgem.o
diff --git a/drivers/gpu/drm/vgem/vgem_dma_buf.c b/drivers/gpu/drm/vgem/vgem_dma_buf.c
new file mode 100644
index 0000000..eca9445
--- /dev/null
+++ b/drivers/gpu/drm/vgem/vgem_dma_buf.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Ben Widawsky <ben at bwidawsk.net>
+ *
+ */
+
+#include <linux/dma-buf.h>
+#include "vgem_drv.h"
+
+#define VGEM_FD_PERMS 0600
+
+struct sg_table *vgem_gem_map_dma_buf(struct dma_buf_attachment *attachment,
+                                      enum dma_data_direction dir)
+{
+	struct drm_vgem_gem_object *obj = attachment->dmabuf->priv;
+	struct sg_table *sg;
+	int ret;
+
+	ret = vgem_gem_get_pages(obj);
+	if (ret) {
+		vgem_gem_put_pages(obj);
+		return NULL;
+	}
+
+	BUG_ON(obj->pages == NULL);
+
+	sg = drm_prime_pages_to_sg(obj->pages, obj->base.size / PAGE_SIZE);
+	return sg;
+}
+
+void vgem_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
+			    struct sg_table *sg)
+{
+	sg_free_table(sg);
+	kfree(sg);
+}
+
+void vgem_gem_release(struct dma_buf *buf)
+{
+	struct drm_vgem_gem_object *obj = buf->priv;
+
+	BUG_ON(buf != obj->base.export_dma_buf);
+
+	obj->base.prime_fd = -1;
+	obj->base.export_dma_buf = NULL;
+	drm_gem_object_unreference_unlocked(&obj->base);
+}
+
+struct dma_buf_ops vgem_dmabuf_ops = {
+	.map_dma_buf = vgem_gem_map_dma_buf,
+	.unmap_dma_buf = vgem_gem_unmap_dma_buf,
+	.release = vgem_gem_release
+};
+
+int vgem_prime_to_fd(struct drm_device *dev, struct drm_file *file,
+		     uint32_t handle, int *prime_fd)
+{
+	struct drm_vgem_file_private *file_priv = file->driver_priv;
+	struct drm_vgem_gem_object *obj;
+	int ret;
+
+	DRM_DEBUG_PRIME("Request fd for handle %d\n", handle);
+
+	obj = to_vgem_bo(drm_gem_object_lookup(dev, file, handle));
+	if (!obj)
+		return -EBADF;
+
+	/* This means a user has already called get_fd on this */
+	if (obj->base.prime_fd != -1) {
+		DRM_DEBUG_PRIME("User requested a previously exported buffer "
+				"%d %d\n", handle, obj->base.prime_fd);
+		drm_gem_object_unreference(&obj->base);
+		goto out_fd;
+	}
+
+	/* Make a dma buf out of our vgem object */
+	obj->base.export_dma_buf = dma_buf_export(obj, &vgem_dmabuf_ops,
+						  obj->base.size,
+						  VGEM_FD_PERMS);
+	if (IS_ERR(obj->base.export_dma_buf)) {
+		DRM_DEBUG_PRIME("export fail\n");
+		return PTR_ERR(obj->base.export_dma_buf);
+	} else
+		obj->base.prime_fd = dma_buf_fd(obj->base.export_dma_buf);
+
+	mutex_lock(&dev->prime_mutex);
+	ret = drm_prime_insert_fd_handle_mapping(&file_priv->prime,
+						 obj->base.export_dma_buf,
+						 handle);
+	WARN_ON(ret);
+	ret = drm_prime_add_dma_buf(dev, &obj->base);
+	mutex_unlock(&dev->prime_mutex);
+	if (ret)
+		return ret;
+
+out_fd:
+	*prime_fd = obj->base.prime_fd;
+
+	return 0;
+}
+
+int vgem_prime_to_handle(struct drm_device *dev,
+			 struct drm_file *file, int prime_fd,
+			 uint32_t *handle)
+{
+	return 0;
+}
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
index cd6ab42..9cd1ed4 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.c
+++ b/drivers/gpu/drm/vgem/vgem_drv.c
@@ -71,12 +71,15 @@ static int vgem_open(struct drm_device *dev, struct drm_file *file)
 
 	file->driver_priv = file_priv;
 
+	drm_prime_init_file_private(&file_priv->prime);
+
 	return 0;
 }
 
 static void vgem_preclose(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_vgem_file_private *file_priv = file->driver_priv;
+	drm_prime_destroy_file_private(&file_priv->prime);
 	kfree(file_priv);
 }
 
@@ -312,6 +315,9 @@ static struct drm_driver vgem_driver = {
 	.dumb_create		= vgem_gem_dumb_create,
 	.dumb_map_offset	= vgem_gem_dumb_map,
 
+	.prime_handle_to_fd	= vgem_prime_to_fd,
+	.prime_fd_to_handle	= vgem_prime_to_handle,
+
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
 	.date	= DRIVER_DATE,
diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h
index ca63fa0b..56d1c0f 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.h
+++ b/drivers/gpu/drm/vgem/vgem_drv.h
@@ -42,6 +42,7 @@ struct drm_vgem_gem_object {
 };
 
 struct drm_vgem_file_private {
+	struct drm_prime_file_private prime;
 };
 
 /* vgem_drv.c */
@@ -49,6 +50,12 @@ extern void vgem_gem_put_pages(struct drm_vgem_gem_object *obj);
 extern int vgem_gem_get_pages(struct drm_vgem_gem_object *obj);
 
 /* vgem_dma_buf.c */
+extern int vgem_prime_to_fd(struct drm_device *dev,
+			    struct drm_file *file_priv,
+			    uint32_t handle, int *prime_fd);
 
+extern int vgem_prime_to_handle(struct drm_device *dev,
+				struct drm_file *file_priv,
+				int prime_fd, uint32_t *handle);
 
 #endif
-- 
1.7.9.1



More information about the dri-devel mailing list