[PATCH 3/7] v4l: videobuf2: dma-sg: move some generic functions to memops

2011-04-18 Thread Marek Szyprowski
From: Andrzej Pietrasiewicz andrze...@samsung.com

This patch moves some generic code to videobuf2-memops. This code will
be later used by the iommu allocator. This patch adds also vma locking
in user pointer mode.

Signed-off-by: Andrzej Pietrasiewicz andrze...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
CC: Pawel Osciak pa...@osciak.com
---
 drivers/media/video/videobuf2-dma-sg.c |   37 +--
 drivers/media/video/videobuf2-memops.c |   76 
 include/media/videobuf2-memops.h   |5 ++
 3 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-sg.c 
b/drivers/media/video/videobuf2-dma-sg.c
index b2d9485..240abaa 100644
--- a/drivers/media/video/videobuf2-dma-sg.c
+++ b/drivers/media/video/videobuf2-dma-sg.c
@@ -29,6 +29,7 @@ struct vb2_dma_sg_buf {
struct vb2_dma_sg_desc  sg_desc;
atomic_trefcount;
struct vb2_vmarea_handler   handler;
+   struct vm_area_struct   *vma;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -150,15 +151,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, 
unsigned long vaddr,
if (!buf-pages)
goto userptr_fail_pages_array_alloc;
 
-   down_read(current-mm-mmap_sem);
-   num_pages_from_user = get_user_pages(current, current-mm,
-vaddr  PAGE_MASK,
-buf-sg_desc.num_pages,
-write,
-1, /* force */
-buf-pages,
-NULL);
-   up_read(current-mm-mmap_sem);
+   num_pages_from_user = vb2_get_user_pages(vaddr, buf-sg_desc.num_pages,
+buf-pages, write, buf-vma);
+
if (num_pages_from_user != buf-sg_desc.num_pages)
goto userptr_fail_get_user_pages;
 
@@ -177,6 +172,8 @@ userptr_fail_get_user_pages:
   num_pages_from_user, buf-sg_desc.num_pages);
while (--num_pages_from_user = 0)
put_page(buf-pages[num_pages_from_user]);
+   if (buf-vma)
+   vb2_put_vma(buf-vma);
kfree(buf-pages);
 
 userptr_fail_pages_array_alloc:
@@ -200,6 +197,8 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
   __func__, buf-sg_desc.num_pages);
