diff options
-rw-r--r-- | arch/arm64/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm64/include/asm/dma-contiguous.h | 29 | ||||
-rw-r--r-- | arch/arm64/mm/dma-mapping.c | 25 | ||||
-rw-r--r-- | arch/arm64/mm/init.c | 3 |
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 | |||
23 | static inline void | ||
24 | dma_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 | ||
47 | static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, | 60 | static 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 | ||
59 | static struct dma_map_ops arm64_swiotlb_dma_ops = { | 80 | static 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 | } |