Commit bca0fa5f authored by Marek Szyprowski's avatar Marek Szyprowski

common: add dma_mmap_from_coherent() function

Add a common helper for dma-mapping core for mapping a coherent buffer
to userspace.
Reported-by: default avatarSubash Patel <subashrp@gmail.com>
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Acked-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Tested-By: default avatarSubash Patel <subash.ramaswamy@linaro.org>
parent 76e10d15
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
struct dma_coherent_mem { struct dma_coherent_mem {
void *virt_base; void *virt_base;
dma_addr_t device_base; dma_addr_t device_base;
phys_addr_t pfn_base;
int size; int size;
int flags; int flags;
unsigned long *bitmap; unsigned long *bitmap;
...@@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, ...@@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dev->dma_mem->virt_base = mem_base; dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr; dev->dma_mem->device_base = device_addr;
dev->dma_mem->pfn_base = PFN_DOWN(bus_addr);
dev->dma_mem->size = pages; dev->dma_mem->size = pages;
dev->dma_mem->flags = flags; dev->dma_mem->flags = flags;
...@@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr) ...@@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
return 0; return 0;
} }
EXPORT_SYMBOL(dma_release_from_coherent); EXPORT_SYMBOL(dma_release_from_coherent);
/**
* dma_mmap_from_coherent() - try to mmap the memory allocated from
* per-device coherent memory pool to userspace
* @dev: device from which the memory was allocated
* @vma: vm_area for the userspace memory
* @vaddr: cpu address returned by dma_alloc_from_coherent
* @size: size of the memory buffer allocated by dma_alloc_from_coherent
*
* This checks whether the memory was allocated from the per-device
* coherent memory pool and if so, maps that memory to the provided vma.
*
* Returns 1 if we correctly mapped the memory, or 0 if
* dma_release_coherent() should proceed with mapping memory from
* generic pools.
*/
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;
if (mem && vaddr >= mem->virt_base && vaddr + size <=
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
unsigned long off = vma->vm_pgoff;
int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
int count = size >> PAGE_SHIFT;
*ret = -ENXIO;
if (off < count && user_count <= count - off) {
unsigned pfn = mem->pfn_base + start + off;
*ret = remap_pfn_range(vma, vma->vm_start, pfn,
user_count << PAGE_SHIFT,
vma->vm_page_prot);
}
return 1;
}
return 0;
}
EXPORT_SYMBOL(dma_mmap_from_coherent);
...@@ -3,13 +3,15 @@ ...@@ -3,13 +3,15 @@
#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
/* /*
* These two functions are only for dma allocator. * These three functions are only for dma allocator.
* Don't use them in device drivers. * Don't use them in device drivers.
*/ */
int dma_alloc_from_coherent(struct device *dev, ssize_t size, int dma_alloc_from_coherent(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret); dma_addr_t *dma_handle, void **ret);
int dma_release_from_coherent(struct device *dev, int order, void *vaddr); int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, size_t size, int *ret);
/* /*
* Standard interface * Standard interface
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment