aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaura Abbott <lauraa@codeaurora.org>2013-12-12 14:28:33 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2013-12-19 12:44:09 -0500
commit6ac2104debc235b745265b64d610237a6833fd53 (patch)
tree220521d71f3799ec7d1510a00910ffb7efad1722
parentc666e8d5cae745b1515898f8b7a033c468a899d0 (diff)
arm64: Enable CMA
arm64 bit targets need the features CMA provides. Add the appropriate hooks, header files, and Kconfig to allow this to happen. Cc: Will Deacon <will.deacon@arm.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Laura Abbott <lauraa@codeaurora.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/dma-contiguous.h29
-rw-r--r--arch/arm64/mm/dma-mapping.c25
-rw-r--r--arch/arm64/mm/init.c3
4 files changed, 56 insertions, 2 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index cb9421b540c8..101683d336c9 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
27 select HAVE_DEBUG_KMEMLEAK 27 select HAVE_DEBUG_KMEMLEAK
28 select HAVE_DMA_API_DEBUG 28 select HAVE_DMA_API_DEBUG
29 select HAVE_DMA_ATTRS 29 select HAVE_DMA_ATTRS
30 select HAVE_DMA_CONTIGUOUS
30 select HAVE_EFFICIENT_UNALIGNED_ACCESS 31 select HAVE_EFFICIENT_UNALIGNED_ACCESS
31 select HAVE_GENERIC_DMA_COHERENT 32 select HAVE_GENERIC_DMA_COHERENT
32 select HAVE_HW_BREAKPOINT if PERF_EVENTS 33 select HAVE_HW_BREAKPOINT if PERF_EVENTS
diff --git a/arch/arm64/include/asm/dma-contiguous.h b/arch/arm64/include/asm/dma-contiguous.h
new file mode 100644
index 000000000000..d6aacb61ff4a
--- /dev/null
+++ b/arch/arm64/include/asm/dma-contiguous.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#ifndef _ASM_DMA_CONTIGUOUS_H
15#define _ASM_DMA_CONTIGUOUS_H
16
17#ifdef __KERNEL__
18#ifdef CONFIG_DMA_CMA
19
20#include <linux/types.h>
21#include <asm-generic/dma-contiguous.h>
22
23static inline void
24dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
25
26#endif
27#endif
28
29#endif
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 83e643131e10..45b5ab54c9ee 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -21,6 +21,7 @@
21#include <linux/export.h> 21#include <linux/export.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/dma-mapping.h> 23#include <linux/dma-mapping.h>
24#include <linux/dma-contiguous.h>
24#include <linux/vmalloc.h> 25#include <linux/vmalloc.h>
25#include <linux/swiotlb.h> 26#include <linux/swiotlb.h>
26 27
@@ -41,7 +42,19 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
41 if (IS_ENABLED(CONFIG_ZONE_DMA32) && 42 if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
42 dev->coherent_dma_mask <= DMA_BIT_MASK(32)) 43 dev->coherent_dma_mask <= DMA_BIT_MASK(32))
43 flags |= GFP_DMA32; 44 flags |= GFP_DMA32;
44 return swiotlb_alloc_coherent(dev, size, dma_handle, flags); 45 if (IS_ENABLED(CONFIG_DMA_CMA)) {
46 struct page *page;
47
48 page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
49 get_order(size));
50 if (!page)
51 return NULL;
52
53 *dma_handle = phys_to_dma(dev, page_to_phys(page));
54 return page_address(page);
55 } else {
56 return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
57 }
45} 58}
46 59
47static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, 60static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
@@ -53,7 +66,15 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
53 return; 66 return;
54 } 67 }
55 68
56 swiotlb_free_coherent(dev, size, vaddr, dma_handle); 69 if (IS_ENABLED(CONFIG_DMA_CMA)) {
70 phys_addr_t paddr = dma_to_phys(dev, dma_handle);
71
72 dma_release_from_contiguous(dev,
73 phys_to_page(paddr),
74 size >> PAGE_SHIFT);
75 } else {
76 swiotlb_free_coherent(dev, size, vaddr, dma_handle);
77 }
57} 78}
58 79
59static struct dma_map_ops arm64_swiotlb_dma_ops = { 80static struct dma_map_ops arm64_swiotlb_dma_ops = {
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 0cb8742de4f2..d0b4c2efda90 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -30,6 +30,7 @@
30#include <linux/memblock.h> 30#include <linux/memblock.h>
31#include <linux/sort.h> 31#include <linux/sort.h>
32#include <linux/of_fdt.h> 32#include <linux/of_fdt.h>
33#include <linux/dma-contiguous.h>
33 34
34#include <asm/sections.h> 35#include <asm/sections.h>
35#include <asm/setup.h> 36#include <asm/setup.h>
@@ -159,6 +160,8 @@ void __init arm64_memblock_init(void)
159 memblock_reserve(base, size); 160 memblock_reserve(base, size);
160 } 161 }
161 162
163 dma_contiguous_reserve(0);
164
162 memblock_allow_resize(); 165 memblock_allow_resize();
163 memblock_dump_all(); 166 memblock_dump_all();
164} 167}