summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2013-04-23 15:27:40 -0700
committerMatthew Pedro <mapedro@nvidia.com>2013-10-16 14:34:15 -0700
commit15814ccc8a511c57182ba3396a1b16af2c648b14 (patch)
treea979f254acfefb1de2553f2478ae6fa4ffe67984
parent6ff867b97f89fa562ab419a4afd2076d8eaf8a13 (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". Bug 1369083 Change-Id: I4629eebe206c7640adf63551968fd89260dd0082 Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/279984 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Allen Martin <amartin@nvidia.com> Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Tested-by: Matthew Pedro <mapedro@nvidia.com>
-rw-r--r--drivers/media/video/videobuf2-dma-nvmap.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/drivers/media/video/videobuf2-dma-nvmap.c b/drivers/media/video/videobuf2-dma-nvmap.c
index 27f43e5a3a57..5ab3c62ac05b 100644
--- a/drivers/media/video/videobuf2-dma-nvmap.c
+++ b/drivers/media/video/videobuf2-dma-nvmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -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,42 @@ 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");
+ pr_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) {
+ pr_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,
@@ -158,8 +186,8 @@ static void *vb2_dma_nvmap_get_userptr(void *alloc_ctx, unsigned long vaddr,
ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr);
if (ret) {
- printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
- vaddr);
+ pr_err("Failed acquiring VMA for vaddr 0x%08lx\n",
+ vaddr);
kfree(buf);
return ERR_PTR(ret);
}