if (buf-vaddr)
vm_unmap_ram(buf-vaddr, buf-sg_desc.num_pages);
+   if (buf-vma)
+   vb2_put_vma(buf-vma);
while (--i = 0) {
if (buf-write)
set_page_dirty_lock(buf-pages[i]);
@@ -236,28 +235,16 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
 static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
struct vb2_dma_sg_buf *buf = buf_priv;
-   unsigned long uaddr = vma-vm_start;
-   unsigned long usize = vma-vm_end - vma-vm_start;
-   int i = 0;
+   int ret;
 
if (!buf) {
printk(KERN_ERR No memory to map\n);
return -EINVAL;
}
 
-   do {
-   int ret;
-
-   ret = vm_insert_page(vma, uaddr, buf-pages[i++]);
-   if (ret) {
-   printk(KERN_ERR Remapping memory, error: %d\n, ret);
-   return ret;
-   }
-
-   uaddr += PAGE_SIZE;
-   usize -= PAGE_SIZE;
-   } while (usize  0);
-
+   ret = vb2_insert_pages(vma, buf-pages);
+   if (ret)
+   return ret;
 
/*
 * Use common vm_area operations to track buffer refcount.
diff --git a/drivers/media/video/videobuf2-memops.c 
b/drivers/media/video/videobuf2-memops.c
index 5370a3a..9d44473 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -185,6 +185,82 @@ int vb2_mmap_pfn_range(struct vm_area_struct *vma, 
unsigned long paddr,
 EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
 
 /**
+ * vb2_get_user_pages() - pin user pages
+ * @vaddr: virtual address from which to start
+ * @num_pages: number of pages to pin
+ * @pages: table of pointers to struct pages to pin
+ * @write: if 0, the pages must not be written to
+ * @vma:   output parameter, copy of the vma or NULL
+ * if get_user_pages fails
+ *
+ * This function just forwards invocation to get_user_pages, but eases using
+ * the latter in videobuf2 allocators.
+ */
+int vb2_get_user_pages(unsigned long vaddr, unsigned int num_pages,
+  struct page **pages, int write, struct vm_area_struct 
**vma)
+{
+   struct vm_area_struct *found_vma;
+   struct mm_struct *mm = current-mm;
+   int ret = -EFAULT;
+
+   down_read(current-mm-mmap_sem);
+
+   found_vma = find_vma(mm, vaddr);
+

[PATCH 3/7] v4l: videobuf2: dma-sg: move some generic functions to memops

2011-04-05 Thread Marek Szyprowski
From: Andrzej Pietrasiewicz andrze...@samsung.com

This patch moves some generic code to videobuf2-memops. This code will
be later used by the iommu allocator. This patch adds also vma locking
in user pointer mode.

Signed-off-by: Andrzej Pietrasiewicz andrze...@samsung.com
Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com
CC: Pawel Osciak pa...@osciak.com
---
 drivers/media/video/videobuf2-dma-sg.c |   37 +--
 drivers/media/video/videobuf2-memops.c |   76 
 include/media/videobuf2-memops.h   |5 ++
 3 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-sg.c 
b/drivers/media/video/videobuf2-dma-sg.c
index b2d9485..240abaa 100644
--- a/drivers/media/video/videobuf2-dma-sg.c
+++ b/drivers/media/video/videobuf2-dma-sg.c
@@ -29,6 +29,7 @@ struct vb2_dma_sg_buf {
struct vb2_dma_sg_desc  sg_desc;
atomic_trefcount;
struct vb2_vmarea_handler   handler;
+   struct vm_area_struct   *vma;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -150,15 +151,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, 
unsigned long vaddr,
if (!buf-pages)
goto userptr_fail_pages_array_alloc;
 
-   down_read(current-mm-mmap_sem);
-   num_pages_from_user = get_user_pages(current, current-mm,
-vaddr  PAGE_MASK,
-buf-sg_desc.num_pages,
-write,
-1, /* force */
-buf-pages,
-NULL);
-   up_read(current-mm-mmap_sem);
+   num_pages_from_user = vb2_get_user_pages(vaddr, buf-sg_desc.num_pages,
+buf-pages, write, buf-vma);
+
if (num_pages_from_user != buf-sg_desc.num_pages)
goto userptr_fail_get_user_pages;
 
@@ -177,6 +172,8 @@ userptr_fail_get_user_pages:
   num_pages_from_user, buf-sg_desc.num_pages);
while (--num_pages_from_user = 0)
put_page(buf-pages[num_pages_from_user]);
+   if (buf-vma)
+   vb2_put_vma(buf-vma);
kfree(buf-pages);
 
 userptr_fail_pages_array_alloc:
@@ -200,6 +197,8 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
   __func__, buf-sg_desc.num_pages);
if (buf-vaddr)
vm_unmap_ram(buf-vaddr, buf-sg_desc.num_pages);
+   if (buf-vma)
+   vb2_put_vma(buf-vma);
while (--i = 0) {
if (buf-write)
set_page_dirty_lock(buf-pages[i]);
@@ -236,28 +235,16 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
 static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
struct vb2_dma_sg_buf *buf = buf_priv;
-   unsigned long uaddr = vma-vm_start;
-   unsigned long usize = vma-vm_end - vma-vm_start;
-   int i = 0;
+   int ret;
 
if (!buf) {
printk(KERN_ERR No memory to map\n);
return -EINVAL;
}
 
-   do {
-   int ret;
-
-   ret = vm_insert_page(vma, uaddr, buf-pages[i++]);
-   if (ret) {
-   printk(KERN_ERR Remapping memory, error: %d\n, ret);
-   return ret;
-   }
-
-   uaddr += PAGE_SIZE;
-   usize -= PAGE_SIZE;
-   } while (usize  0);
-
+   ret = vb2_insert_pages(vma, buf-pages);
+   if (ret)
+   return ret;
 
/*
 * Use common vm_area operations to track buffer refcount.
diff --git a/drivers/media/video/videobuf2-memops.c 
b/drivers/media/video/videobuf2-memops.c
index 5370a3a..9d44473 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -185,6 +185,82 @@ int vb2_mmap_pfn_range(struct vm_area_struct *vma, 
unsigned long paddr,
 EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
 
 /**
+ * vb2_get_user_pages() - pin user pages
+ * @vaddr: virtual address from which to start
+ * @num_pages: number of pages to pin
+ * @pages: table of pointers to struct pages to pin
+ * @write: if 0, the pages must not be written to
+ * @vma:   output parameter, copy of the vma or NULL
+ * if get_user_pages fails
+ *
+ * This function just forwards invocation to get_user_pages, but eases using
+ * the latter in videobuf2 allocators.
+ */
+int vb2_get_user_pages(unsigned long vaddr, unsigned int num_pages,
+  struct page **pages, int write, struct vm_area_struct 
**vma)
+{
+   struct vm_area_struct *found_vma;
+   struct mm_struct *mm = current-mm;
+   int ret = -EFAULT;
+
+   down_read(current-mm-mmap_sem);
+
+   found_vma = find_vma(mm, vaddr);
+