summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2013-04-23 15:27:40 -0700
committerMax Krummenacher <max.krummenacher@toradex.com>2013-06-12 21:43:53 +0200
commitbb608d8f147839a4c8e53476fb97f1f3eaff3db5 (patch)
tree4bc26b7847abbf99c9e042aca7b52d5581c2fe9c
parent6a319070d30e2a25805fcd9278a4f10736ee1dea (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>
-rw-r--r--drivers/media/video/videobuf2-dma-nvmap.c33
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,