summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-11-04 14:29:28 -0500
committerChristoph Hellwig <hch@lst.de>2018-12-01 12:07:11 -0500
commit0c3b3171ceccb8830c2bb5adff1b4e9b204c1450 (patch)
treec7dbe5478677405c690334e59acc392c5db86858 /arch
parentf0edfea8ef93ed6cc5f747c46c85c8e53e0798a0 (diff)
dma-mapping: move the arm64 noncoherent alloc/free support to common code
The arm64 codebase to implement coherent dma allocation for architectures with non-coherent DMA is a good start for a generic implementation, given that is uses the generic remap helpers, provides the atomic pool for allocations that can't sleep and still is realtively simple and well tested. Move it to kernel/dma and allow architectures to opt into it using a config symbol. Architectures just need to provide a new arch_dma_prep_coherent helper to writeback an invalidate the caches for any memory that gets remapped for uncached access. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/Kconfig2
-rw-r--r--arch/arm64/mm/dma-mapping.c184
2 files changed, 11 insertions, 175 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d065acb6d10..2e645ea693ea 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -82,7 +82,7 @@ config ARM64
82 select CRC32 82 select CRC32
83 select DCACHE_WORD_ACCESS 83 select DCACHE_WORD_ACCESS
84 select DMA_DIRECT_OPS 84 select DMA_DIRECT_OPS
85 select DMA_REMAP 85 select DMA_DIRECT_REMAP
86 select EDAC_SUPPORT 86 select EDAC_SUPPORT
87 select FRAME_POINTER 87 select FRAME_POINTER
88 select GENERIC_ALLOCATOR 88 select GENERIC_ALLOCATOR
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index a3ac26284845..e2e7e5d0f94e 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -33,113 +33,6 @@
33 33
34#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
35 35
36static struct gen_pool *atomic_pool __ro_after_init;
37
38#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
39static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE;
40
41static int __init early_coherent_pool(char *p)
42{
43 atomic_pool_size = memparse(p, &p);
44 return 0;
45}
46early_param("coherent_pool", early_coherent_pool);
47
48static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
49{
50 unsigned long val;
51 void *ptr = NULL;
52
53 if (!atomic_pool) {
54 WARN(1, "coherent pool not initialised!\n");
55 return NULL;
56 }
57
58 val = gen_pool_alloc(atomic_pool, size);
59 if (val) {
60 phys_addr_t phys = gen_pool_virt_to_phys(atomic_pool, val);
61
62 *ret_page = phys_to_page(phys);
63 ptr = (void *)val;
64 memset(ptr, 0, size);
65 }
66
67 return ptr;
68}
69
70static bool __in_atomic_pool(void *start, size_t size)
71{
72 return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
73}
74
75static int __free_from_pool(void *start, size_t size)
76{
77 if (!__in_atomic_pool(start, size))
78 return 0;
79
80 gen_pool_free(atomic_pool, (unsigned long)start, size);
81
82 return 1;
83}
84
85void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
86 gfp_t flags, unsigned long attrs)
87{
88 struct page *page;
89 void *ptr, *coherent_ptr;
90 pgprot_t prot = pgprot_writecombine(PAGE_KERNEL);
91
92 size = PAGE_ALIGN(size);
93
94 if (!gfpflags_allow_blocking(flags)) {
95 struct page *page = NULL;
96 void *addr = __alloc_from_pool(size, &page, flags);
97
98 if (addr)
99 *dma_handle = phys_to_dma(dev, page_to_phys(page));
100
101 return addr;
102 }
103
104 ptr = dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);
105 if (!ptr)
106 goto no_mem;
107
108 /* remove any dirty cache lines on the kernel alias */
109 __dma_flush_area(ptr, size);
110
111 /* create a coherent mapping */
112 page = virt_to_page(ptr);
113 coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
114 prot, __builtin_return_address(0));
115 if (!coherent_ptr)
116 goto no_map;
117
118 return coherent_ptr;
119
120no_map:
121 dma_direct_free_pages(dev, size, ptr, *dma_handle, attrs);
122no_mem:
123 return NULL;
124}
125
126void arch_dma_free(struct device *dev, size_t size, void *vaddr,
127 dma_addr_t dma_handle, unsigned long attrs)
128{
129 if (!__free_from_pool(vaddr, PAGE_ALIGN(size))) {
130 void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle));
131
132 vunmap(vaddr);
133 dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs);
134 }
135}
136
137long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
138 dma_addr_t dma_addr)
139{
140 return __phys_to_pfn(dma_to_phys(dev, dma_addr));
141}
142
143pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, 36pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
144 unsigned long attrs) 37 unsigned long attrs)
145{ 38{
@@ -160,6 +53,11 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
160 __dma_unmap_area(phys_to_virt(paddr), size, dir); 53 __dma_unmap_area(phys_to_virt(paddr), size, dir);
161} 54}
162 55
56void arch_dma_prep_coherent(struct page *page, size_t size)
57{
58 __dma_flush_area(page_address(page), size);
59}
60
163#ifdef CONFIG_IOMMU_DMA 61#ifdef CONFIG_IOMMU_DMA
164static int __swiotlb_get_sgtable_page(struct sg_table *sgt, 62static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
165 struct page *page, size_t size) 63 struct page *page, size_t size)
@@ -191,67 +89,6 @@ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
191} 89}
192#endif /* CONFIG_IOMMU_DMA */ 90#endif /* CONFIG_IOMMU_DMA */
193 91
194static int __init atomic_pool_init(void)
195{
196 pgprot_t prot = __pgprot(PROT_NORMAL_NC);
197 unsigned long nr_pages = atomic_pool_size >> PAGE_SHIFT;
198 struct page *page;
199 void *addr;
200 unsigned int pool_size_order = get_order(atomic_pool_size);
201
202 if (dev_get_cma_area(NULL))
203 page = dma_alloc_from_contiguous(NULL, nr_pages,
204 pool_size_order, false);
205 else
206 page = alloc_pages(GFP_DMA32, pool_size_order);
207
208 if (page) {
209 int ret;
210 void *page_addr = page_address(page);
211
212 memset(page_addr, 0, atomic_pool_size);
213 __dma_flush_area(page_addr, atomic_pool_size);
214
215 atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
216 if (!atomic_pool)
217 goto free_page;
218
219 addr = dma_common_contiguous_remap(page, atomic_pool_size,
220 VM_USERMAP, prot, atomic_pool_init);
221
222 if (!addr)
223 goto destroy_genpool;
224
225 ret = gen_pool_add_virt(atomic_pool, (unsigned long)addr,
226 page_to_phys(page),
227 atomic_pool_size, -1);
228 if (ret)
229 goto remove_mapping;
230
231 gen_pool_set_algo(atomic_pool,
232 gen_pool_first_fit_order_align,
233 NULL);
234
235 pr_info("DMA: preallocated %zu KiB pool for atomic allocations\n",
236 atomic_pool_size / 1024);
237 return 0;
238 }
239 goto out;
240
241remove_mapping:
242 dma_common_free_remap(addr, atomic_pool_size, VM_USERMAP);
243destroy_genpool:
244 gen_pool_destroy(atomic_pool);
245 atomic_pool = NULL;
246free_page:
247 if (!dma_release_from_contiguous(NULL, page, nr_pages))
248 __free_pages(page, pool_size_order);
249out:
250 pr_err("DMA: failed to allocate %zu KiB pool for atomic coherent allocation\n",
251 atomic_pool_size / 1024);
252 return -ENOMEM;
253}
254
255/******************************************** 92/********************************************
256 * The following APIs are for dummy DMA ops * 93 * The following APIs are for dummy DMA ops *
257 ********************************************/ 94 ********************************************/
@@ -350,8 +187,7 @@ static int __init arm64_dma_init(void)
350 TAINT_CPU_OUT_OF_SPEC, 187 TAINT_CPU_OUT_OF_SPEC,
351 "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", 188 "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)",
352 ARCH_DMA_MINALIGN, cache_line_size()); 189 ARCH_DMA_MINALIGN, cache_line_size());
353 190 return dma_atomic_pool_init(GFP_DMA32, __pgprot(PROT_NORMAL_NC));
354 return atomic_pool_init();
355} 191}
356arch_initcall(arm64_dma_init); 192arch_initcall(arm64_dma_init);
357 193
@@ -397,7 +233,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
397 page = alloc_pages(gfp, get_order(size)); 233 page = alloc_pages(gfp, get_order(size));
398 addr = page ? page_address(page) : NULL; 234 addr = page ? page_address(page) : NULL;
399 } else { 235 } else {
400 addr = __alloc_from_pool(size, &page, gfp); 236 addr = dma_alloc_from_pool(size, &page, gfp);
401 } 237 }
402 if (!addr) 238 if (!addr)
403 return NULL; 239 return NULL;
@@ -407,7 +243,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
407 if (coherent) 243 if (coherent)
408 __free_pages(page, get_order(size)); 244 __free_pages(page, get_order(size));
409 else 245 else
410 __free_from_pool(addr, size); 246 dma_free_from_pool(addr, size);
411 addr = NULL; 247 addr = NULL;
412 } 248 }
413 } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) { 249 } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
@@ -471,9 +307,9 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
471 * coherent devices. 307 * coherent devices.
472 * Hence how dodgy the below logic looks... 308 * Hence how dodgy the below logic looks...
473 */ 309 */
474 if (__in_atomic_pool(cpu_addr, size)) { 310 if (dma_in_atomic_pool(cpu_addr, size)) {
475 iommu_dma_unmap_page(dev, handle, iosize, 0, 0); 311 iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
476 __free_from_pool(cpu_addr, size); 312 dma_free_from_pool(cpu_addr, size);
477 } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) { 313 } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
478 struct page *page = vmalloc_to_page(cpu_addr); 314 struct page *page = vmalloc_to_page(cpu_addr);
479 315