Hello, On Wednesday, January 04, 2012 5:19 PM Javier Martin wrote: > Some video devices need to use contiguous memory > which is not backed by pages as it happens with > vmalloc. This patch provides userptr handling for > those devices. > > --- > Changes since v3: > - Remove vma_res variable. > > Signed-off-by: Javier Martin <javier.martin@xxxxxxxxxxxxxxxxx> Acked-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> Do you plan to put a git tree with all your patches and send a pull request to Mauro? If not I will take this patch and put it on my vb2 branch. > --- > drivers/media/video/videobuf2-vmalloc.c | 70 +++++++++++++++++++++---------- > 1 files changed, 47 insertions(+), 23 deletions(-) > > diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c > index 03aa62f..f9ff15f 100644 > --- a/drivers/media/video/videobuf2-vmalloc.c > +++ b/drivers/media/video/videobuf2-vmalloc.c > @@ -10,6 +10,7 @@ > * the Free Software Foundation. > */ > > +#include <linux/io.h> > #include <linux/module.h> > #include <linux/mm.h> > #include <linux/sched.h> > @@ -22,6 +23,7 @@ > struct vb2_vmalloc_buf { > void *vaddr; > struct page **pages; > + struct vm_area_struct *vma; > int write; > unsigned long size; > unsigned int n_pages; > @@ -71,6 +73,8 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, > struct vb2_vmalloc_buf *buf; > unsigned long first, last; > int n_pages, offset; > + struct vm_area_struct *vma; > + dma_addr_t physp; > > buf = kzalloc(sizeof(*buf), GFP_KERNEL); > if (!buf) > @@ -80,23 +84,37 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, > offset = vaddr & ~PAGE_MASK; > buf->size = size; > > - first = vaddr >> PAGE_SHIFT; > - last = (vaddr + size - 1) >> PAGE_SHIFT; > - buf->n_pages = last - first + 1; > - buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); > - if (!buf->pages) > - goto fail_pages_array_alloc; > > - /* current->mm->mmap_sem is taken by videobuf2 core */ > - n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, > - buf->n_pages, write, 1, /* force */ > - buf->pages, NULL); > - if (n_pages != buf->n_pages) > - goto fail_get_user_pages; > - > - buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); > - if (!buf->vaddr) > - goto fail_get_user_pages; > + vma = find_vma(current->mm, vaddr); > + if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { > + if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) > + goto fail_pages_array_alloc; > + buf->vma = vma; > + buf->vaddr = ioremap_nocache(physp, size); > + if (!buf->vaddr) > + goto fail_pages_array_alloc; > + } else { > + first = vaddr >> PAGE_SHIFT; > + last = (vaddr + size - 1) >> PAGE_SHIFT; > + buf->n_pages = last - first + 1; > + buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), > + GFP_KERNEL); > + if (!buf->pages) > + goto fail_pages_array_alloc; > + > + /* current->mm->mmap_sem is taken by videobuf2 core */ > + n_pages = get_user_pages(current, current->mm, > + vaddr & PAGE_MASK, buf->n_pages, > + write, 1, /* force */ > + buf->pages, NULL); > + if (n_pages != buf->n_pages) > + goto fail_get_user_pages; > + > + buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, > + PAGE_KERNEL); > + if (!buf->vaddr) > + goto fail_get_user_pages; > + } > > buf->vaddr += offset; > return buf; > @@ -120,14 +138,20 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) > unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; > unsigned int i; > > - if (vaddr) > - vm_unmap_ram((void *)vaddr, buf->n_pages); > - for (i = 0; i < buf->n_pages; ++i) { > - if (buf->write) > - set_page_dirty_lock(buf->pages[i]); > - put_page(buf->pages[i]); > + if (buf->pages) { > + if (vaddr) > + vm_unmap_ram((void *)vaddr, buf->n_pages); > + for (i = 0; i < buf->n_pages; ++i) { > + if (buf->write) > + set_page_dirty_lock(buf->pages[i]); > + put_page(buf->pages[i]); > + } > + kfree(buf->pages); > + } else { > + if (buf->vma) > + vb2_put_vma(buf->vma); > + iounmap(buf->vaddr); > } > - kfree(buf->pages); > kfree(buf); > } > > -- Best regards -- Marek Szyprowski Samsung Poland R&D Center -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html