summaryrefslogtreecommitdiff
path: root/arch/mips/mm/dma-default.c
diff options
context:
space:
mode:
authorZubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>2014-07-16 15:51:32 (GMT)
committerRalf Baechle <ralf@linux-mips.org>2014-09-22 11:35:52 (GMT)
commitf46493826a79f6a2bf9d8a0030e627e0255bbf48 (patch)
tree1ab960daaf90654f3267f00ec70080543e175261 /arch/mips/mm/dma-default.c
parent8057b30814e1c90e9425bb7b3be868b55bf5435c (diff)
downloadlinux-f46493826a79f6a2bf9d8a0030e627e0255bbf48.tar.xz
MIPS: DMA: Add cma support
Adds cma support to the MIPS architecture. cma uses memblock. However, mips uses bootmem. bootmem is informed about any regions reserved by memblock dma api is modified to use cma reserved memory regions when available Tested using cma_test. cma_test is a simple driver that assigns blocks of memory from cma reserved sections. Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Cc: catalin.marinas@arm.com Cc: will.deacon@arm.com Cc: tglx@linutronix.de Cc: mingo@redhat.com Cc: hpa@zytor.com Cc: arnd@arndb.de Cc: gregkh@linuxfoundation.org Cc: m.szyprowski@samsung.com Cc: x86@kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-arch@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7360/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm/dma-default.c')
-rw-r--r--arch/mips/mm/dma-default.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 44b6dff..33ba3c5 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/gfp.h>
#include <linux/highmem.h>
+#include <linux/dma-contiguous.h>
#include <asm/cache.h>
#include <asm/cpu-type.h>
@@ -128,23 +129,30 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
void *ret;
+ struct page *page = NULL;
+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
return ret;
gfp = massage_gfp_flags(dev, gfp);
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret) {
- memset(ret, 0, size);
- *dma_handle = plat_map_dma_mem(dev, ret, size);
-
- if (!plat_device_is_coherent(dev)) {
- dma_cache_wback_inv((unsigned long) ret, size);
- if (!hw_coherentio)
- ret = UNCAC_ADDR(ret);
- }
+ if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
+ page = dma_alloc_from_contiguous(dev,
+ count, get_order(size));
+ if (!page)
+ page = alloc_pages(gfp, get_order(size));
+
+ if (!page)
+ return NULL;
+
+ ret = page_address(page);
+ memset(ret, 0, size);
+ *dma_handle = plat_map_dma_mem(dev, ret, size);
+ if (!plat_device_is_coherent(dev)) {
+ dma_cache_wback_inv((unsigned long) ret, size);
+ if (!hw_coherentio)
+ ret = UNCAC_ADDR(ret);
}
return ret;
@@ -164,6 +172,8 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
int order = get_order(size);
+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ struct page *page = NULL;
if (dma_release_from_coherent(dev, order, vaddr))
return;
@@ -173,7 +183,10 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
if (!plat_device_is_coherent(dev) && !hw_coherentio)
addr = CAC_ADDR(addr);
- free_pages(addr, get_order(size));
+ page = virt_to_page((void *) addr);
+
+ if (!dma_release_from_contiguous(dev, page, count))
+ __free_pages(page, get_order(size));
}
static inline void __dma_sync_virtual(void *addr, size_t size,