[PATCH 3/4] drm/exynos: added userptr feature.

Rob Clark rob.clark at linaro.org
Tue May 15 07:28:31 PDT 2012


On Tue, May 15, 2012 at 7:40 AM, InKi Dae <daeinki at gmail.com> wrote:
> 2012/5/15 Rob Clark <rob.clark at linaro.org>:
>> On Tue, May 15, 2012 at 2:17 AM, Inki Dae <inki.dae at samsung.com> wrote:
>>> Hi Rob,
>>>
>>>> -----Original Message-----
>>>> From: robdclark at gmail.com [mailto:robdclark at gmail.com] On Behalf Of Rob
>>>> Clark
>>>> Sent: Tuesday, May 15, 2012 4:35 PM
>>>> To: Inki Dae
>>>> Cc: airlied at linux.ie; dri-devel at lists.freedesktop.org;
>>>> kyungmin.park at samsung.com; sw0312.kim at samsung.com
>>>> Subject: Re: [PATCH 3/4] drm/exynos: added userptr feature.
>>>>
>>>> On Mon, Apr 23, 2012 at 7:43 AM, Inki Dae <inki.dae at samsung.com> wrote:
>>>> > this feature could be used to use memory region allocated by malloc() in
>>>> user
>>>> > mode and mmaped memory region allocated by other memory allocators.
>>>> userptr
>>>> > interface can identify memory type through vm_flags value and would get
>>>> > pages or page frame numbers to user space appropriately.
>>>>
>>>> I apologize for being a little late to jump in on this thread, but...
>>>>
>>>> I must confess to not being a huge fan of userptr.  It really is
>>>> opening a can of worms, and seems best avoided if at all possible.
>>>> I'm not entirely sure the use-case for which you require this, but I
>>>> wonder if there isn't an alternative way?   I mean, the main case I
>>>> could think of for mapping userspace memory would be something like
>>>> texture upload.  But could that be handled in an alternative way,
>>>> something like a pwrite or texture_upload API, which could temporarily
>>>> pin the userspace memory, kick off a dma from that user buffer to a
>>>> proper GEM buffer, and then unpin the user buffer when the DMA
>>>> completes?
>>>>
>>>
>>> This feature have being discussed with drm and linux-mm guys and I have
>>> posted this patch four times.
>>> So please, see below e-mail threads.
>>> http://www.spinics.net/lists/dri-devel/msg22729.html
>>>
>>> and then please, give me your opinions.
>>
>>
>> Yeah, I read that and understand that the purpose is to support
>> malloc()'d memory (and btw, all the other changes like limits to the
>> amount of userptr buffers are good if we do decide to support userptr
>> buffers).  But my question was more about why do you need to support
>> malloc'd buffers... other than "just because v4l2 does" ;-)
>>
>> I don't really like the userptr feature in v4l2 either, and view it as
>> a necessary evil because at the time there was nothing like dmabuf.
>> But now that we have dmabuf to share buffers with zero copy between
>> two devices, to we *really* still need userptr?
>>
>
> Definitely no, as I mentioned on this email thread, we are using the
> userptr feature for pixman and evas
> backend to use gpu acceleration directly(zero-copy). as you may know,
> Evas is part of the Enlightenment Foundation Libraries(EFL) and
> Elementary for pixman. all the applicaions based on them uses user
> address to draw something so the backends(such as gpu accelerators)
> can refer to only the user address to the buffer rendered. do you
> think we can avoid memory copy to use those GPUs without such userptr
> feature? I think there is no way and only the way that the gpu uses
> the user address to render without memory copy. and as mentioned on
> this thread, this feature had been tried by i915 in the desktop world.
> for this, you can refer to Daniel's comments.

oh, yeah, for something like pixman it is hard to accelerate.  But I
wonder if there is still some benefit.  I don't know as much about
evas, but pixman is assumed to be a synchronous API, so you must
always block until the operation completes which looses a lot of the
potential benefit of a blitter.  And also I think you have no control
over when the client free()'s a buffer.  So you end up having to
map/unmap the buffer to the gpu/blitter/whatever every single
operation.  Not to mention possible need for cache operations, etc.  I
wonder if trying to accel it in hw really brings any benefit vs just
using NEON?

I thought EFL has a GLES backend..  I could be wrong about that, but
if it does probably you'd get better performance by using the GLES
backend vs trying to accelerate what is intended as a sw path..

> and as you know, note that we are already using dmabuf to share a
> buffer between device drivers or v4l2 and drm framework. for this, we
> also tested drm prime feature with v4l2 world and we applied umm
> concept to ump for 3d gpu(known as mali) also.
>
> Anyway, this userptr feature is different from your thought. and maybe
> you also need such feature for performance enhancement. Please give me
> any idea if you have any good way instead of this userptr fearure.
> there may be any good idea I don't know.

well, I just try and point people to APIs that are actually designed
with hw acceleration in mind in the first place (x11/EXA, GLES, etc)
;-)

There missing really an API for client side 2d accel.  Well, I guess
there is OpenVG, although I'm not sure if anyone actually ever used
it.. maybe we do need something for better supporting 2d blitters in
weston compositor, for example.

BR,
-R


> Thanks,
> Inki Dae
>
>> I guess if I understood better the use-case, maybe I could try to
>> think of some alternatives.
>>
>> BR,
>> -R
>>
>>> Thanks,
>>> Inki Dae
>>>
>>>> BR,
>>>> -R
>>>>
>>>> > Signed-off-by: Inki Dae <inki.dae at samsung.com>
>>>> > Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>>>> > ---
>>>> >  drivers/gpu/drm/exynos/exynos_drm_drv.c |    2 +
>>>> >  drivers/gpu/drm/exynos/exynos_drm_gem.c |  258
>>>> +++++++++++++++++++++++++++++++
>>>> >  drivers/gpu/drm/exynos/exynos_drm_gem.h |   13 ++-
>>>> >  include/drm/exynos_drm.h                |   25 +++-
>>>> >  4 files changed, 296 insertions(+), 2 deletions(-)
>>>> >
>>>> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>>> b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>>> > index f58a487..5bb0361 100644
>>>> > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>>> > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
>>>> > @@ -211,6 +211,8 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
>>>> >                        DRM_AUTH),
>>>> >        DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
>>>> >                        exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED |
>>> DRM_AUTH),
>>>> > +       DRM_IOCTL_DEF_DRV(EXYNOS_GEM_USERPTR,
>>>> > +                       exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED),
>>>> >        DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS,
>>>> exynos_plane_set_zpos_ioctl,
>>>> >                        DRM_UNLOCKED | DRM_AUTH),
>>>> >        DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
>>>> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>>> b/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>>> > index afd0cd4..b68d4ea 100644
>>>> > --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>>> > +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>>> > @@ -66,6 +66,43 @@ static int check_gem_flags(unsigned int flags)
>>>> >        return 0;
>>>> >  }
>>>> >
>>>> > +static struct vm_area_struct *get_vma(struct vm_area_struct *vma)
>>>> > +{
>>>> > +       struct vm_area_struct *vma_copy;
>>>> > +
>>>> > +       vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
>>>> > +       if (!vma_copy)
>>>> > +               return NULL;
>>>> > +
>>>> > +       if (vma->vm_ops && vma->vm_ops->open)
>>>> > +               vma->vm_ops->open(vma);
>>>> > +
>>>> > +       if (vma->vm_file)
>>>> > +               get_file(vma->vm_file);
>>>> > +
>>>> > +       memcpy(vma_copy, vma, sizeof(*vma));
>>>> > +
>>>> > +       vma_copy->vm_mm = NULL;
>>>> > +       vma_copy->vm_next = NULL;
>>>> > +       vma_copy->vm_prev = NULL;
>>>> > +
>>>> > +       return vma_copy;
>>>> > +}
>>>> > +
>>>> > +static void put_vma(struct vm_area_struct *vma)
>>>> > +{
>>>> > +       if (!vma)
>>>> > +               return;
>>>> > +
>>>> > +       if (vma->vm_ops && vma->vm_ops->close)
>>>> > +               vma->vm_ops->close(vma);
>>>> > +
>>>> > +       if (vma->vm_file)
>>>> > +               fput(vma->vm_file);
>>>> > +
>>>> > +       kfree(vma);
>>>> > +}
>>>> > +
>>>> >  static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj,
>>>> >                                        struct vm_area_struct *vma)
>>>> >  {
>>>> > @@ -254,6 +291,41 @@ static void exynos_drm_gem_put_pages(struct
>>>> drm_gem_object *obj)
>>>> >        /* add some codes for UNCACHED type here. TODO */
>>>> >  }
>>>> >
>>>> > +static void exynos_drm_put_userptr(struct drm_gem_object *obj)
>>>> > +{
>>>> > +       struct exynos_drm_gem_obj *exynos_gem_obj;
>>>> > +       struct exynos_drm_gem_buf *buf;
>>>> > +       struct vm_area_struct *vma;
>>>> > +       int npages;
>>>> > +
>>>> > +       exynos_gem_obj = to_exynos_gem_obj(obj);
>>>> > +       buf = exynos_gem_obj->buffer;
>>>> > +       vma = exynos_gem_obj->vma;
>>>> > +
>>>> > +       if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
>>>> > +               put_vma(exynos_gem_obj->vma);
>>>> > +               goto out;
>>>> > +       }
>>>> > +
>>>> > +       npages = buf->size >> PAGE_SHIFT;
>>>> > +
>>>> > +       npages--;
>>>> > +       while (npages >= 0) {
>>>> > +               if (buf->write)
>>>> > +                       set_page_dirty_lock(buf->pages[npages]);
>>>> > +
>>>> > +               put_page(buf->pages[npages]);
>>>> > +               npages--;
>>>> > +       }
>>>> > +
>>>> > +out:
>>>> > +       kfree(buf->pages);
>>>> > +       buf->pages = NULL;
>>>> > +
>>>> > +       kfree(buf->sgt);
>>>> > +       buf->sgt = NULL;
>>>> > +}
>>>> > +
>>>> >  static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
>>>> >                                        struct drm_file *file_priv,
>>>> >                                        unsigned int *handle)
>>>> > @@ -293,6 +365,8 @@ void exynos_drm_gem_destroy(struct
>>>> exynos_drm_gem_obj *exynos_gem_obj)
>>>> >
>>>> >        if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG)
>>>> >                exynos_drm_gem_put_pages(obj);
>>>> > +       else if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR)
>>>> > +               exynos_drm_put_userptr(obj);
>>>> >        else
>>>> >                exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags,
>>> buf);
>>>> >
>>>> > @@ -606,6 +680,190 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device
>>>> *dev, void *data,
>>>> >        return 0;
>>>> >  }
>>>> >
>>>> > +static int exynos_drm_get_userptr(struct drm_device *dev,
>>>> > +                               struct exynos_drm_gem_obj *obj,
>>>> > +                               unsigned long userptr,
>>>> > +                               unsigned int write)
>>>> > +{
>>>> > +       unsigned int get_npages;
>>>> > +       unsigned long npages = 0;
>>>> > +       struct vm_area_struct *vma;
>>>> > +       struct exynos_drm_gem_buf *buf = obj->buffer;
>>>> > +
>>>> > +       vma = find_vma(current->mm, userptr);
>>>> > +
>>>> > +       /* the memory region mmaped with VM_PFNMAP. */
>>>> > +       if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
>>>> > +               unsigned long this_pfn, prev_pfn, pa;
>>>> > +               unsigned long start, end, offset;
>>>> > +               struct scatterlist *sgl;
>>>> > +
>>>> > +               start = userptr;
>>>> > +               offset = userptr & ~PAGE_MASK;
>>>> > +               end = start + buf->size;
>>>> > +               sgl = buf->sgt->sgl;
>>>> > +
>>>> > +               for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
>>>> > +                       int ret = follow_pfn(vma, start, &this_pfn);
>>>> > +                       if (ret)
>>>> > +                               return ret;
>>>> > +
>>>> > +                       if (prev_pfn == 0)
>>>> > +                               pa = this_pfn << PAGE_SHIFT;
>>>> > +                       else if (this_pfn != prev_pfn + 1)
>>>> > +                               return -EFAULT;
>>>> > +
>>>> > +                       sg_dma_address(sgl) = (pa + offset);
>>>> > +                       sg_dma_len(sgl) = PAGE_SIZE;
>>>> > +                       prev_pfn = this_pfn;
>>>> > +                       pa += PAGE_SIZE;
>>>> > +                       npages++;
>>>> > +                       sgl = sg_next(sgl);
>>>> > +               }
>>>> > +
>>>> > +               buf->dma_addr = pa + offset;
>>>> > +
>>>> > +               obj->vma = get_vma(vma);
>>>> > +               if (!obj->vma)
>>>> > +                       return -ENOMEM;
>>>> > +
>>>> > +               buf->pfnmap = true;
>>>> > +
>>>> > +               return npages;
>>>> > +       }
>>>> > +
>>>> > +       buf->write = write;
>>>> > +       npages = buf->size >> PAGE_SHIFT;
>>>> > +
>>>> > +       down_read(&current->mm->mmap_sem);
>>>> > +       get_npages = get_user_pages(current, current->mm, userptr,
>>>> > +                                       npages, write, 1, buf->pages,
>>> NULL);
>>>> > +       up_read(&current->mm->mmap_sem);
>>>> > +       if (get_npages != npages)
>>>> > +               DRM_ERROR("failed to get user_pages.\n");
>>>> > +
>>>> > +       buf->pfnmap = false;
>>>> > +
>>>> > +       return get_npages;
>>>> > +}
>>>> > +
>>>> > +int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
>>>> > +                                     struct drm_file *file_priv)
>>>> > +{
>>>> > +       struct exynos_drm_gem_obj *exynos_gem_obj;
>>>> > +       struct drm_exynos_gem_userptr *args = data;
>>>> > +       struct exynos_drm_gem_buf *buf;
>>>> > +       struct scatterlist *sgl;
>>>> > +       unsigned long size, userptr;
>>>> > +       unsigned int npages;
>>>> > +       int ret, get_npages;
>>>> > +
>>>> > +       DRM_DEBUG_KMS("%s\n", __FILE__);
>>>> > +
>>>> > +       if (!args->size) {
>>>> > +               DRM_ERROR("invalid size.\n");
>>>> > +               return -EINVAL;
>>>> > +       }
>>>> > +
>>>> > +       ret = check_gem_flags(args->flags);
>>>> > +       if (ret)
>>>> > +               return ret;
>>>> > +
>>>> > +       size = roundup_gem_size(args->size, EXYNOS_BO_USERPTR);
>>>> > +       userptr = args->userptr;
>>>> > +
>>>> > +       buf = exynos_drm_init_buf(dev, size);
>>>> > +       if (!buf)
>>>> > +               return -ENOMEM;
>>>> > +
>>>> > +       exynos_gem_obj = exynos_drm_gem_init(dev, size);
>>>> > +       if (!exynos_gem_obj) {
>>>> > +               ret = -ENOMEM;
>>>> > +               goto err_free_buffer;
>>>> > +       }
>>>> > +
>>>> > +       buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
>>>> > +       if (!buf->sgt) {
>>>> > +               DRM_ERROR("failed to allocate buf->sgt.\n");
>>>> > +               ret = -ENOMEM;
>>>> > +               goto err_release_gem;
>>>> > +       }
>>>> > +
>>>> > +       npages = size >> PAGE_SHIFT;
>>>> > +
>>>> > +       ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL);
>>>> > +       if (ret < 0) {
>>>> > +               DRM_ERROR("failed to initailize sg table.\n");
>>>> > +               goto err_free_sgt;
>>>> > +       }
>>>> > +
>>>> > +       buf->pages = kzalloc(npages * sizeof(struct page *),
>>> GFP_KERNEL);
>>>> > +       if (!buf->pages) {
>>>> > +               DRM_ERROR("failed to allocate buf->pages\n");
>>>> > +               ret = -ENOMEM;
>>>> > +               goto err_free_table;
>>>> > +       }
>>>> > +
>>>> > +       exynos_gem_obj->buffer = buf;
>>>> > +
>>>> > +       get_npages = exynos_drm_get_userptr(dev, exynos_gem_obj,
>>> userptr,
>>>> 1);
>>>> > +       if (get_npages != npages) {
>>>> > +               DRM_ERROR("failed to get user_pages.\n");
>>>> > +               ret = get_npages;
>>>> > +               goto err_release_userptr;
>>>> > +       }
>>>> > +
>>>> > +       ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base,
>>>> file_priv,
>>>> > +                                               &args->handle);
>>>> > +       if (ret < 0) {
>>>> > +               DRM_ERROR("failed to create gem handle.\n");
>>>> > +               goto err_release_userptr;
>>>> > +       }
>>>> > +
>>>> > +       sgl = buf->sgt->sgl;
>>>> > +
>>>> > +       /*
>>>> > +        * if buf->pfnmap is true then update sgl of sgt with pages but
>>>> > +        * if buf->pfnmap is false then it means the sgl was updated
>>>> already
>>>> > +        * so it doesn't need to update the sgl.
>>>> > +        */
>>>> > +       if (!buf->pfnmap) {
>>>> > +               unsigned int i = 0;
>>>> > +
>>>> > +               /* set all pages to sg list. */
>>>> > +               while (i < npages) {
>>>> > +                       sg_set_page(sgl, buf->pages[i], PAGE_SIZE, 0);
>>>> > +                       sg_dma_address(sgl) =
>>> page_to_phys(buf->pages[i]);
>>>> > +                       i++;
>>>> > +                       sgl = sg_next(sgl);
>>>> > +               }
>>>> > +       }
>>>> > +
>>>> > +       /* always use EXYNOS_BO_USERPTR as memory type for userptr. */
>>>> > +       exynos_gem_obj->flags |= EXYNOS_BO_USERPTR;
>>>> > +
>>>> > +       return 0;
>>>> > +
>>>> > +err_release_userptr:
>>>> > +       get_npages--;
>>>> > +       while (get_npages >= 0)
>>>> > +               put_page(buf->pages[get_npages--]);
>>>> > +       kfree(buf->pages);
>>>> > +       buf->pages = NULL;
>>>> > +err_free_table:
>>>> > +       sg_free_table(buf->sgt);
>>>> > +err_free_sgt:
>>>> > +       kfree(buf->sgt);
>>>> > +       buf->sgt = NULL;
>>>> > +err_release_gem:
>>>> > +       drm_gem_object_release(&exynos_gem_obj->base);
>>>> > +       kfree(exynos_gem_obj);
>>>> > +       exynos_gem_obj = NULL;
>>>> > +err_free_buffer:
>>>> > +       exynos_drm_free_buf(dev, 0, buf);
>>>> > +       return ret;
>>>> > +}
>>>> > +
>>>> >  int exynos_drm_gem_init_object(struct drm_gem_object *obj)
>>>> >  {
>>>> >        DRM_DEBUG_KMS("%s\n", __FILE__);
>>>> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h
>>>> b/drivers/gpu/drm/exynos/exynos_drm_gem.h
>>>> > index efc8252..1de2241 100644
>>>> > --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
>>>> > +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
>>>> > @@ -29,7 +29,8 @@
>>>> >  #define to_exynos_gem_obj(x)   container_of(x,\
>>>> >                        struct exynos_drm_gem_obj, base)
>>>> >
>>>> > -#define IS_NONCONTIG_BUFFER(f)         (f & EXYNOS_BO_NONCONTIG)
>>>> > +#define IS_NONCONTIG_BUFFER(f)         ((f & EXYNOS_BO_NONCONTIG) ||\
>>>> > +                                       (f & EXYNOS_BO_USERPTR))
>>>> >
>>>> >  /*
>>>> >  * exynos drm gem buffer structure.
>>>> > @@ -38,18 +39,23 @@
>>>> >  * @dma_addr: bus address(accessed by dma) to allocated memory region.
>>>> >  *     - this address could be physical address without IOMMU and
>>>> >  *     device address with IOMMU.
>>>> > + * @write: whether pages will be written to by the caller.
>>>> >  * @sgt: sg table to transfer page data.
>>>> >  * @pages: contain all pages to allocated memory region.
>>>> >  * @page_size: could be 4K, 64K or 1MB.
>>>> >  * @size: size of allocated memory region.
>>>> > + * @pfnmap: indicate whether memory region from userptr is mmaped with
>>>> > + *     VM_PFNMAP or not.
>>>> >  */
>>>> >  struct exynos_drm_gem_buf {
>>>> >        void __iomem            *kvaddr;
>>>> >        dma_addr_t              dma_addr;
>>>> > +       unsigned int            write;
>>>> >        struct sg_table         *sgt;
>>>> >        struct page             **pages;
>>>> >        unsigned long           page_size;
>>>> >        unsigned long           size;
>>>> > +       bool                    pfnmap;
>>>> >  };
>>>> >
>>>> >  /*
>>>> > @@ -73,6 +79,7 @@ struct exynos_drm_gem_obj {
>>>> >        struct drm_gem_object           base;
>>>> >        struct exynos_drm_gem_buf       *buffer;
>>>> >        unsigned long                   size;
>>>> > +       struct vm_area_struct           *vma;
>>>> >        unsigned int                    flags;
>>>> >  };
>>>> >
>>>> > @@ -127,6 +134,10 @@ int exynos_drm_gem_map_offset_ioctl(struct
>>>> drm_device *dev, void *data,
>>>> >  int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
>>>> >                              struct drm_file *file_priv);
>>>> >
>>>> > +/* map user space allocated by malloc to pages. */
>>>> > +int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
>>>> > +                                     struct drm_file *file_priv);
>>>> > +
>>>> >  /* initialize gem object. */
>>>> >  int exynos_drm_gem_init_object(struct drm_gem_object *obj);
>>>> >
>>>> > diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
>>>> > index 2d6eb06..48eda6e 100644
>>>> > --- a/include/drm/exynos_drm.h
>>>> > +++ b/include/drm/exynos_drm.h
>>>> > @@ -75,6 +75,23 @@ struct drm_exynos_gem_mmap {
>>>> >  };
>>>> >
>>>> >  /**
>>>> > + * User-requested user space importing structure
>>>> > + *
>>>> > + * @userptr: user space address allocated by malloc.
>>>> > + * @size: size to the buffer allocated by malloc.
>>>> > + * @flags: indicate user-desired cache attribute to map the allocated
>>>> buffer
>>>> > + *     to kernel space.
>>>> > + * @handle: a returned handle to created gem object.
>>>> > + *     - this handle will be set by gem module of kernel side.
>>>> > + */
>>>> > +struct drm_exynos_gem_userptr {
>>>> > +       uint64_t userptr;
>>>> > +       uint64_t size;
>>>> > +       unsigned int flags;
>>>> > +       unsigned int handle;
>>>> > +};
>>>> > +
>>>> > +/**
>>>> >  * A structure for user connection request of virtual display.
>>>> >  *
>>>> >  * @connection: indicate whether doing connetion or not by user.
>>>> > @@ -105,13 +122,16 @@ enum e_drm_exynos_gem_mem_type {
>>>> >        EXYNOS_BO_CACHABLE      = 1 << 1,
>>>> >        /* write-combine mapping. */
>>>> >        EXYNOS_BO_WC            = 1 << 2,
>>>> > +       /* user space memory allocated by malloc. */
>>>> > +       EXYNOS_BO_USERPTR       = 1 << 3,
>>>> >        EXYNOS_BO_MASK          = EXYNOS_BO_NONCONTIG |
>>> EXYNOS_BO_CACHABLE
>>>> |
>>>> > -                                       EXYNOS_BO_WC
>>>> > +                                       EXYNOS_BO_WC | EXYNOS_BO_USERPTR
>>>> >  };
>>>> >
>>>> >  #define DRM_EXYNOS_GEM_CREATE          0x00
>>>> >  #define DRM_EXYNOS_GEM_MAP_OFFSET      0x01
>>>> >  #define DRM_EXYNOS_GEM_MMAP            0x02
>>>> > +#define DRM_EXYNOS_GEM_USERPTR         0x03
>>>> >  /* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
>>>> >  #define DRM_EXYNOS_PLANE_SET_ZPOS      0x06
>>>> >  #define DRM_EXYNOS_VIDI_CONNECTION     0x07
>>>> > @@ -125,6 +145,9 @@ enum e_drm_exynos_gem_mem_type {
>>>> >  #define DRM_IOCTL_EXYNOS_GEM_MMAP      DRM_IOWR(DRM_COMMAND_BASE + \
>>>> >                DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
>>>> >
>>>> > +#define DRM_IOCTL_EXYNOS_GEM_USERPTR   DRM_IOWR(DRM_COMMAND_BASE + \
>>>> > +               DRM_EXYNOS_GEM_USERPTR, struct drm_exynos_gem_userptr)
>>>> > +
>>>> >  #define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS
>>>  DRM_IOWR(DRM_COMMAND_BASE
>>>> + \
>>>> >                DRM_EXYNOS_PLANE_SET_ZPOS, struct
>>> drm_exynos_plane_set_zpos)
>>>> >
>>>> > --
>>>> > 1.7.4.1
>>>> >
>>>> > _______________________________________________
>>>> > dri-devel mailing list
>>>> > dri-devel at lists.freedesktop.org
>>>> > http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list