[PATCH 3/7] v4l: videobuf2: dma-sg: move some generic functions to memops
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
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); +