aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>2014-07-16 11:51:32 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-09-22 07:35:52 -0400
commitf46493826a79f6a2bf9d8a0030e627e0255bbf48 (patch)
tree1ab960daaf90654f3267f00ec70080543e175261
parent8057b30814e1c90e9425bb7b3be868b55bf5435c (diff)
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>
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/mips/kernel/setup.c9
-rw-r--r--arch/mips/mm/dma-default.c37
4 files changed, 36 insertions, 12 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d7c8bd4e2f0e..ad6badb6be71 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -29,6 +29,7 @@ config MIPS
29 select GENERIC_ATOMIC64 if !64BIT 29 select GENERIC_ATOMIC64 if !64BIT
30 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE 30 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
31 select HAVE_DMA_ATTRS 31 select HAVE_DMA_ATTRS
32 select HAVE_DMA_CONTIGUOUS
32 select HAVE_DMA_API_DEBUG 33 select HAVE_DMA_API_DEBUG
33 select GENERIC_IRQ_PROBE 34 select GENERIC_IRQ_PROBE
34 select GENERIC_IRQ_SHOW 35 select GENERIC_IRQ_SHOW
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 335e5290ec75..c0b09571a7a5 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1,6 +1,7 @@
1# MIPS headers 1# MIPS headers
2generic-y += cputime.h 2generic-y += cputime.h
3generic-y += current.h 3generic-y += current.h
4generic-y += dma-contiguous.h
4generic-y += emergency-restart.h 5generic-y += emergency-restart.h
5generic-y += hash.h 6generic-y += hash.h
6generic-y += local64.h 7generic-y += local64.h
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 7c1fe2b42d40..b3b8f0d9d4a7 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -24,6 +24,8 @@
24#include <linux/debugfs.h> 24#include <linux/debugfs.h>
25#include <linux/kexec.h> 25#include <linux/kexec.h>
26#include <linux/sizes.h> 26#include <linux/sizes.h>
27#include <linux/device.h>
28#include <linux/dma-contiguous.h>
27 29
28#include <asm/addrspace.h> 30#include <asm/addrspace.h>
29#include <asm/bootinfo.h> 31#include <asm/bootinfo.h>
@@ -476,6 +478,7 @@ static void __init bootmem_init(void)
476 * o bootmem_init() 478 * o bootmem_init()
477 * o sparse_init() 479 * o sparse_init()
478 * o paging_init() 480 * o paging_init()
481 * o dma_continguous_reserve()
479 * 482 *
480 * At this stage the bootmem allocator is ready to use. 483 * At this stage the bootmem allocator is ready to use.
481 * 484 *
@@ -609,6 +612,7 @@ static void __init request_crashkernel(struct resource *res)
609 612
610static void __init arch_mem_init(char **cmdline_p) 613static void __init arch_mem_init(char **cmdline_p)
611{ 614{
615 struct memblock_region *reg;
612 extern void plat_mem_setup(void); 616 extern void plat_mem_setup(void);
613 617
614 /* call board setup routine */ 618 /* call board setup routine */
@@ -675,6 +679,11 @@ static void __init arch_mem_init(char **cmdline_p)
675 sparse_init(); 679 sparse_init();
676 plat_swiotlb_setup(); 680 plat_swiotlb_setup();
677 paging_init(); 681 paging_init();
682
683 dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
684 /* Tell bootmem about cma reserved memblock section */
685 for_each_memblock(reserved, reg)
686 reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
678} 687}
679 688
680static void __init resource_init(void) 689static void __init resource_init(void)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 44b6dff5aba2..33ba3c558fe4 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -16,6 +16,7 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/gfp.h> 17#include <linux/gfp.h>
18#include <linux/highmem.h> 18#include <linux/highmem.h>
19#include <linux/dma-contiguous.h>
19 20
20#include <asm/cache.h> 21#include <asm/cache.h>
21#include <asm/cpu-type.h> 22#include <asm/cpu-type.h>
@@ -128,23 +129,30 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
128 dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs) 129 dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
129{ 130{
130 void *ret; 131 void *ret;
132 struct page *page = NULL;
133 unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
131 134
132 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) 135 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
133 return ret; 136 return ret;
134 137
135 gfp = massage_gfp_flags(dev, gfp); 138 gfp = massage_gfp_flags(dev, gfp);
136 139
137 ret = (void *) __get_free_pages(gfp, get_order(size)); 140 if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
138 141 page = dma_alloc_from_contiguous(dev,
139 if (ret) { 142 count, get_order(size));
140 memset(ret, 0, size); 143 if (!page)
141 *dma_handle = plat_map_dma_mem(dev, ret, size); 144 page = alloc_pages(gfp, get_order(size));
142 145
143 if (!plat_device_is_coherent(dev)) { 146 if (!page)
144 dma_cache_wback_inv((unsigned long) ret, size); 147 return NULL;
145 if (!hw_coherentio) 148
146 ret = UNCAC_ADDR(ret); 149 ret = page_address(page);
147 } 150 memset(ret, 0, size);
151 *dma_handle = plat_map_dma_mem(dev, ret, size);
152 if (!plat_device_is_coherent(dev)) {
153 dma_cache_wback_inv((unsigned long) ret, size);
154 if (!hw_coherentio)
155 ret = UNCAC_ADDR(ret);
148 } 156 }
149 157
150 return ret; 158 return ret;
@@ -164,6 +172,8 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
164{ 172{
165 unsigned long addr = (unsigned long) vaddr; 173 unsigned long addr = (unsigned long) vaddr;
166 int order = get_order(size); 174 int order = get_order(size);
175 unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
176 struct page *page = NULL;
167 177
168 if (dma_release_from_coherent(dev, order, vaddr)) 178 if (dma_release_from_coherent(dev, order, vaddr))
169 return; 179 return;
@@ -173,7 +183,10 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
173 if (!plat_device_is_coherent(dev) && !hw_coherentio) 183 if (!plat_device_is_coherent(dev) && !hw_coherentio)
174 addr = CAC_ADDR(addr); 184 addr = CAC_ADDR(addr);
175 185
176 free_pages(addr, get_order(size)); 186 page = virt_to_page((void *) addr);
187
188 if (!dma_release_from_contiguous(dev, page, count))
189 __free_pages(page, get_order(size));
177} 190}
178 191
179static inline void __dma_sync_virtual(void *addr, size_t size, 192static inline void __dma_sync_virtual(void *addr, size_t size,