[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