diff options
| -rw-r--r-- | drivers/base/dma-coherent.c | 42 | ||||
| -rw-r--r-- | include/asm-generic/dma-coherent.h | 4 |
2 files changed, 45 insertions, 1 deletions
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index bb0025c510b3..1b85949e3d2f 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | struct dma_coherent_mem { | 10 | struct dma_coherent_mem { |
| 11 | void *virt_base; | 11 | void *virt_base; |
| 12 | dma_addr_t device_base; | 12 | dma_addr_t device_base; |
| 13 | phys_addr_t pfn_base; | ||
| 13 | int size; | 14 | int size; |
| 14 | int flags; | 15 | int flags; |
| 15 | unsigned long *bitmap; | 16 | unsigned long *bitmap; |
| @@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, | |||
| 44 | 45 | ||
| 45 | dev->dma_mem->virt_base = mem_base; | 46 | dev->dma_mem->virt_base = mem_base; |
| 46 | dev->dma_mem->device_base = device_addr; | 47 | dev->dma_mem->device_base = device_addr; |
| 48 | dev->dma_mem->pfn_base = PFN_DOWN(bus_addr); | ||
| 47 | dev->dma_mem->size = pages; | 49 | dev->dma_mem->size = pages; |
| 48 | dev->dma_mem->flags = flags; | 50 | dev->dma_mem->flags = flags; |
| 49 | 51 | ||
| @@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr) | |||
| 176 | return 0; | 178 | return 0; |
| 177 | } | 179 | } |
| 178 | EXPORT_SYMBOL(dma_release_from_coherent); | 180 | EXPORT_SYMBOL(dma_release_from_coherent); |
| 181 | |||
| 182 | /** | ||
| 183 | * dma_mmap_from_coherent() - try to mmap the memory allocated from | ||
| 184 | * per-device coherent memory pool to userspace | ||
| 185 | * @dev: device from which the memory was allocated | ||
| 186 | * @vma: vm_area for the userspace memory | ||
| 187 | * @vaddr: cpu address returned by dma_alloc_from_coherent | ||
| 188 | * @size: size of the memory buffer allocated by dma_alloc_from_coherent | ||
| 189 | * | ||
| 190 | * This checks whether the memory was allocated from the per-device | ||
| 191 | * coherent memory pool and if so, maps that memory to the provided vma. | ||
| 192 | * | ||
| 193 | * Returns 1 if we correctly mapped the memory, or 0 if | ||
| 194 | * dma_release_coherent() should proceed with mapping memory from | ||
| 195 | * generic pools. | ||
| 196 | */ | ||
| 197 | int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, | ||
| 198 | void *vaddr, size_t size, int *ret) | ||
| 199 | { | ||
| 200 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | ||
| 201 | |||
| 202 | if (mem && vaddr >= mem->virt_base && vaddr + size <= | ||
| 203 | (mem->virt_base + (mem->size << PAGE_SHIFT))) { | ||
| 204 | unsigned long off = vma->vm_pgoff; | ||
| 205 | int start = (vaddr - mem->virt_base) >> PAGE_SHIFT; | ||
| 206 | int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | ||
| 207 | int count = size >> PAGE_SHIFT; | ||
| 208 | |||
| 209 | *ret = -ENXIO; | ||
| 210 | if (off < count && user_count <= count - off) { | ||
| 211 | unsigned pfn = mem->pfn_base + start + off; | ||
| 212 | *ret = remap_pfn_range(vma, vma->vm_start, pfn, | ||
| 213 | user_count << PAGE_SHIFT, | ||
| 214 | vma->vm_page_prot); | ||
| 215 | } | ||
| 216 | return 1; | ||
| 217 | } | ||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | EXPORT_SYMBOL(dma_mmap_from_coherent); | ||
diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h index 85a3ffaa0242..abfb2682de7f 100644 --- a/include/asm-generic/dma-coherent.h +++ b/include/asm-generic/dma-coherent.h | |||
| @@ -3,13 +3,15 @@ | |||
| 3 | 3 | ||
| 4 | #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT | 4 | #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT |
| 5 | /* | 5 | /* |
| 6 | * These two functions are only for dma allocator. | 6 | * These three functions are only for dma allocator. |
| 7 | * Don't use them in device drivers. | 7 | * Don't use them in device drivers. |
| 8 | */ | 8 | */ |
| 9 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, | 9 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, |
| 10 | dma_addr_t *dma_handle, void **ret); | 10 | dma_addr_t *dma_handle, void **ret); |
| 11 | int dma_release_from_coherent(struct device *dev, int order, void *vaddr); | 11 | int dma_release_from_coherent(struct device *dev, int order, void *vaddr); |
| 12 | 12 | ||
| 13 | int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, | ||
| 14 | void *cpu_addr, size_t size, int *ret); | ||
| 13 | /* | 15 | /* |
| 14 | * Standard interface | 16 | * Standard interface |
| 15 | */ | 17 | */ |
