aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/dma-mapping.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 6f3676f1559f..db5db02e885f 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -10,6 +10,7 @@
10#include <linux/dma-mapping.h> 10#include <linux/dma-mapping.h>
11#include <linux/export.h> 11#include <linux/export.h>
12#include <linux/gfp.h> 12#include <linux/gfp.h>
13#include <asm-generic/dma-coherent.h>
13 14
14/* 15/*
15 * Managed DMA API 16 * Managed DMA API
@@ -218,3 +219,33 @@ void dmam_release_declared_memory(struct device *dev)
218EXPORT_SYMBOL(dmam_release_declared_memory); 219EXPORT_SYMBOL(dmam_release_declared_memory);
219 220
220#endif 221#endif
222
223/*
224 * Create userspace mapping for the DMA-coherent memory.
225 */
226int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
227 void *cpu_addr, dma_addr_t dma_addr, size_t size)
228{
229 int ret = -ENXIO;
230#ifdef CONFIG_MMU
231 unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
232 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
233 unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
234 unsigned long off = vma->vm_pgoff;
235
236 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
237
238 if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
239 return ret;
240
241 if (off < count && user_count <= (count - off)) {
242 ret = remap_pfn_range(vma, vma->vm_start,
243 pfn + off,
244 user_count << PAGE_SHIFT,
245 vma->vm_page_prot);
246 }
247#endif /* CONFIG_MMU */
248
249 return ret;
250}
251EXPORT_SYMBOL(dma_common_mmap);