summaryrefslogtreecommitdiff
path: root/arch/arm/mm/dma-mapping.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-11-26 16:19:58 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-15 15:22:20 +0000
commita9c9147eb9b1dba0ce567a41897c7773b4d1b0bc (patch)
tree178938c909f4717c2e599d6f3de954d7ee8a7f21 /arch/arm/mm/dma-mapping.c
parent93f1d629e22b08642eb713ad96ac2cb9ade0641c (diff)
ARM: dma-mapping: provide per-cpu type map/unmap functions
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Tested-By: Santosh Shilimkar <santosh.shilimkar@ti.com>
Diffstat (limited to 'arch/arm/mm/dma-mapping.c')
-rw-r--r--arch/arm/mm/dma-mapping.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0d68d2c83cda..efa8efa33f5e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -406,35 +406,31 @@ EXPORT_SYMBOL(dma_free_coherent);
*/
static void dma_cache_maint(const void *start, size_t size, int direction)
{
- void (*inner_op)(const void *, const void *);
void (*outer_op)(unsigned long, unsigned long);
- BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1));
-
switch (direction) {
case DMA_FROM_DEVICE: /* invalidate only */
- inner_op = dmac_inv_range;
outer_op = outer_inv_range;
break;
case DMA_TO_DEVICE: /* writeback only */
- inner_op = dmac_clean_range;
outer_op = outer_clean_range;
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
- inner_op = dmac_flush_range;
outer_op = outer_flush_range;
break;
default:
BUG();
}
- inner_op(start, start + size);
outer_op(__pa(start), __pa(start) + size);
}
void ___dma_single_cpu_to_dev(const void *kaddr, size_t size,
enum dma_data_direction dir)
{
+ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
+
+ dmac_map_area(kaddr, size, dir);
dma_cache_maint(kaddr, size, dir);
}
EXPORT_SYMBOL(___dma_single_cpu_to_dev);
@@ -442,12 +438,15 @@ EXPORT_SYMBOL(___dma_single_cpu_to_dev);
void ___dma_single_dev_to_cpu(const void *kaddr, size_t size,
enum dma_data_direction dir)
{
- /* nothing to do */
+ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
+
+ dmac_unmap_area(kaddr, size, dir);
}
EXPORT_SYMBOL(___dma_single_dev_to_cpu);
static void dma_cache_maint_page(struct page *page, unsigned long offset,
- size_t size, void (*op)(const void *, const void *))
+ size_t size, enum dma_data_direction dir,
+ void (*op)(const void *, size_t, int))
{
/*
* A single sg entry may refer to multiple physically contiguous
@@ -471,12 +470,12 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
vaddr = kmap_high_get(page);
if (vaddr) {
vaddr += offset;
- op(vaddr, vaddr + len);
+ op(vaddr, len, dir);
kunmap_high(page);
}
} else {
vaddr = page_address(page) + offset;
- op(vaddr, vaddr + len);
+ op(vaddr, len, dir);
}
offset = 0;
page++;
@@ -488,27 +487,23 @@ void ___dma_page_cpu_to_dev(struct page *page, unsigned long off,
size_t size, enum dma_data_direction dir)
{
unsigned long paddr;
- void (*inner_op)(const void *, const void *);
void (*outer_op)(unsigned long, unsigned long);
switch (direction) {
case DMA_FROM_DEVICE: /* invalidate only */
- inner_op = dmac_inv_range;
outer_op = outer_inv_range;
break;
case DMA_TO_DEVICE: /* writeback only */
- inner_op = dmac_clean_range;
outer_op = outer_clean_range;
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
- inner_op = dmac_flush_range;
outer_op = outer_flush_range;
break;
default:
BUG();
}
- dma_cache_maint_page(page, off, size, inner_op);
+ dma_cache_maint_page(page, off, size, dir, dmac_map_area);
paddr = page_to_phys(page) + off;
outer_op(paddr, paddr + size);
@@ -518,7 +513,7 @@ EXPORT_SYMBOL(___dma_page_cpu_to_dev);
void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
size_t size, enum dma_data_direction dir)
{
- /* nothing to do */
+ dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
}
EXPORT_SYMBOL(___dma_page_dev_to_cpu);