[PATCH v2] drm/vgem: implement virtual GEM
Rob Clark
robdclark at gmail.com
Sat Jan 31 10:32:45 PST 2015
On Sat, Jan 31, 2015 at 1:13 PM, Ben Widawsky <ben at bwidawsk.net> 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 at 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 at chromium.org>
>> > Signed-off-by: Adam Jackson <ajax at redhat.com>
>> > Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
>> > Signed-off-by: Zach Reizner <zachr at google.com>
>>
>> couple small suggestions/comments below, but with those addressed,
>>
>> Reviewed-by: Rob Clark <robdclark at 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 at redhat.com>
>> > + * Ben Widawsky <ben at 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.
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;
>> > +}
>> > +
More information about the dri-devel
mailing list