diff options
author | Bryan Wu <pengw@nvidia.com> | 2013-04-23 15:27:40 -0700 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2013-06-12 21:43:53 +0200 |
commit | bb608d8f147839a4c8e53476fb97f1f3eaff3db5 (patch) | |
tree | 4bc26b7847abbf99c9e042aca7b52d5581c2fe9c /drivers/media/video | |
parent | 6a319070d30e2a25805fcd9278a4f10736ee1dea (diff) |
media: videobuf2: fix buffer management issues
Use right buffer flag NVMAP_HANDLE_WRITE_COMBINE to allocate buffer,
which can be shared by VI/CSI and CPU. Don't use NVMAP_HEAP_SYSMEM.
It is validated to old T20 silicon and can't support big buffers. By
default, our nvmap_alloc() will use IOVMM to allocate buffers.
nvmap_pin() gives us IOVA for hardware engines like VI/CSI module
with IOMMU enabled in kernel. nvmap_mmap() gives us VA for CPU
read/write operations. So we need to convert VA address to physical
address of the buffer and map that buffer to user space processor's
memory space "page by page".
Change-Id: I543d9d95fc14395200647e09480f25d9bc001e00
Signed-off-by: Bryan Wu <pengw@nvidia.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/videobuf2-dma-nvmap.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/media/video/videobuf2-dma-nvmap.c b/drivers/media/video/videobuf2-dma-nvmap.c index 27f43e5a3a57..8c3c36c9922f 100644 --- a/drivers/media/video/videobuf2-dma-nvmap.c +++ b/drivers/media/video/videobuf2-dma-nvmap.c @@ -54,7 +54,7 @@ static void *vb2_dma_nvmap_alloc(void *alloc_ctx, unsigned long size) } buf->nvmap_ref = nvmap_alloc(conf->nvmap_client, size, 32, - NVMAP_HANDLE_CACHEABLE, NVMAP_HEAP_SYSMEM); + NVMAP_HANDLE_UNCACHEABLE, 0); if (IS_ERR(buf->nvmap_ref)) { dev_err(conf->dev, "nvmap_alloc failed\n"); ret = -ENOMEM; @@ -134,14 +134,41 @@ static unsigned int vb2_dma_nvmap_num_users(void *buf_priv) static int vb2_dma_nvmap_mmap(void *buf_priv, struct vm_area_struct *vma) { struct vb2_dc_buf *buf = buf_priv; + unsigned long vm_start, paddr; + void * vaddr; + int size; + int ret; if (!buf) { printk(KERN_ERR "No buffer to map\n"); return -EINVAL; } - return vb2_mmap_pfn_range(vma, buf->paddr, buf->size, - &vb2_common_vm_ops, &buf->handler); + size = min_t(unsigned long, vma->vm_end - vma->vm_start, buf->size); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + for (vaddr = buf->vaddr; vaddr < buf->vaddr + size; + vaddr += PAGE_SIZE) { + paddr = page_to_phys(vmalloc_to_page(vaddr)); + vm_start = vma->vm_start + (unsigned long) (vaddr - buf->vaddr); + ret = remap_pfn_range(vma, vm_start, paddr >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot); + if (ret) { + printk(KERN_ERR "Remapping memory failed, error: %d\n", ret); + return ret; + } + pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n", + __func__, paddr, vm_start, PAGE_SIZE); + } + + vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; + vma->vm_private_data = &buf->handler; + vma->vm_ops = &vb2_common_vm_ops; + + vma->vm_ops->open(vma); + + return 0; } static void *vb2_dma_nvmap_get_userptr(void *alloc_ctx, unsigned long vaddr, |