Signed-off-by: Jan Kara <j...@suse.cz>
---
 drivers/media/v4l2-core/videobuf2-dma-sg.c | 85 ++++++------------------------
 1 file changed, 15 insertions(+), 70 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ef0b3f765d8e..a37ee0fa84d3 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -33,6 +33,7 @@ module_param(debug, int, 0644);
 struct vb2_dma_sg_buf {
        void                            *vaddr;
        struct page                     **pages;
+       struct pinned_pfns              *pfns;
        int                             write;
        int                             offset;
        struct sg_table                 sg_table;
@@ -166,9 +167,10 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, 
struct pinned_pfns **ppfn,
                                    int write)
 {
        struct vb2_dma_sg_buf *buf;
-       unsigned long first, last;
-       int num_pages_from_user;
-       struct vm_area_struct *vma;
+       struct pinned_pfns *pfns = *ppfn;
+
+       if (pfns_vector_to_pages(pfns))
+               return NULL;
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
@@ -178,75 +180,20 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, 
struct pinned_pfns **ppfn,
        buf->write = write;
        buf->offset = vaddr & ~PAGE_MASK;
        buf->size = size;
-
-       first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
-       last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
-       buf->num_pages = last - first + 1;
-
-       buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
-                            GFP_KERNEL);
-       if (!buf->pages)
-               goto userptr_fail_alloc_pages;
-
-       vma = find_vma(current->mm, vaddr);
-       if (!vma) {
-               dprintk(1, "no vma for address %lu\n", vaddr);
-               goto userptr_fail_find_vma;
-       }
-
-       if (vma->vm_end < vaddr + size) {
-               dprintk(1, "vma at %lu is too small for %lu bytes\n",
-                       vaddr, size);
-               goto userptr_fail_find_vma;
-       }
-
-       buf->vma = vb2_get_vma(vma);
-       if (!buf->vma) {
-               dprintk(1, "failed to copy vma\n");
-               goto userptr_fail_find_vma;
-       }
-
-       if (vma_is_io(buf->vma)) {
-               for (num_pages_from_user = 0;
-                    num_pages_from_user < buf->num_pages;
-                    ++num_pages_from_user, vaddr += PAGE_SIZE) {
-                       unsigned long pfn;
-
-                       if (follow_pfn(buf->vma, vaddr, &pfn)) {
-                               dprintk(1, "no page for address %lu\n", vaddr);
-                               break;
-                       }
-                       buf->pages[num_pages_from_user] = pfn_to_page(pfn);
-               }
-       } else
-               num_pages_from_user = get_user_pages(current, current->mm,
-                                            vaddr & PAGE_MASK,
-                                            buf->num_pages,
-                                            write,
-                                            1, /* force */
-                                            buf->pages,
-                                            NULL);
-
-       if (num_pages_from_user != buf->num_pages)
-               goto userptr_fail_get_user_pages;
+       buf->pages = pfns_vector_pages(pfns);
+       buf->num_pages = pfns_vector_count(pfns);
 
        if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
                        buf->num_pages, buf->offset, size, 0))
-               goto userptr_fail_alloc_table_from_pages;
+               goto fail;
+
+       buf->pfns = pfns;
+       /* Clear *ppfn so that the caller doesn't free the vector */
+       *ppfn = NULL;
 
        return buf;
 
-userptr_fail_alloc_table_from_pages:
-userptr_fail_get_user_pages:
-       dprintk(1, "get_user_pages requested/got: %d/%d]\n",
-               buf->num_pages, num_pages_from_user);
-       if (!vma_is_io(buf->vma))
-               while (--num_pages_from_user >= 0)
-                       put_page(buf->pages[num_pages_from_user]);
-       vb2_put_vma(buf->vma);
-userptr_fail_find_vma:
-       kfree(buf->pages);
-userptr_fail_alloc_pages:
+fail:
        kfree(buf);
        return NULL;
 }
@@ -268,11 +215,9 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
        while (--i >= 0) {
                if (buf->write)
                        set_page_dirty_lock(buf->pages[i]);
-               if (!vma_is_io(buf->vma))
-                       put_page(buf->pages[i]);
        }
-       kfree(buf->pages);
-       vb2_put_vma(buf->vma);
+       put_vaddr_pfns(buf->pfns);
+       pfns_vector_destroy(buf->pfns);
        kfree(buf);
 }
 
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to