diff options
author | Christoph Hellwig <hch@lst.de> | 2018-10-08 03:12:01 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-10-19 02:53:24 -0400 |
commit | 886643b766321f15f63bd950be618cbb6dd22bbc (patch) | |
tree | d84cbe166a610723a06937fbb09c89ffcb608246 | |
parent | a4a4330db46a17289cf2ca5f9fb153d536267b97 (diff) |
arm64: use the generic swiotlb_dma_ops
Now that the generic swiotlb code supports non-coherent DMA we can switch
to it for arm64. For that we need to refactor the existing
alloc/free/mmap/pgprot helpers to be used as the architecture hooks,
and implement the standard arch_sync_dma_for_{device,cpu} hooks for
cache maintaincance in the streaming dma hooks, which also implies
using the generic dma_coherent flag in struct device.
Note that we need to keep the old is_device_dma_coherent function around
for now, so that the shared arm/arm64 Xen code keeps working.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r-- | arch/arm64/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/device.h | 1 | ||||
-rw-r--r-- | arch/arm64/include/asm/dma-mapping.h | 7 | ||||
-rw-r--r-- | arch/arm64/mm/dma-mapping.c | 253 |
4 files changed, 55 insertions, 210 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1b1a0e95c751..c4db5131d837 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -11,6 +11,8 @@ config ARM64 | |||
11 | select ARCH_CLOCKSOURCE_DATA | 11 | select ARCH_CLOCKSOURCE_DATA |
12 | select ARCH_HAS_DEBUG_VIRTUAL | 12 | select ARCH_HAS_DEBUG_VIRTUAL |
13 | select ARCH_HAS_DEVMEM_IS_ALLOWED | 13 | select ARCH_HAS_DEVMEM_IS_ALLOWED |
14 | select ARCH_HAS_DMA_COHERENT_TO_PFN | ||
15 | select ARCH_HAS_DMA_MMAP_PGPROT | ||
14 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI | 16 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI |
15 | select ARCH_HAS_ELF_RANDOMIZE | 17 | select ARCH_HAS_ELF_RANDOMIZE |
16 | select ARCH_HAS_FAST_MULTIPLIER | 18 | select ARCH_HAS_FAST_MULTIPLIER |
@@ -24,6 +26,8 @@ config ARM64 | |||
24 | select ARCH_HAS_SG_CHAIN | 26 | select ARCH_HAS_SG_CHAIN |
25 | select ARCH_HAS_STRICT_KERNEL_RWX | 27 | select ARCH_HAS_STRICT_KERNEL_RWX |
26 | select ARCH_HAS_STRICT_MODULE_RWX | 28 | select ARCH_HAS_STRICT_MODULE_RWX |
29 | select ARCH_HAS_SYNC_DMA_FOR_DEVICE | ||
30 | select ARCH_HAS_SYNC_DMA_FOR_CPU | ||
27 | select ARCH_HAS_SYSCALL_WRAPPER | 31 | select ARCH_HAS_SYSCALL_WRAPPER |
28 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 32 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
29 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 33 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index 5a5fa47a6b18..3dd3d664c5c5 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h | |||
@@ -23,7 +23,6 @@ struct dev_archdata { | |||
23 | #ifdef CONFIG_XEN | 23 | #ifdef CONFIG_XEN |
24 | const struct dma_map_ops *dev_dma_ops; | 24 | const struct dma_map_ops *dev_dma_ops; |
25 | #endif | 25 | #endif |
26 | bool dma_coherent; | ||
27 | }; | 26 | }; |
28 | 27 | ||
29 | struct pdev_archdata { | 28 | struct pdev_archdata { |
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index b7847eb8a7bb..c41f3fb1446c 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h | |||
@@ -44,10 +44,13 @@ void arch_teardown_dma_ops(struct device *dev); | |||
44 | #define arch_teardown_dma_ops arch_teardown_dma_ops | 44 | #define arch_teardown_dma_ops arch_teardown_dma_ops |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | /* do not use this function in a driver */ | 47 | /* |
48 | * Do not use this function in a driver, it is only provided for | ||
49 | * arch/arm/mm/xen.c, which is used by arm64 as well. | ||
50 | */ | ||
48 | static inline bool is_device_dma_coherent(struct device *dev) | 51 | static inline bool is_device_dma_coherent(struct device *dev) |
49 | { | 52 | { |
50 | return dev->archdata.dma_coherent; | 53 | return dev->dma_coherent; |
51 | } | 54 | } |
52 | 55 | ||
53 | #endif /* __KERNEL__ */ | 56 | #endif /* __KERNEL__ */ |
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index eee6cfcfde9e..5a5d7990e980 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/genalloc.h> | 26 | #include <linux/genalloc.h> |
27 | #include <linux/dma-direct.h> | 27 | #include <linux/dma-direct.h> |
28 | #include <linux/dma-noncoherent.h> | ||
28 | #include <linux/dma-contiguous.h> | 29 | #include <linux/dma-contiguous.h> |
29 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
30 | #include <linux/swiotlb.h> | 31 | #include <linux/swiotlb.h> |
@@ -32,16 +33,6 @@ | |||
32 | 33 | ||
33 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
34 | 35 | ||
35 | static int swiotlb __ro_after_init; | ||
36 | |||
37 | static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, | ||
38 | bool coherent) | ||
39 | { | ||
40 | if (!coherent || (attrs & DMA_ATTR_WRITE_COMBINE)) | ||
41 | return pgprot_writecombine(prot); | ||
42 | return prot; | ||
43 | } | ||
44 | |||
45 | static struct gen_pool *atomic_pool __ro_after_init; | 36 | static struct gen_pool *atomic_pool __ro_after_init; |
46 | 37 | ||
47 | #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K | 38 | #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K |
@@ -91,18 +82,16 @@ static int __free_from_pool(void *start, size_t size) | |||
91 | return 1; | 82 | return 1; |
92 | } | 83 | } |
93 | 84 | ||
94 | static void *__dma_alloc(struct device *dev, size_t size, | 85 | void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, |
95 | dma_addr_t *dma_handle, gfp_t flags, | 86 | gfp_t flags, unsigned long attrs) |
96 | unsigned long attrs) | ||
97 | { | 87 | { |
98 | struct page *page; | 88 | struct page *page; |
99 | void *ptr, *coherent_ptr; | 89 | void *ptr, *coherent_ptr; |
100 | bool coherent = is_device_dma_coherent(dev); | 90 | pgprot_t prot = pgprot_writecombine(PAGE_KERNEL); |
101 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false); | ||
102 | 91 | ||
103 | size = PAGE_ALIGN(size); | 92 | size = PAGE_ALIGN(size); |
104 | 93 | ||
105 | if (!coherent && !gfpflags_allow_blocking(flags)) { | 94 | if (!gfpflags_allow_blocking(flags)) { |
106 | struct page *page = NULL; | 95 | struct page *page = NULL; |
107 | void *addr = __alloc_from_pool(size, &page, flags); | 96 | void *addr = __alloc_from_pool(size, &page, flags); |
108 | 97 | ||
@@ -116,10 +105,6 @@ static void *__dma_alloc(struct device *dev, size_t size, | |||
116 | if (!ptr) | 105 | if (!ptr) |
117 | goto no_mem; | 106 | goto no_mem; |
118 | 107 | ||
119 | /* no need for non-cacheable mapping if coherent */ | ||
120 | if (coherent) | ||
121 | return ptr; | ||
122 | |||
123 | /* remove any dirty cache lines on the kernel alias */ | 108 | /* remove any dirty cache lines on the kernel alias */ |
124 | __dma_flush_area(ptr, size); | 109 | __dma_flush_area(ptr, size); |
125 | 110 | ||
@@ -138,125 +123,52 @@ no_mem: | |||
138 | return NULL; | 123 | return NULL; |
139 | } | 124 | } |
140 | 125 | ||
141 | static void __dma_free(struct device *dev, size_t size, | 126 | void arch_dma_free(struct device *dev, size_t size, void *vaddr, |
142 | void *vaddr, dma_addr_t dma_handle, | 127 | dma_addr_t dma_handle, unsigned long attrs) |
143 | unsigned long attrs) | ||
144 | { | 128 | { |
145 | void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle)); | 129 | if (!__free_from_pool(vaddr, PAGE_ALIGN(size))) { |
130 | void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle)); | ||
146 | 131 | ||
147 | size = PAGE_ALIGN(size); | ||
148 | |||
149 | if (!is_device_dma_coherent(dev)) { | ||
150 | if (__free_from_pool(vaddr, size)) | ||
151 | return; | ||
152 | vunmap(vaddr); | 132 | vunmap(vaddr); |
133 | dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs); | ||
153 | } | 134 | } |
154 | dma_direct_free_pages(dev, size, swiotlb_addr, dma_handle, attrs); | ||
155 | } | 135 | } |
156 | 136 | ||
157 | static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page, | 137 | long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr, |
158 | unsigned long offset, size_t size, | 138 | dma_addr_t dma_addr) |
159 | enum dma_data_direction dir, | ||
160 | unsigned long attrs) | ||
161 | { | 139 | { |
162 | dma_addr_t dev_addr; | 140 | return __phys_to_pfn(dma_to_phys(dev, dma_addr)); |
163 | |||
164 | dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs); | ||
165 | if (!is_device_dma_coherent(dev) && | ||
166 | (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) | ||
167 | __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
168 | |||
169 | return dev_addr; | ||
170 | } | 141 | } |
171 | 142 | ||
172 | 143 | pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, | |
173 | static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr, | 144 | unsigned long attrs) |
174 | size_t size, enum dma_data_direction dir, | ||
175 | unsigned long attrs) | ||
176 | { | 145 | { |
177 | if (!is_device_dma_coherent(dev) && | 146 | if (!dev_is_dma_coherent(dev) || (attrs & DMA_ATTR_WRITE_COMBINE)) |
178 | (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) | 147 | return pgprot_writecombine(prot); |
179 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | 148 | return prot; |
180 | swiotlb_unmap_page(dev, dev_addr, size, dir, attrs); | ||
181 | } | ||
182 | |||
183 | static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl, | ||
184 | int nelems, enum dma_data_direction dir, | ||
185 | unsigned long attrs) | ||
186 | { | ||
187 | struct scatterlist *sg; | ||
188 | int i, ret; | ||
189 | |||
190 | ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs); | ||
191 | if (!is_device_dma_coherent(dev) && | ||
192 | (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) | ||
193 | for_each_sg(sgl, sg, ret, i) | ||
194 | __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
195 | sg->length, dir); | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static void __swiotlb_unmap_sg_attrs(struct device *dev, | ||
201 | struct scatterlist *sgl, int nelems, | ||
202 | enum dma_data_direction dir, | ||
203 | unsigned long attrs) | ||
204 | { | ||
205 | struct scatterlist *sg; | ||
206 | int i; | ||
207 | |||
208 | if (!is_device_dma_coherent(dev) && | ||
209 | (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) | ||
210 | for_each_sg(sgl, sg, nelems, i) | ||
211 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
212 | sg->length, dir); | ||
213 | swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs); | ||
214 | } | 149 | } |
215 | 150 | ||
216 | static void __swiotlb_sync_single_for_cpu(struct device *dev, | 151 | void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, |
217 | dma_addr_t dev_addr, size_t size, | 152 | size_t size, enum dma_data_direction dir) |
218 | enum dma_data_direction dir) | ||
219 | { | 153 | { |
220 | if (!is_device_dma_coherent(dev)) | 154 | __dma_map_area(phys_to_virt(paddr), size, dir); |
221 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
222 | swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir); | ||
223 | } | 155 | } |
224 | 156 | ||
225 | static void __swiotlb_sync_single_for_device(struct device *dev, | 157 | void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, |
226 | dma_addr_t dev_addr, size_t size, | 158 | size_t size, enum dma_data_direction dir) |
227 | enum dma_data_direction dir) | ||
228 | { | 159 | { |
229 | swiotlb_sync_single_for_device(dev, dev_addr, size, dir); | 160 | __dma_unmap_area(phys_to_virt(paddr), size, dir); |
230 | if (!is_device_dma_coherent(dev)) | ||
231 | __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
232 | } | 161 | } |
233 | 162 | ||
234 | static void __swiotlb_sync_sg_for_cpu(struct device *dev, | 163 | static int __swiotlb_get_sgtable_page(struct sg_table *sgt, |
235 | struct scatterlist *sgl, int nelems, | 164 | struct page *page, size_t size) |
236 | enum dma_data_direction dir) | ||
237 | { | 165 | { |
238 | struct scatterlist *sg; | 166 | int ret = sg_alloc_table(sgt, 1, GFP_KERNEL); |
239 | int i; | ||
240 | |||
241 | if (!is_device_dma_coherent(dev)) | ||
242 | for_each_sg(sgl, sg, nelems, i) | ||
243 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
244 | sg->length, dir); | ||
245 | swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir); | ||
246 | } | ||
247 | 167 | ||
248 | static void __swiotlb_sync_sg_for_device(struct device *dev, | 168 | if (!ret) |
249 | struct scatterlist *sgl, int nelems, | 169 | sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); |
250 | enum dma_data_direction dir) | ||
251 | { | ||
252 | struct scatterlist *sg; | ||
253 | int i; | ||
254 | 170 | ||
255 | swiotlb_sync_sg_for_device(dev, sgl, nelems, dir); | 171 | return ret; |
256 | if (!is_device_dma_coherent(dev)) | ||
257 | for_each_sg(sgl, sg, nelems, i) | ||
258 | __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
259 | sg->length, dir); | ||
260 | } | 172 | } |
261 | 173 | ||
262 | static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, | 174 | static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, |
@@ -277,74 +189,6 @@ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, | |||
277 | return ret; | 189 | return ret; |
278 | } | 190 | } |
279 | 191 | ||
280 | static int __swiotlb_mmap(struct device *dev, | ||
281 | struct vm_area_struct *vma, | ||
282 | void *cpu_addr, dma_addr_t dma_addr, size_t size, | ||
283 | unsigned long attrs) | ||
284 | { | ||
285 | int ret; | ||
286 | unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT; | ||
287 | |||
288 | vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, | ||
289 | is_device_dma_coherent(dev)); | ||
290 | |||
291 | if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) | ||
292 | return ret; | ||
293 | |||
294 | return __swiotlb_mmap_pfn(vma, pfn, size); | ||
295 | } | ||
296 | |||
297 | static int __swiotlb_get_sgtable_page(struct sg_table *sgt, | ||
298 | struct page *page, size_t size) | ||
299 | { | ||
300 | int ret = sg_alloc_table(sgt, 1, GFP_KERNEL); | ||
301 | |||
302 | if (!ret) | ||
303 | sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); | ||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt, | ||
309 | void *cpu_addr, dma_addr_t handle, size_t size, | ||
310 | unsigned long attrs) | ||
311 | { | ||
312 | struct page *page = phys_to_page(dma_to_phys(dev, handle)); | ||
313 | |||
314 | return __swiotlb_get_sgtable_page(sgt, page, size); | ||
315 | } | ||
316 | |||
317 | static int __swiotlb_dma_supported(struct device *hwdev, u64 mask) | ||
318 | { | ||
319 | if (swiotlb) | ||
320 | return swiotlb_dma_supported(hwdev, mask); | ||
321 | return 1; | ||
322 | } | ||
323 | |||
324 | static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr) | ||
325 | { | ||
326 | if (swiotlb) | ||
327 | return dma_direct_mapping_error(hwdev, addr); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static const struct dma_map_ops arm64_swiotlb_dma_ops = { | ||
332 | .alloc = __dma_alloc, | ||
333 | .free = __dma_free, | ||
334 | .mmap = __swiotlb_mmap, | ||
335 | .get_sgtable = __swiotlb_get_sgtable, | ||
336 | .map_page = __swiotlb_map_page, | ||
337 | .unmap_page = __swiotlb_unmap_page, | ||
338 | .map_sg = __swiotlb_map_sg_attrs, | ||
339 | .unmap_sg = __swiotlb_unmap_sg_attrs, | ||
340 | .sync_single_for_cpu = __swiotlb_sync_single_for_cpu, | ||
341 | .sync_single_for_device = __swiotlb_sync_single_for_device, | ||
342 | .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu, | ||
343 | .sync_sg_for_device = __swiotlb_sync_sg_for_device, | ||
344 | .dma_supported = __swiotlb_dma_supported, | ||
345 | .mapping_error = __swiotlb_dma_mapping_error, | ||
346 | }; | ||
347 | |||
348 | static int __init atomic_pool_init(void) | 192 | static int __init atomic_pool_init(void) |
349 | { | 193 | { |
350 | pgprot_t prot = __pgprot(PROT_NORMAL_NC); | 194 | pgprot_t prot = __pgprot(PROT_NORMAL_NC); |
@@ -500,10 +344,6 @@ EXPORT_SYMBOL(dummy_dma_ops); | |||
500 | 344 | ||
501 | static int __init arm64_dma_init(void) | 345 | static int __init arm64_dma_init(void) |
502 | { | 346 | { |
503 | if (swiotlb_force == SWIOTLB_FORCE || | ||
504 | max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) | ||
505 | swiotlb = 1; | ||
506 | |||
507 | WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(), | 347 | WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(), |
508 | TAINT_CPU_OUT_OF_SPEC, | 348 | TAINT_CPU_OUT_OF_SPEC, |
509 | "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", | 349 | "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", |
@@ -528,7 +368,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, | |||
528 | dma_addr_t *handle, gfp_t gfp, | 368 | dma_addr_t *handle, gfp_t gfp, |
529 | unsigned long attrs) | 369 | unsigned long attrs) |
530 | { | 370 | { |
531 | bool coherent = is_device_dma_coherent(dev); | 371 | bool coherent = dev_is_dma_coherent(dev); |
532 | int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs); | 372 | int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs); |
533 | size_t iosize = size; | 373 | size_t iosize = size; |
534 | void *addr; | 374 | void *addr; |
@@ -569,7 +409,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, | |||
569 | addr = NULL; | 409 | addr = NULL; |
570 | } | 410 | } |
571 | } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) { | 411 | } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) { |
572 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent); | 412 | pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs); |
573 | struct page *page; | 413 | struct page *page; |
574 | 414 | ||
575 | page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, | 415 | page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, |
@@ -596,7 +436,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, | |||
596 | size >> PAGE_SHIFT); | 436 | size >> PAGE_SHIFT); |
597 | } | 437 | } |
598 | } else { | 438 | } else { |
599 | pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent); | 439 | pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs); |
600 | struct page **pages; | 440 | struct page **pages; |
601 | 441 | ||
602 | pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot, | 442 | pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot, |
@@ -658,8 +498,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, | |||
658 | struct vm_struct *area; | 498 | struct vm_struct *area; |
659 | int ret; | 499 | int ret; |
660 | 500 | ||
661 | vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, | 501 | vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs); |
662 | is_device_dma_coherent(dev)); | ||
663 | 502 | ||
664 | if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) | 503 | if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) |
665 | return ret; | 504 | return ret; |
@@ -709,11 +548,11 @@ static void __iommu_sync_single_for_cpu(struct device *dev, | |||
709 | { | 548 | { |
710 | phys_addr_t phys; | 549 | phys_addr_t phys; |
711 | 550 | ||
712 | if (is_device_dma_coherent(dev)) | 551 | if (dev_is_dma_coherent(dev)) |
713 | return; | 552 | return; |
714 | 553 | ||
715 | phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); | 554 | phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); |
716 | __dma_unmap_area(phys_to_virt(phys), size, dir); | 555 | arch_sync_dma_for_cpu(dev, phys, size, dir); |
717 | } | 556 | } |
718 | 557 | ||
719 | static void __iommu_sync_single_for_device(struct device *dev, | 558 | static void __iommu_sync_single_for_device(struct device *dev, |
@@ -722,11 +561,11 @@ static void __iommu_sync_single_for_device(struct device *dev, | |||
722 | { | 561 | { |
723 | phys_addr_t phys; | 562 | phys_addr_t phys; |
724 | 563 | ||
725 | if (is_device_dma_coherent(dev)) | 564 | if (dev_is_dma_coherent(dev)) |
726 | return; | 565 | return; |
727 | 566 | ||
728 | phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); | 567 | phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); |
729 | __dma_map_area(phys_to_virt(phys), size, dir); | 568 | arch_sync_dma_for_device(dev, phys, size, dir); |
730 | } | 569 | } |
731 | 570 | ||
732 | static dma_addr_t __iommu_map_page(struct device *dev, struct page *page, | 571 | static dma_addr_t __iommu_map_page(struct device *dev, struct page *page, |
@@ -734,7 +573,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page, | |||
734 | enum dma_data_direction dir, | 573 | enum dma_data_direction dir, |
735 | unsigned long attrs) | 574 | unsigned long attrs) |
736 | { | 575 | { |
737 | bool coherent = is_device_dma_coherent(dev); | 576 | bool coherent = dev_is_dma_coherent(dev); |
738 | int prot = dma_info_to_prot(dir, coherent, attrs); | 577 | int prot = dma_info_to_prot(dir, coherent, attrs); |
739 | dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot); | 578 | dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot); |
740 | 579 | ||
@@ -762,11 +601,11 @@ static void __iommu_sync_sg_for_cpu(struct device *dev, | |||
762 | struct scatterlist *sg; | 601 | struct scatterlist *sg; |
763 | int i; | 602 | int i; |
764 | 603 | ||
765 | if (is_device_dma_coherent(dev)) | 604 | if (dev_is_dma_coherent(dev)) |
766 | return; | 605 | return; |
767 | 606 | ||
768 | for_each_sg(sgl, sg, nelems, i) | 607 | for_each_sg(sgl, sg, nelems, i) |
769 | __dma_unmap_area(sg_virt(sg), sg->length, dir); | 608 | arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir); |
770 | } | 609 | } |
771 | 610 | ||
772 | static void __iommu_sync_sg_for_device(struct device *dev, | 611 | static void __iommu_sync_sg_for_device(struct device *dev, |
@@ -776,18 +615,18 @@ static void __iommu_sync_sg_for_device(struct device *dev, | |||
776 | struct scatterlist *sg; | 615 | struct scatterlist *sg; |
777 | int i; | 616 | int i; |
778 | 617 | ||
779 | if (is_device_dma_coherent(dev)) | 618 | if (dev_is_dma_coherent(dev)) |
780 | return; | 619 | return; |
781 | 620 | ||
782 | for_each_sg(sgl, sg, nelems, i) | 621 | for_each_sg(sgl, sg, nelems, i) |
783 | __dma_map_area(sg_virt(sg), sg->length, dir); | 622 | arch_sync_dma_for_device(dev, sg_phys(sg), sg->length, dir); |
784 | } | 623 | } |
785 | 624 | ||
786 | static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl, | 625 | static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl, |
787 | int nelems, enum dma_data_direction dir, | 626 | int nelems, enum dma_data_direction dir, |
788 | unsigned long attrs) | 627 | unsigned long attrs) |
789 | { | 628 | { |
790 | bool coherent = is_device_dma_coherent(dev); | 629 | bool coherent = dev_is_dma_coherent(dev); |
791 | 630 | ||
792 | if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) | 631 | if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) |
793 | __iommu_sync_sg_for_device(dev, sgl, nelems, dir); | 632 | __iommu_sync_sg_for_device(dev, sgl, nelems, dir); |
@@ -879,9 +718,9 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | |||
879 | const struct iommu_ops *iommu, bool coherent) | 718 | const struct iommu_ops *iommu, bool coherent) |
880 | { | 719 | { |
881 | if (!dev->dma_ops) | 720 | if (!dev->dma_ops) |
882 | dev->dma_ops = &arm64_swiotlb_dma_ops; | 721 | dev->dma_ops = &swiotlb_dma_ops; |
883 | 722 | ||
884 | dev->archdata.dma_coherent = coherent; | 723 | dev->dma_coherent = coherent; |
885 | __iommu_setup_dma_ops(dev, dma_base, size, iommu); | 724 | __iommu_setup_dma_ops(dev, dma_base, size, iommu); |
886 | 725 | ||
887 | #ifdef CONFIG_XEN | 726 | #ifdef CONFIG_XEN |