On Sat, Jan 31, 2015 at 1:13 PM, Ben Widawsky <ben@xxxxxxxxxxxx> wrote: > 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@xxxxxxxxxx> 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@xxxxxxxxxxxx> >> > Signed-off-by: Adam Jackson <ajax@xxxxxxxxxx> >> > Signed-off-by: Ben Widawsky <ben@xxxxxxxxxxxx> >> > Signed-off-by: Zach Reizner <zachr@xxxxxxxxxx> >> >> couple small suggestions/comments below, but with those addressed, >> >> Reviewed-by: Rob Clark <robdclark@xxxxxxxxx> >> >> > --- >> > 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@xxxxxxxxxx> >> > + * Ben Widawsky <ben@xxxxxxxxxxxx> >> > + */ >> > + >> > +/** >> > + * 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. yeah, ok, that makes sense.. The helpers dtrt.. drm_gem_get_pages() cleans up properly if it fails part way through. So should be a drop-in replacement, and make the new driver that much smaller :-) BR, -R > >> > + 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; >> > +} >> > + _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel