> -----Original Message----- > From: robdcl...@gmail.com [mailto:robdcl...@gmail.com] On Behalf Of Rob > Clark > Sent: Wednesday, May 16, 2012 5:43 PM > To: Inki Dae > Cc: InKi Dae; kyungmin.p...@samsung.com; sw0312....@samsung.com; dri- > de...@lists.freedesktop.org > Subject: Re: [PATCH 3/4] drm/exynos: added userptr feature. > > On Wed, May 16, 2012 at 12:04 AM, Inki Dae <inki....@samsung.com> wrote: > > > > > >> -----Original Message----- > >> From: robdcl...@gmail.com [mailto:robdcl...@gmail.com] On Behalf Of Rob > >> Clark > >> Sent: Tuesday, May 15, 2012 11:29 PM > >> To: InKi Dae > >> Cc: Inki Dae; kyungmin.p...@samsung.com; sw0312....@samsung.com; dri- > >> de...@lists.freedesktop.org > >> Subject: Re: [PATCH 3/4] drm/exynos: added userptr feature. > >> > >> On Tue, May 15, 2012 at 7:40 AM, InKi Dae <daei...@gmail.com> wrote: > >> > 2012/5/15 Rob Clark <rob.cl...@linaro.org>: > >> >> On Tue, May 15, 2012 at 2:17 AM, Inki Dae <inki....@samsung.com> > wrote: > >> >>> Hi Rob, > >> >>> > >> >>>> -----Original Message----- > >> >>>> From: robdcl...@gmail.com [mailto:robdcl...@gmail.com] On Behalf > Of > >> Rob > >> >>>> Clark > >> >>>> Sent: Tuesday, May 15, 2012 4:35 PM > >> >>>> To: Inki Dae > >> >>>> Cc: airl...@linux.ie; dri-devel@lists.freedesktop.org; > >> >>>> kyungmin.p...@samsung.com; sw0312....@samsung.com > >> >>>> Subject: Re: [PATCH 3/4] drm/exynos: added userptr feature. > >> >>>> > >> >>>> On Mon, Apr 23, 2012 at 7:43 AM, Inki Dae <inki....@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? > >> > > > > Yes, actually, we are using NEON backend of PIXMAN for best performance > > also. like this, PIXMAN's NEON backend for small image and 2D GPU > backend of > > EXA for large image because NEON is faster than 2d gpu for small image > but > > not for large image. > > > >> 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.. > >> > > Right, EFL has a GLES backend and also PIXMAN for software path. > application > > using Elementary can use PIXMAN for software path and also GLES for > hardware > > acceleration. so the purpose of using userptr feature is for buffer > drawn by > > any user using Evas to be rendered by gpu hardware. > > > hmm, I don't suppose it is primarily a one-way transfer (ie. like one > time blit from sw rendered surface to texture)? I'd be more > comfortable w/ an API that somehow just created a temporary mapping > that unpins the pages before the syscall returns, ie. like a > EXYNOS_IOCTL_BLIT_FROM_USERPTR type interface, which does some blit > from a user ptr to a GEM bo. >
You mean use such interface to do BitBLIT instead of using userptr? via driver also uses this way. > BR, > -R > > > > > Thanks, > > Inki Dae > > > >> > 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....@samsung.com> > >> >>>> > Signed-off-by: Kyungmin Park <kyungmin.p...@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(¤t->mm->mmap_sem); > >> >>>> > + get_npages = get_user_pages(current, current->mm, userptr, > >> >>>> > + npages, write, 1, > > buf->pages, > >> >>> NULL); > >> >>>> > + up_read(¤t->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@lists.freedesktop.org > >> >>>> > http://lists.freedesktop.org/mailman/listinfo/dri-devel > >> >>> > >> >>> _______________________________________________ > >> >>> dri-devel mailing list > >> >>> dri-devel@lists.freedesktop.org > >> >>> http://lists.freedesktop.org/mailman/listinfo/dri-devel > >> >> _______________________________________________ > >> >> dri-devel mailing list > >> >> dri-devel@lists.freedesktop.org > >> >> http://lists.freedesktop.org/mailman/listinfo/dri-devel > >> > _______________________________________________ > >> > dri-devel mailing list > >> > dri-devel@lists.freedesktop.org > >> > http://lists.freedesktop.org/mailman/listinfo/dri-devel > > > > _______________________________________________ > > dri-devel mailing list > > dri-devel@lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel