[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-06-10 Thread Hans Verkuil
For unclear reasons my SoB was missing in my pull request. So add it now:

Signed-off-by: Hans Verkuil 

Regards,

Hans

On 05/13/15 15:08, Jan Kara wrote:
> Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
> This removes the knowledge about vmas and mmap_sem locking from exynos
> driver. Also it fixes a problem that the function has been mapping user
> provided address without holding mmap_sem.
> 
> Signed-off-by: Jan Kara 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
>  drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 
> -
>  2 files changed, 29 insertions(+), 157 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
> b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 81a250830808..265519c0fe2d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> @@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
>   dma_addr_t  dma_addr;
>   unsigned long   userptr;
>   unsigned long   size;
> - struct page **pages;
> - unsigned intnpages;
> + struct frame_vector *vec;
>   struct sg_table *sgt;
> - struct vm_area_struct   *vma;
>   atomic_trefcount;
>   boolin_pool;
>   boolout_of_list;
> @@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
> *drm_dev,
>  {
>   struct g2d_cmdlist_userptr *g2d_userptr =
>   (struct g2d_cmdlist_userptr *)obj;
> + struct page **pages;
>  
>   if (!obj)
>   return;
> @@ -382,19 +381,21 @@ out:
>   exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
>   DMA_BIDIRECTIONAL);
>  
> - exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
> - g2d_userptr->npages,
> - g2d_userptr->vma);
> + pages = frame_vector_pages(g2d_userptr->vec);
> + if (!IS_ERR(pages)) {
> + int i;
>  
> - exynos_gem_put_vma(g2d_userptr->vma);
> + for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
> + set_page_dirty_lock(pages[i]);
> + }
> + put_vaddr_frames(g2d_userptr->vec);
> + frame_vector_destroy(g2d_userptr->vec);
>  
>   if (!g2d_userptr->out_of_list)
>   list_del_init(_userptr->list);
>  
>   sg_free_table(g2d_userptr->sgt);
>   kfree(g2d_userptr->sgt);
> -
> - drm_free_large(g2d_userptr->pages);
>   kfree(g2d_userptr);
>  }
>  
> @@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> drm_device *drm_dev,
>   struct vm_area_struct *vma;
>   unsigned long start, end;
>   unsigned int npages, offset;
> + struct frame_vector *vec;
>   int ret;
>  
>   if (!size) {
> @@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> drm_device *drm_dev,
>   return ERR_PTR(-ENOMEM);
>  
>   atomic_set(_userptr->refcount, 1);
> + g2d_userptr->size = size;
>  
>   start = userptr & PAGE_MASK;
>   offset = userptr & ~PAGE_MASK;
>   end = PAGE_ALIGN(userptr + size);
>   npages = (end - start) >> PAGE_SHIFT;
> - g2d_userptr->npages = npages;
> -
> - pages = drm_calloc_large(npages, sizeof(struct page *));
> - if (!pages) {
> - DRM_ERROR("failed to allocate pages.\n");
> - ret = -ENOMEM;
> + vec = g2d_userptr->vec = frame_vector_create(npages);
> + if (!vec)
>   goto err_free;
> - }
>  
> - down_read(>mm->mmap_sem);
> - vma = find_vma(current->mm, userptr);
> - if (!vma) {
> - up_read(>mm->mmap_sem);
> - DRM_ERROR("failed to get vm region.\n");
> + ret = get_vaddr_frames(start, npages, 1, 1, vec);
> + if (ret != npages) {
> + DRM_ERROR("failed to get user pages from userptr.\n");
> + if (ret < 0)
> + goto err_destroy_framevec;
>   ret = -EFAULT;
> - goto err_free_pages;
> + goto err_put_framevec;
>   }
> -
> - if (vma->vm_end < userptr + size) {
> - up_read(>mm->mmap_sem);
> - DRM_ERROR("vma is too small.\n");
> + if (frame_vector_to_pages(vec) < 0) {
>   ret = -EFAULT;
> - goto err_free_pages;
> + goto err_put_framevec;
>   }
>  
> - g2d_userptr->vma = exynos_gem_get_vma(vma);
> - if (!g2d_userptr->vma) {
> - up_read(>mm->mmap_sem);
> - DRM_ERROR("failed to copy vma.\n");
> - ret = -ENOMEM;
> - goto err_free_pages;
> - }
> -
> - g2d_userptr->size = size;
> -
> - ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
> - npages, pages, 

[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-14 Thread Inki Dae
Hi,

On 2015년 05월 13일 22:08, Jan Kara wrote:
> Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
> This removes the knowledge about vmas and mmap_sem locking from exynos
> driver. Also it fixes a problem that the function has been mapping user
> provided address without holding mmap_sem.
> 
> Signed-off-by: Jan Kara 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
>  drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 
> -
>  2 files changed, 29 insertions(+), 157 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
> b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 81a250830808..265519c0fe2d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> @@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
>   dma_addr_t  dma_addr;
>   unsigned long   userptr;
>   unsigned long   size;
> - struct page **pages;
> - unsigned intnpages;
> + struct frame_vector *vec;
>   struct sg_table *sgt;
> - struct vm_area_struct   *vma;
>   atomic_trefcount;
>   boolin_pool;
>   boolout_of_list;
> @@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
> *drm_dev,
>  {
>   struct g2d_cmdlist_userptr *g2d_userptr =
>   (struct g2d_cmdlist_userptr *)obj;
> + struct page **pages;
>  
>   if (!obj)
>   return;
> @@ -382,19 +381,21 @@ out:
>   exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
>   DMA_BIDIRECTIONAL);
>  
> - exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
> - g2d_userptr->npages,
> - g2d_userptr->vma);
> + pages = frame_vector_pages(g2d_userptr->vec);
> + if (!IS_ERR(pages)) {
> + int i;
>  
> - exynos_gem_put_vma(g2d_userptr->vma);
> + for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
> + set_page_dirty_lock(pages[i]);
> + }
> + put_vaddr_frames(g2d_userptr->vec);
> + frame_vector_destroy(g2d_userptr->vec);
>  
>   if (!g2d_userptr->out_of_list)
>   list_del_init(_userptr->list);
>  
>   sg_free_table(g2d_userptr->sgt);
>   kfree(g2d_userptr->sgt);
> -
> - drm_free_large(g2d_userptr->pages);
>   kfree(g2d_userptr);
>  }
>  
> @@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> drm_device *drm_dev,
>   struct vm_area_struct *vma;
>   unsigned long start, end;
>   unsigned int npages, offset;
> + struct frame_vector *vec;
>   int ret;
>  
>   if (!size) {
> @@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> drm_device *drm_dev,
>   return ERR_PTR(-ENOMEM);
>  
>   atomic_set(_userptr->refcount, 1);
> + g2d_userptr->size = size;
>  
>   start = userptr & PAGE_MASK;
>   offset = userptr & ~PAGE_MASK;
>   end = PAGE_ALIGN(userptr + size);
>   npages = (end - start) >> PAGE_SHIFT;
> - g2d_userptr->npages = npages;
> -
> - pages = drm_calloc_large(npages, sizeof(struct page *));

The declaration to pages isn't needed anymore because you removed it.

> - if (!pages) {
> - DRM_ERROR("failed to allocate pages.\n");
> - ret = -ENOMEM;
> + vec = g2d_userptr->vec = frame_vector_create(npages);

I think you can use g2d_userptr->vec so it seems that vec isn't needed.

> + if (!vec)
>   goto err_free;
> - }
>  
> - down_read(>mm->mmap_sem);
> - vma = find_vma(current->mm, userptr);

For vma, ditto.

Thanks,
Inki Dae

[--SNIP--]


[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-14 Thread Jan Kara
On Thu 14-05-15 19:51:23, Inki Dae wrote:
> Hi,
> 
> On 2015년 05월 13일 22:08, Jan Kara wrote:
> > Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
> > This removes the knowledge about vmas and mmap_sem locking from exynos
> > driver. Also it fixes a problem that the function has been mapping user
> > provided address without holding mmap_sem.
> > 
> > Signed-off-by: Jan Kara 
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
> >  drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 
> > -
> >  2 files changed, 29 insertions(+), 157 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
> > b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> > index 81a250830808..265519c0fe2d 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> > @@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
> > dma_addr_t  dma_addr;
> > unsigned long   userptr;
> > unsigned long   size;
> > -   struct page **pages;
> > -   unsigned intnpages;
> > +   struct frame_vector *vec;
> > struct sg_table *sgt;
> > -   struct vm_area_struct   *vma;
> > atomic_trefcount;
> > boolin_pool;
> > boolout_of_list;
> > @@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
> > *drm_dev,
> >  {
> > struct g2d_cmdlist_userptr *g2d_userptr =
> > (struct g2d_cmdlist_userptr *)obj;
> > +   struct page **pages;
> >  
> > if (!obj)
> > return;
> > @@ -382,19 +381,21 @@ out:
> > exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
> > DMA_BIDIRECTIONAL);
> >  
> > -   exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
> > -   g2d_userptr->npages,
> > -   g2d_userptr->vma);
> > +   pages = frame_vector_pages(g2d_userptr->vec);
> > +   if (!IS_ERR(pages)) {
> > +   int i;
> >  
> > -   exynos_gem_put_vma(g2d_userptr->vma);
> > +   for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
> > +   set_page_dirty_lock(pages[i]);
> > +   }
> > +   put_vaddr_frames(g2d_userptr->vec);
> > +   frame_vector_destroy(g2d_userptr->vec);
> >  
> > if (!g2d_userptr->out_of_list)
> > list_del_init(_userptr->list);
> >  
> > sg_free_table(g2d_userptr->sgt);
> > kfree(g2d_userptr->sgt);
> > -
> > -   drm_free_large(g2d_userptr->pages);
> > kfree(g2d_userptr);
> >  }
> >  
> > @@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> > drm_device *drm_dev,
> > struct vm_area_struct *vma;
> > unsigned long start, end;
> > unsigned int npages, offset;
> > +   struct frame_vector *vec;
> > int ret;
> >  
> > if (!size) {
> > @@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> > drm_device *drm_dev,
> > return ERR_PTR(-ENOMEM);
> >  
> > atomic_set(_userptr->refcount, 1);
> > +   g2d_userptr->size = size;
> >  
> > start = userptr & PAGE_MASK;
> > offset = userptr & ~PAGE_MASK;
> > end = PAGE_ALIGN(userptr + size);
> > npages = (end - start) >> PAGE_SHIFT;
> > -   g2d_userptr->npages = npages;
> > -
> > -   pages = drm_calloc_large(npages, sizeof(struct page *));
> 
> The declaration to pages isn't needed anymore because you removed it.
> 
> > -   if (!pages) {
> > -   DRM_ERROR("failed to allocate pages.\n");
> > -   ret = -ENOMEM;
> > +   vec = g2d_userptr->vec = frame_vector_create(npages);
> 
> I think you can use g2d_userptr->vec so it seems that vec isn't needed.
> 
> > +   if (!vec)
> > goto err_free;
> > -   }
> >  
> > -   down_read(>mm->mmap_sem);
> > -   vma = find_vma(current->mm, userptr);
> 
> For vma, ditto.
  Thanks for review! Attached is a new version of the patch.

Honza

-- 
Jan Kara 
SUSE Labs, CR
-- next part --
A non-text attachment was scrubbed...
Name: 0001-drm-exynos-Convert-g2d_userptr_get_dma_addr-to-use-g.patch
Type: text/x-patch
Size: 7676 bytes
Desc: not available
URL: 



[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-13 Thread Jan Kara
Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
This removes the knowledge about vmas and mmap_sem locking from exynos
driver. Also it fixes a problem that the function has been mapping user
provided address without holding mmap_sem.

Signed-off-by: Jan Kara 
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 -
 2 files changed, 29 insertions(+), 157 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 81a250830808..265519c0fe2d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
dma_addr_t  dma_addr;
unsigned long   userptr;
unsigned long   size;
-   struct page **pages;
-   unsigned intnpages;
+   struct frame_vector *vec;
struct sg_table *sgt;
-   struct vm_area_struct   *vma;
atomic_trefcount;
boolin_pool;
boolout_of_list;
@@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
*drm_dev,
 {
struct g2d_cmdlist_userptr *g2d_userptr =
(struct g2d_cmdlist_userptr *)obj;
+   struct page **pages;

if (!obj)
return;
@@ -382,19 +381,21 @@ out:
exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
DMA_BIDIRECTIONAL);

-   exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
-   g2d_userptr->npages,
-   g2d_userptr->vma);
+   pages = frame_vector_pages(g2d_userptr->vec);
+   if (!IS_ERR(pages)) {
+   int i;

-   exynos_gem_put_vma(g2d_userptr->vma);
+   for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
+   set_page_dirty_lock(pages[i]);
+   }
+   put_vaddr_frames(g2d_userptr->vec);
+   frame_vector_destroy(g2d_userptr->vec);

if (!g2d_userptr->out_of_list)
list_del_init(_userptr->list);

sg_free_table(g2d_userptr->sgt);
kfree(g2d_userptr->sgt);
-
-   drm_free_large(g2d_userptr->pages);
kfree(g2d_userptr);
 }

@@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
struct vm_area_struct *vma;
unsigned long start, end;
unsigned int npages, offset;
+   struct frame_vector *vec;
int ret;

if (!size) {
@@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
return ERR_PTR(-ENOMEM);

atomic_set(_userptr->refcount, 1);
+   g2d_userptr->size = size;

start = userptr & PAGE_MASK;
offset = userptr & ~PAGE_MASK;
end = PAGE_ALIGN(userptr + size);
npages = (end - start) >> PAGE_SHIFT;
-   g2d_userptr->npages = npages;
-
-   pages = drm_calloc_large(npages, sizeof(struct page *));
-   if (!pages) {
-   DRM_ERROR("failed to allocate pages.\n");
-   ret = -ENOMEM;
+   vec = g2d_userptr->vec = frame_vector_create(npages);
+   if (!vec)
goto err_free;
-   }

-   down_read(>mm->mmap_sem);
-   vma = find_vma(current->mm, userptr);
-   if (!vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get vm region.\n");
+   ret = get_vaddr_frames(start, npages, 1, 1, vec);
+   if (ret != npages) {
+   DRM_ERROR("failed to get user pages from userptr.\n");
+   if (ret < 0)
+   goto err_destroy_framevec;
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}
-
-   if (vma->vm_end < userptr + size) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("vma is too small.\n");
+   if (frame_vector_to_pages(vec) < 0) {
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}

-   g2d_userptr->vma = exynos_gem_get_vma(vma);
-   if (!g2d_userptr->vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to copy vma.\n");
-   ret = -ENOMEM;
-   goto err_free_pages;
-   }
-
-   g2d_userptr->size = size;
-
-   ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
-   npages, pages, vma);
-   if (ret < 0) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get user pages from userptr.\n");
-   goto err_put_vma;
-   }
-
-   up_read(>mm->mmap_sem);
-   g2d_userptr->pages = pages;
-

[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-06 Thread Jan Kara
On Wed 06-05-15 12:47:35, Vlastimil Babka wrote:
> On 05/06/2015 09:28 AM, Jan Kara wrote:
> >Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
> >This removes the knowledge about vmas and mmap_sem locking from exynos
> >driver. Also it fixes a problem that the function has been mapping user
> >provided address without holding mmap_sem.
> >
> >Signed-off-by: Jan Kara 
> >---
> >  drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
> >  drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 
> > -
> >  2 files changed, 29 insertions(+), 157 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
> >b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> >index 81a250830808..265519c0fe2d 100644
> >--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> >+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> ...
> >@@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> >drm_device *drm_dev,
> > return ERR_PTR(-ENOMEM);
> >
> > atomic_set(_userptr->refcount, 1);
> >+g2d_userptr->size = size;
> >
> > start = userptr & PAGE_MASK;
> > offset = userptr & ~PAGE_MASK;
> > end = PAGE_ALIGN(userptr + size);
> > npages = (end - start) >> PAGE_SHIFT;
> >-g2d_userptr->npages = npages;
> >-
> >-pages = drm_calloc_large(npages, sizeof(struct page *));
> >-if (!pages) {
> >-DRM_ERROR("failed to allocate pages.\n");
> >-ret = -ENOMEM;
> >+vec = g2d_userptr->vec = frame_vector_create(npages);
> >+if (!vec)
> > goto err_free;
> >-}
> >
> >-down_read(>mm->mmap_sem);
> >-vma = find_vma(current->mm, userptr);
> >-if (!vma) {
> >-up_read(>mm->mmap_sem);
> >-DRM_ERROR("failed to get vm region.\n");
> >+ret = get_vaddr_frames(start, npages, 1, 1, vec);
> 
> Use true instead of 1.
  Yes, thanks!

Honza
-- 
Jan Kara 
SUSE Labs, CR


[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-06 Thread Vlastimil Babka
On 05/06/2015 09:28 AM, Jan Kara wrote:
> Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
> This removes the knowledge about vmas and mmap_sem locking from exynos
> driver. Also it fixes a problem that the function has been mapping user
> provided address without holding mmap_sem.
>
> Signed-off-by: Jan Kara 
> ---
>   drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
>   drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 
> -
>   2 files changed, 29 insertions(+), 157 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
> b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 81a250830808..265519c0fe2d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
...
> @@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
> drm_device *drm_dev,
>   return ERR_PTR(-ENOMEM);
>
>   atomic_set(_userptr->refcount, 1);
> + g2d_userptr->size = size;
>
>   start = userptr & PAGE_MASK;
>   offset = userptr & ~PAGE_MASK;
>   end = PAGE_ALIGN(userptr + size);
>   npages = (end - start) >> PAGE_SHIFT;
> - g2d_userptr->npages = npages;
> -
> - pages = drm_calloc_large(npages, sizeof(struct page *));
> - if (!pages) {
> - DRM_ERROR("failed to allocate pages.\n");
> - ret = -ENOMEM;
> + vec = g2d_userptr->vec = frame_vector_create(npages);
> + if (!vec)
>   goto err_free;
> - }
>
> - down_read(>mm->mmap_sem);
> - vma = find_vma(current->mm, userptr);
> - if (!vma) {
> - up_read(>mm->mmap_sem);
> - DRM_ERROR("failed to get vm region.\n");
> + ret = get_vaddr_frames(start, npages, 1, 1, vec);

Use true instead of 1.



[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-06 Thread Jan Kara
Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
This removes the knowledge about vmas and mmap_sem locking from exynos
driver. Also it fixes a problem that the function has been mapping user
provided address without holding mmap_sem.

Signed-off-by: Jan Kara 
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 89 ++
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 -
 2 files changed, 29 insertions(+), 157 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 81a250830808..265519c0fe2d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
dma_addr_t  dma_addr;
unsigned long   userptr;
unsigned long   size;
-   struct page **pages;
-   unsigned intnpages;
+   struct frame_vector *vec;
struct sg_table *sgt;
-   struct vm_area_struct   *vma;
atomic_trefcount;
boolin_pool;
boolout_of_list;
@@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
*drm_dev,
 {
struct g2d_cmdlist_userptr *g2d_userptr =
(struct g2d_cmdlist_userptr *)obj;
+   struct page **pages;

if (!obj)
return;
@@ -382,19 +381,21 @@ out:
exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
DMA_BIDIRECTIONAL);

-   exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
-   g2d_userptr->npages,
-   g2d_userptr->vma);
+   pages = frame_vector_pages(g2d_userptr->vec);
+   if (!IS_ERR(pages)) {
+   int i;

-   exynos_gem_put_vma(g2d_userptr->vma);
+   for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
+   set_page_dirty_lock(pages[i]);
+   }
+   put_vaddr_frames(g2d_userptr->vec);
+   frame_vector_destroy(g2d_userptr->vec);

if (!g2d_userptr->out_of_list)
list_del_init(_userptr->list);

sg_free_table(g2d_userptr->sgt);
kfree(g2d_userptr->sgt);
-
-   drm_free_large(g2d_userptr->pages);
kfree(g2d_userptr);
 }

@@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
struct vm_area_struct *vma;
unsigned long start, end;
unsigned int npages, offset;
+   struct frame_vector *vec;
int ret;

if (!size) {
@@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
return ERR_PTR(-ENOMEM);

atomic_set(_userptr->refcount, 1);
+   g2d_userptr->size = size;

start = userptr & PAGE_MASK;
offset = userptr & ~PAGE_MASK;
end = PAGE_ALIGN(userptr + size);
npages = (end - start) >> PAGE_SHIFT;
-   g2d_userptr->npages = npages;
-
-   pages = drm_calloc_large(npages, sizeof(struct page *));
-   if (!pages) {
-   DRM_ERROR("failed to allocate pages.\n");
-   ret = -ENOMEM;
+   vec = g2d_userptr->vec = frame_vector_create(npages);
+   if (!vec)
goto err_free;
-   }

-   down_read(>mm->mmap_sem);
-   vma = find_vma(current->mm, userptr);
-   if (!vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get vm region.\n");
+   ret = get_vaddr_frames(start, npages, 1, 1, vec);
+   if (ret != npages) {
+   DRM_ERROR("failed to get user pages from userptr.\n");
+   if (ret < 0)
+   goto err_destroy_framevec;
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}
-
-   if (vma->vm_end < userptr + size) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("vma is too small.\n");
+   if (frame_vector_to_pages(vec) < 0) {
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}

-   g2d_userptr->vma = exynos_gem_get_vma(vma);
-   if (!g2d_userptr->vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to copy vma.\n");
-   ret = -ENOMEM;
-   goto err_free_pages;
-   }
-
-   g2d_userptr->size = size;
-
-   ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
-   npages, pages, vma);
-   if (ret < 0) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get user pages from userptr.\n");
-   goto err_put_vma;
-   }
-
-   up_read(>mm->mmap_sem);
-   g2d_userptr->pages = pages;
-

[PATCH 9/9] drm/exynos: Convert g2d_userptr_get_dma_addr() to use get_vaddr_frames()

2015-05-05 Thread Jan Kara
Convert g2d_userptr_get_dma_addr() to pin pages using get_vaddr_frames().
This removes the knowledge about vmas and mmap_sem locking from exynos
driver. Also it fixes a problem that the function has been mapping user
provided address without holding mmap_sem.

Signed-off-by: Jan Kara 
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 91 ++-
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 97 -
 2 files changed, 30 insertions(+), 158 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 81a250830808..65eb38797fd3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -190,10 +190,8 @@ struct g2d_cmdlist_userptr {
dma_addr_t  dma_addr;
unsigned long   userptr;
unsigned long   size;
-   struct page **pages;
-   unsigned intnpages;
+   struct frame_vector *vec;
struct sg_table *sgt;
-   struct vm_area_struct   *vma;
atomic_trefcount;
boolin_pool;
boolout_of_list;
@@ -363,6 +361,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device 
*drm_dev,
 {
struct g2d_cmdlist_userptr *g2d_userptr =
(struct g2d_cmdlist_userptr *)obj;
+   struct page **pages;

if (!obj)
return;
@@ -382,19 +381,21 @@ out:
exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
DMA_BIDIRECTIONAL);

-   exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
-   g2d_userptr->npages,
-   g2d_userptr->vma);
+   pages = frame_vector_pages(g2d_userptr->vec);
+   if (!IS_ERR(pages)) {
+   int i;

-   exynos_gem_put_vma(g2d_userptr->vma);
+   for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++)
+   set_page_dirty_lock(pages[i]);
+   }
+   put_vaddr_frames(g2d_userptr->vec);
+   frame_vector_destroy(g2d_userptr->vec);

if (!g2d_userptr->out_of_list)
list_del_init(_userptr->list);

sg_free_table(g2d_userptr->sgt);
kfree(g2d_userptr->sgt);
-
-   drm_free_large(g2d_userptr->pages);
kfree(g2d_userptr);
 }

@@ -413,6 +414,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
struct vm_area_struct *vma;
unsigned long start, end;
unsigned int npages, offset;
+   struct frame_vector *vec;
int ret;

if (!size) {
@@ -456,65 +458,37 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
return ERR_PTR(-ENOMEM);

atomic_set(_userptr->refcount, 1);
+   g2d_userptr->size = size;

start = userptr & PAGE_MASK;
offset = userptr & ~PAGE_MASK;
end = PAGE_ALIGN(userptr + size);
npages = (end - start) >> PAGE_SHIFT;
-   g2d_userptr->npages = npages;
+   vec = g2d_userptr->vec = frame_vector_create(npages);
+   if (!vec)
+   goto out_free;

-   pages = drm_calloc_large(npages, sizeof(struct page *));
-   if (!pages) {
-   DRM_ERROR("failed to allocate pages.\n");
-   ret = -ENOMEM;
-   goto err_free;
-   }
-
-   down_read(>mm->mmap_sem);
-   vma = find_vma(current->mm, userptr);
-   if (!vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get vm region.\n");
+   ret = get_vaddr_frames(start, npages, 1, 1, vec);
+   if (ret != npages) {
+   DRM_ERROR("failed to get user pages from userptr.\n");
+   if (ret < 0)
+   goto err_destroy_framevec;
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}
-
-   if (vma->vm_end < userptr + size) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("vma is too small.\n");
+   if (frame_vector_to_pages(vec) < 0) {
ret = -EFAULT;
-   goto err_free_pages;
+   goto err_put_framevec;
}

-   g2d_userptr->vma = exynos_gem_get_vma(vma);
-   if (!g2d_userptr->vma) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to copy vma.\n");
-   ret = -ENOMEM;
-   goto err_free_pages;
-   }
-
-   g2d_userptr->size = size;
-
-   ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
-   npages, pages, vma);
-   if (ret < 0) {
-   up_read(>mm->mmap_sem);
-   DRM_ERROR("failed to get user pages from userptr.\n");
-   goto err_put_vma;
-   }
-
-   up_read(>mm->mmap_sem);
-