On Sat, Jan 31, 2015 at 11:02:05AM -0500, Rob Clark wrote:
On Fri, Jan 30, 2015 at 1:05 PM, Zach Reizner zachr@google.com wrote:
This patch implements the virtual GEM driver with PRIME sharing which allows vgem to import a gem object from other drivers for the purpose of mmap-ing them to userspace. The mmap is done using the mmap operation exported by other drivers.
v2: remove platform_device and do not attach to dma bufs
Reviewed-by: Stéphane Marchesin marcheu@chromium.org Signed-off-by: Adam Jackson ajax@redhat.com Signed-off-by: Ben Widawsky ben@bwidawsk.net Signed-off-by: Zach Reizner zachr@google.com
couple small suggestions/comments below, but with those addressed,
Reviewed-by: Rob Clark robdclark@gmail.com
drivers/gpu/drm/Kconfig | 9 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/vgem/Makefile | 4 + drivers/gpu/drm/vgem/vgem_dma_buf.c | 96 +++++++++ drivers/gpu/drm/vgem/vgem_drv.c | 390 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vgem/vgem_drv.h | 57 ++++++ 6 files changed, 557 insertions(+) create mode 100644 drivers/gpu/drm/vgem/Makefile create mode 100644 drivers/gpu/drm/vgem/vgem_dma_buf.c create mode 100644 drivers/gpu/drm/vgem/vgem_drv.c create mode 100644 drivers/gpu/drm/vgem/vgem_drv.h
[snip]
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c new file mode 100644 index 0000000..e20f4a4 --- /dev/null +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -0,0 +1,390 @@ +/*
- Copyright 2011 Red Hat, Inc.
- Copyright © 2014 The Chromium OS Authors
- 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
- on the rights to use, copy, modify, merge, publish, distribute, sub
- license, and/or sell copies of the Software, and to permit persons to whom
- them 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 MERCHANTIBILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS 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:
Adam Jackson <ajax@redhat.com>
Ben Widawsky <ben@bwidawsk.net>
- */
+/**
- This is vgem, a (non-hardware-backed) GEM service. This is used by Mesa's
- software renderer and the X server for efficient buffer sharing.
- */
+#include <linux/module.h> +#include <linux/ramfs.h> +#include <linux/shmem_fs.h> +#include <linux/dma-buf.h> +#include "vgem_drv.h"
+#define DRIVER_NAME "vgem" +#define DRIVER_DESC "Virtual GEM provider" +#define DRIVER_DATE "20120112" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0
+void vgem_gem_put_pages(struct drm_vgem_gem_object *obj) +{
int num_pages = obj->base.size / PAGE_SIZE;
int i;
for (i = 0; i < num_pages; i++) {
if (obj->pages[i] == NULL)
break;
seems like other than this break statement, you could use drm_gem_put_pages().. not entirely sure why you'd encounter a null page, but if there is a legit reason for that, then just add the check in drm_gem_put_pages() (plus maybe a comment) and use that..
First, this code predated drm_gem_put_pages, so it was probably just an oversight that a consolidated function existed. As for the NULL, it's because the cleanup of failed vgem get_pages() just calls vgem put_pages() (you can't have sparsely populated entries, but the last n pointers can be NULL). If the helpers just dtrt, then it should use that.
page_cache_release(obj->pages[i]);
}
drm_free_large(obj->pages);
obj->pages = NULL;
+}
+static void vgem_gem_free_object(struct drm_gem_object *obj) +{
struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
drm_gem_free_mmap_offset(obj);
if (vgem_obj->use_dma_buf && obj->dma_buf) {
dma_buf_put(obj->dma_buf);
obj->dma_buf = NULL;
}
drm_gem_object_release(obj);
if (vgem_obj->pages)
vgem_gem_put_pages(vgem_obj);
vgem_obj->pages = NULL;
kfree(vgem_obj);
+}
+int vgem_gem_get_pages(struct drm_vgem_gem_object *obj) +{
struct address_space *mapping;
gfp_t gfpmask = GFP_KERNEL;
int num_pages, i, ret = 0;
if (obj->pages || obj->use_dma_buf)
return 0;
num_pages = obj->base.size / PAGE_SIZE;
obj->pages = drm_malloc_ab(num_pages, sizeof(struct page *));
if (obj->pages == NULL)
return -ENOMEM;
mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
again, seems like you could use drm_gem_get_pages().. although you get the mapping in a slightly different way.. not sure if that was intentional?
Again, this predates the helpers :D My original patches on top of ajax were from Feb. 2012. Helpers seem like the right thing to do now.
BR, -R
gfpmask |= mapping_gfp_mask(mapping);
for (i = 0; i < num_pages; i++) {
struct page *page;
obj->pages[i] = NULL;
page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
if (IS_ERR(page)) {
ret = PTR_ERR(page);
goto err_out;
}
obj->pages[i] = page;
}
return ret;
+err_out:
vgem_gem_put_pages(obj);
return ret;
+}