summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorVandana Salve <vsalve@nvidia.com>2013-08-01 14:04:16 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-16 17:40:30 -0700
commitb69791bbd98eb94019c32f588712d9b71a3f1b02 (patch)
tree85ee6427997e80bfabca7b07a1f216a83b8a95f4 /drivers/base
parent1ee511a9d9fe4cb83bb7db74c58287bd51f76145 (diff)
drivers: dma-coherent: support coherent memory declaration with no kernel mapping
Add DMA_MEMORY_NOMAP flag to avoid creation of kernel virtual mapping during the declaration of DMA coherent memory. This would allow managing carveout memories via dma-coherent API with no impact on kernel VMALLOC space. bug 898152 Change-Id: I700fbfc83716516d15a97f1e18ad0b1a8154a0a9 Signed-off-by: Vandana Salve <vsalve@nvidia.com> Reviewed-on: http://git-master/r/267938 Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/dma-coherent.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index bc256b641027..7e4d53183b4a 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -23,7 +23,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
- if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+ if ((flags &
+ (DMA_MEMORY_MAP | DMA_MEMORY_IO | DMA_MEMORY_NOMAP)) == 0)
goto out;
if (!size)
goto out;
@@ -32,10 +33,6 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
- mem_base = ioremap(bus_addr, size);
- if (!mem_base)
- goto out;
-
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto out;
@@ -43,7 +40,15 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
if (!dev->dma_mem->bitmap)
goto free1_out;
+ if (flags & DMA_MEMORY_NOMAP)
+ goto skip_mapping;
+
+ mem_base = ioremap(bus_addr, size);
+ if (!mem_base)
+ goto out;
dev->dma_mem->virt_base = mem_base;
+
+skip_mapping:
dev->dma_mem->device_base = device_addr;
dev->dma_mem->pfn_base = PFN_DOWN(bus_addr);
dev->dma_mem->size = pages;
@@ -52,6 +57,9 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
+ if (flags & DMA_MEMORY_NOMAP)
+ return DMA_MEMORY_NOMAP;
+
return DMA_MEMORY_IO;
free1_out:
@@ -70,7 +78,10 @@ void dma_release_declared_memory(struct device *dev)
if (!mem)
return;
dev->dma_mem = NULL;
- iounmap(mem->virt_base);
+
+ if (!(mem->flags & DMA_MEMORY_NOMAP))
+ iounmap(mem->virt_base);
+
kfree(mem->bitmap);
kfree(mem);
}
@@ -136,8 +147,10 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
* Memory was found in the per-device area.
*/
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
- *ret = mem->virt_base + (pageno << PAGE_SHIFT);
- memset(*ret, 0, size);
+ if (!(mem->flags & DMA_MEMORY_NOMAP)) {
+ *ret = mem->virt_base + (pageno << PAGE_SHIFT);
+ memset(*ret, 0, size);
+ }
return 1;
@@ -167,11 +180,20 @@ EXPORT_SYMBOL(dma_alloc_from_coherent);
int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+ void *mem_addr;
+
+ if (!mem)
+ return 0;
- if (mem && vaddr >= mem->virt_base && vaddr <
- (mem->virt_base + (mem->size << PAGE_SHIFT))) {
- int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+ if (mem->flags & DMA_MEMORY_NOMAP)
+ mem_addr = (void *)mem->device_base;
+ else
+ mem_addr = mem->virt_base;
+ if (mem && vaddr >= mem_addr && vaddr <
+ (mem_addr + (mem->size << PAGE_SHIFT))) {
+
+ int page = (vaddr - mem_addr) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
return 1;
}
@@ -198,11 +220,20 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
void *vaddr, size_t size, int *ret)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+ void *mem_addr;
+
+ if (!mem)
+ return 0;
+
+ if (mem->flags & DMA_MEMORY_NOMAP)
+ mem_addr = (void *)mem->device_base;
+ else
+ mem_addr = mem->virt_base;
- if (mem && vaddr >= mem->virt_base && vaddr + size <=
- (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+ if (mem && vaddr >= mem_addr && vaddr + size <=
+ (mem_addr + (mem->size << PAGE_SHIFT))) {
unsigned long off = vma->vm_pgoff;
- int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+ int start = (vaddr - mem_addr) >> PAGE_SHIFT;
int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
int count = size >> PAGE_SHIFT;