diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-11-19 15:38:12 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-11-24 17:41:34 +0000 |
commit | 3e82d012e9281a0b6388ff2356e8396b9d781e1c (patch) | |
tree | c76320422bd3988e499680662b3bebbf9796589b /arch/arm/mm | |
parent | 7a9a32a9533fa01de911e1d056142ddd27360782 (diff) | |
download | blackbird-op-linux-3e82d012e9281a0b6388ff2356e8396b9d781e1c.tar.gz blackbird-op-linux-3e82d012e9281a0b6388ff2356e8396b9d781e1c.zip |
ARM: dma-mapping: fix coherent arch dma_alloc_coherent()
The coherent architecture dma_alloc_coherent was using kmalloc/kfree to
manage the memory. dma_alloc_coherent() is expected to work with a
granularity of a page, so this is wrong. Fix it by using the helper
functions now provided.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Greg Ungerer <gerg@uclinux.org>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index dab2d7f04adf..a67130873431 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -246,14 +246,16 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gf return memory; if (arch_is_coherent()) { - void *virt; + struct page *page; - virt = kmalloc(size, gfp); - if (!virt) + page = __dma_alloc_buffer(dev, PAGE_ALIGN(size), gfp); + if (!page) { + *handle = ~0; return NULL; - *handle = virt_to_dma(dev, virt); + } - return virt; + *handle = page_to_dma(dev, page); + return page_address(page); } return __dma_alloc(dev, size, handle, gfp, @@ -336,13 +338,13 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr if (dma_release_from_coherent(dev, get_order(size), cpu_addr)) return; + size = PAGE_ALIGN(size); + if (arch_is_coherent()) { - kfree(cpu_addr); + __dma_free_buffer(dma_to_page(dev, handle), size); return; } - size = PAGE_ALIGN(size); - c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr); if (!c) goto no_area; |