diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-19 16:27:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-19 16:27:23 -0400 |
commit | 671df189537883f36cf9c7d4f9495bfac0f86627 (patch) | |
tree | 22e5f598ed1f5d9b2218d85d4426140f804d61e6 /arch/arm | |
parent | c9fe5630dae1df2328d82042602e2c4d1add8d57 (diff) | |
parent | c7d9eccb3c1e802c5cbb2a764eb0eb9807d9f12e (diff) |
Merge tag 'dma-mapping-5.4' of git://git.infradead.org/users/hch/dma-mapping
Pull dma-mapping updates from Christoph Hellwig:
- add dma-mapping and block layer helpers to take care of IOMMU merging
for mmc plus subsequent fixups (Yoshihiro Shimoda)
- rework handling of the pgprot bits for remapping (me)
- take care of the dma direct infrastructure for swiotlb-xen (me)
- improve the dma noncoherent remapping infrastructure (me)
- better defaults for ->mmap, ->get_sgtable and ->get_required_mask
(me)
- cleanup mmaping of coherent DMA allocations (me)
- various misc cleanups (Andy Shevchenko, me)
* tag 'dma-mapping-5.4' of git://git.infradead.org/users/hch/dma-mapping: (41 commits)
mmc: renesas_sdhi_internal_dmac: Add MMC_CAP2_MERGE_CAPABLE
mmc: queue: Fix bigger segments usage
arm64: use asm-generic/dma-mapping.h
swiotlb-xen: merge xen_unmap_single into xen_swiotlb_unmap_page
swiotlb-xen: simplify cache maintainance
swiotlb-xen: use the same foreign page check everywhere
swiotlb-xen: remove xen_swiotlb_dma_mmap and xen_swiotlb_dma_get_sgtable
xen: remove the exports for xen_{create,destroy}_contiguous_region
xen/arm: remove xen_dma_ops
xen/arm: simplify dma_cache_maint
xen/arm: use dev_is_dma_coherent
xen/arm: consolidate page-coherent.h
xen/arm: use dma-noncoherent.h calls for xen-swiotlb cache maintainance
arm: remove wrappers for the generic dma remap helpers
dma-mapping: introduce a dma_common_find_pages helper
dma-mapping: always use VM_DMA_COHERENT for generic DMA remap
vmalloc: lift the arm flag for coherent mappings to common code
dma-mapping: provide a better default ->get_required_mask
dma-mapping: remove the dma_declare_coherent_memory export
remoteproc: don't allow modular build
...
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/device.h | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 6 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-nommu.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/page-coherent.h | 93 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping-nommu.c | 5 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 84 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 3 | ||||
-rw-r--r-- | arch/arm/xen/mm.c | 129 |
9 files changed, 55 insertions, 271 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2ae7f8adcac4..aa1d3b25e89f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -8,7 +8,7 @@ config ARM | |||
8 | select ARCH_HAS_DEBUG_VIRTUAL if MMU | 8 | select ARCH_HAS_DEBUG_VIRTUAL if MMU |
9 | select ARCH_HAS_DEVMEM_IS_ALLOWED | 9 | select ARCH_HAS_DEVMEM_IS_ALLOWED |
10 | select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB | 10 | select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB |
11 | select ARCH_HAS_DMA_MMAP_PGPROT if SWIOTLB | 11 | select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE |
12 | select ARCH_HAS_ELF_RANDOMIZE | 12 | select ARCH_HAS_ELF_RANDOMIZE |
13 | select ARCH_HAS_FORTIFY_SOURCE | 13 | select ARCH_HAS_FORTIFY_SOURCE |
14 | select ARCH_HAS_KEEPINITRD | 14 | select ARCH_HAS_KEEPINITRD |
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index f6955b55c544..c675bc0d5aa8 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h | |||
@@ -15,9 +15,6 @@ struct dev_archdata { | |||
15 | #ifdef CONFIG_ARM_DMA_USE_IOMMU | 15 | #ifdef CONFIG_ARM_DMA_USE_IOMMU |
16 | struct dma_iommu_mapping *mapping; | 16 | struct dma_iommu_mapping *mapping; |
17 | #endif | 17 | #endif |
18 | #ifdef CONFIG_XEN | ||
19 | const struct dma_map_ops *dev_dma_ops; | ||
20 | #endif | ||
21 | unsigned int dma_coherent:1; | 18 | unsigned int dma_coherent:1; |
22 | unsigned int dma_ops_setup:1; | 19 | unsigned int dma_ops_setup:1; |
23 | }; | 20 | }; |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index dba9355e2484..bdd80ddbca34 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -91,12 +91,6 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
91 | } | 91 | } |
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | /* do not use this function in a driver */ | ||
95 | static inline bool is_device_dma_coherent(struct device *dev) | ||
96 | { | ||
97 | return dev->archdata.dma_coherent; | ||
98 | } | ||
99 | |||
100 | /** | 94 | /** |
101 | * arm_dma_alloc - allocate consistent memory for DMA | 95 | * arm_dma_alloc - allocate consistent memory for DMA |
102 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | 96 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices |
diff --git a/arch/arm/include/asm/pgtable-nommu.h b/arch/arm/include/asm/pgtable-nommu.h index 0b1f6799a32e..d0de24f06724 100644 --- a/arch/arm/include/asm/pgtable-nommu.h +++ b/arch/arm/include/asm/pgtable-nommu.h | |||
@@ -62,7 +62,6 @@ typedef pte_t *pte_addr_t; | |||
62 | */ | 62 | */ |
63 | #define pgprot_noncached(prot) (prot) | 63 | #define pgprot_noncached(prot) (prot) |
64 | #define pgprot_writecombine(prot) (prot) | 64 | #define pgprot_writecombine(prot) (prot) |
65 | #define pgprot_dmacoherent(prot) (prot) | ||
66 | #define pgprot_device(prot) (prot) | 65 | #define pgprot_device(prot) (prot) |
67 | 66 | ||
68 | 67 | ||
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h index 2c403e7c782d..27e984977402 100644 --- a/arch/arm/include/asm/xen/page-coherent.h +++ b/arch/arm/include/asm/xen/page-coherent.h | |||
@@ -1,95 +1,2 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _ASM_ARM_XEN_PAGE_COHERENT_H | ||
3 | #define _ASM_ARM_XEN_PAGE_COHERENT_H | ||
4 | |||
5 | #include <linux/dma-mapping.h> | ||
6 | #include <asm/page.h> | ||
7 | #include <xen/arm/page-coherent.h> | 2 | #include <xen/arm/page-coherent.h> |
8 | |||
9 | static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev) | ||
10 | { | ||
11 | if (dev && dev->archdata.dev_dma_ops) | ||
12 | return dev->archdata.dev_dma_ops; | ||
13 | return get_arch_dma_ops(NULL); | ||
14 | } | ||
15 | |||
16 | static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size, | ||
17 | dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs) | ||
18 | { | ||
19 | return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs); | ||
20 | } | ||
21 | |||
22 | static inline void xen_free_coherent_pages(struct device *hwdev, size_t size, | ||
23 | void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) | ||
24 | { | ||
25 | xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs); | ||
26 | } | ||
27 | |||
28 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, | ||
29 | dma_addr_t dev_addr, unsigned long offset, size_t size, | ||
30 | enum dma_data_direction dir, unsigned long attrs) | ||
31 | { | ||
32 | unsigned long page_pfn = page_to_xen_pfn(page); | ||
33 | unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr); | ||
34 | unsigned long compound_pages = | ||
35 | (1<<compound_order(page)) * XEN_PFN_PER_PAGE; | ||
36 | bool local = (page_pfn <= dev_pfn) && | ||
37 | (dev_pfn - page_pfn < compound_pages); | ||
38 | |||
39 | /* | ||
40 | * Dom0 is mapped 1:1, while the Linux page can span across | ||
41 | * multiple Xen pages, it's not possible for it to contain a | ||
42 | * mix of local and foreign Xen pages. So if the first xen_pfn | ||
43 | * == mfn the page is local otherwise it's a foreign page | ||
44 | * grant-mapped in dom0. If the page is local we can safely | ||
45 | * call the native dma_ops function, otherwise we call the xen | ||
46 | * specific function. | ||
47 | */ | ||
48 | if (local) | ||
49 | xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs); | ||
50 | else | ||
51 | __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs); | ||
52 | } | ||
53 | |||
54 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
55 | size_t size, enum dma_data_direction dir, unsigned long attrs) | ||
56 | { | ||
57 | unsigned long pfn = PFN_DOWN(handle); | ||
58 | /* | ||
59 | * Dom0 is mapped 1:1, while the Linux page can be spanned accross | ||
60 | * multiple Xen page, it's not possible to have a mix of local and | ||
61 | * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a | ||
62 | * foreign mfn will always return false. If the page is local we can | ||
63 | * safely call the native dma_ops function, otherwise we call the xen | ||
64 | * specific function. | ||
65 | */ | ||
66 | if (pfn_valid(pfn)) { | ||
67 | if (xen_get_dma_ops(hwdev)->unmap_page) | ||
68 | xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs); | ||
69 | } else | ||
70 | __xen_dma_unmap_page(hwdev, handle, size, dir, attrs); | ||
71 | } | ||
72 | |||
73 | static inline void xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
74 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
75 | { | ||
76 | unsigned long pfn = PFN_DOWN(handle); | ||
77 | if (pfn_valid(pfn)) { | ||
78 | if (xen_get_dma_ops(hwdev)->sync_single_for_cpu) | ||
79 | xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir); | ||
80 | } else | ||
81 | __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir); | ||
82 | } | ||
83 | |||
84 | static inline void xen_dma_sync_single_for_device(struct device *hwdev, | ||
85 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
86 | { | ||
87 | unsigned long pfn = PFN_DOWN(handle); | ||
88 | if (pfn_valid(pfn)) { | ||
89 | if (xen_get_dma_ops(hwdev)->sync_single_for_device) | ||
90 | xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir); | ||
91 | } else | ||
92 | __xen_dma_sync_single_for_device(hwdev, handle, size, dir); | ||
93 | } | ||
94 | |||
95 | #endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */ | ||
diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index 52b82559d99b..db9247898300 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c | |||
@@ -68,8 +68,9 @@ static int arm_nommu_dma_mmap(struct device *dev, struct vm_area_struct *vma, | |||
68 | 68 | ||
69 | if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret)) | 69 | if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret)) |
70 | return ret; | 70 | return ret; |
71 | 71 | if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) | |
72 | return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size, attrs); | 72 | return ret; |
73 | return -ENXIO; | ||
73 | } | 74 | } |
74 | 75 | ||
75 | 76 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index d42557ee69c2..7d042d5c43e3 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/dma-direct.h> | ||
17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
18 | #include <linux/dma-noncoherent.h> | 19 | #include <linux/dma-noncoherent.h> |
19 | #include <linux/dma-contiguous.h> | 20 | #include <linux/dma-contiguous.h> |
@@ -35,6 +36,7 @@ | |||
35 | #include <asm/mach/map.h> | 36 | #include <asm/mach/map.h> |
36 | #include <asm/system_info.h> | 37 | #include <asm/system_info.h> |
37 | #include <asm/dma-contiguous.h> | 38 | #include <asm/dma-contiguous.h> |
39 | #include <xen/swiotlb-xen.h> | ||
38 | 40 | ||
39 | #include "dma.h" | 41 | #include "dma.h" |
40 | #include "mm.h" | 42 | #include "mm.h" |
@@ -192,6 +194,7 @@ const struct dma_map_ops arm_dma_ops = { | |||
192 | .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu, | 194 | .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu, |
193 | .sync_sg_for_device = arm_dma_sync_sg_for_device, | 195 | .sync_sg_for_device = arm_dma_sync_sg_for_device, |
194 | .dma_supported = arm_dma_supported, | 196 | .dma_supported = arm_dma_supported, |
197 | .get_required_mask = dma_direct_get_required_mask, | ||
195 | }; | 198 | }; |
196 | EXPORT_SYMBOL(arm_dma_ops); | 199 | EXPORT_SYMBOL(arm_dma_ops); |
197 | 200 | ||
@@ -212,6 +215,7 @@ const struct dma_map_ops arm_coherent_dma_ops = { | |||
212 | .map_sg = arm_dma_map_sg, | 215 | .map_sg = arm_dma_map_sg, |
213 | .map_resource = dma_direct_map_resource, | 216 | .map_resource = dma_direct_map_resource, |
214 | .dma_supported = arm_dma_supported, | 217 | .dma_supported = arm_dma_supported, |
218 | .get_required_mask = dma_direct_get_required_mask, | ||
215 | }; | 219 | }; |
216 | EXPORT_SYMBOL(arm_coherent_dma_ops); | 220 | EXPORT_SYMBOL(arm_coherent_dma_ops); |
217 | 221 | ||
@@ -336,25 +340,6 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, | |||
336 | pgprot_t prot, struct page **ret_page, | 340 | pgprot_t prot, struct page **ret_page, |
337 | const void *caller, bool want_vaddr); | 341 | const void *caller, bool want_vaddr); |
338 | 342 | ||
339 | static void * | ||
340 | __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, | ||
341 | const void *caller) | ||
342 | { | ||
343 | /* | ||
344 | * DMA allocation can be mapped to user space, so lets | ||
345 | * set VM_USERMAP flags too. | ||
346 | */ | ||
347 | return dma_common_contiguous_remap(page, size, | ||
348 | VM_ARM_DMA_CONSISTENT | VM_USERMAP, | ||
349 | prot, caller); | ||
350 | } | ||
351 | |||
352 | static void __dma_free_remap(void *cpu_addr, size_t size) | ||
353 | { | ||
354 | dma_common_free_remap(cpu_addr, size, | ||
355 | VM_ARM_DMA_CONSISTENT | VM_USERMAP); | ||
356 | } | ||
357 | |||
358 | #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K | 343 | #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K |
359 | static struct gen_pool *atomic_pool __ro_after_init; | 344 | static struct gen_pool *atomic_pool __ro_after_init; |
360 | 345 | ||
@@ -510,7 +495,7 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, | |||
510 | if (!want_vaddr) | 495 | if (!want_vaddr) |
511 | goto out; | 496 | goto out; |
512 | 497 | ||
513 | ptr = __dma_alloc_remap(page, size, gfp, prot, caller); | 498 | ptr = dma_common_contiguous_remap(page, size, prot, caller); |
514 | if (!ptr) { | 499 | if (!ptr) { |
515 | __dma_free_buffer(page, size); | 500 | __dma_free_buffer(page, size); |
516 | return NULL; | 501 | return NULL; |
@@ -577,7 +562,7 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size, | |||
577 | goto out; | 562 | goto out; |
578 | 563 | ||
579 | if (PageHighMem(page)) { | 564 | if (PageHighMem(page)) { |
580 | ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot, caller); | 565 | ptr = dma_common_contiguous_remap(page, size, prot, caller); |
581 | if (!ptr) { | 566 | if (!ptr) { |
582 | dma_release_from_contiguous(dev, page, count); | 567 | dma_release_from_contiguous(dev, page, count); |
583 | return NULL; | 568 | return NULL; |
@@ -597,7 +582,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page, | |||
597 | { | 582 | { |
598 | if (want_vaddr) { | 583 | if (want_vaddr) { |
599 | if (PageHighMem(page)) | 584 | if (PageHighMem(page)) |
600 | __dma_free_remap(cpu_addr, size); | 585 | dma_common_free_remap(cpu_addr, size); |
601 | else | 586 | else |
602 | __dma_remap(page, size, PAGE_KERNEL); | 587 | __dma_remap(page, size, PAGE_KERNEL); |
603 | } | 588 | } |
@@ -689,7 +674,7 @@ static void *remap_allocator_alloc(struct arm_dma_alloc_args *args, | |||
689 | static void remap_allocator_free(struct arm_dma_free_args *args) | 674 | static void remap_allocator_free(struct arm_dma_free_args *args) |
690 | { | 675 | { |
691 | if (args->want_vaddr) | 676 | if (args->want_vaddr) |
692 | __dma_free_remap(args->cpu_addr, args->size); | 677 | dma_common_free_remap(args->cpu_addr, args->size); |
693 | 678 | ||
694 | __dma_free_buffer(args->page, args->size); | 679 | __dma_free_buffer(args->page, args->size); |
695 | } | 680 | } |
@@ -877,17 +862,6 @@ static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_add | |||
877 | __arm_dma_free(dev, size, cpu_addr, handle, attrs, true); | 862 | __arm_dma_free(dev, size, cpu_addr, handle, attrs, true); |
878 | } | 863 | } |
879 | 864 | ||
880 | /* | ||
881 | * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems | ||
882 | * that the intention is to allow exporting memory allocated via the | ||
883 | * coherent DMA APIs through the dma_buf API, which only accepts a | ||
884 | * scattertable. This presents a couple of problems: | ||
885 | * 1. Not all memory allocated via the coherent DMA APIs is backed by | ||
886 | * a struct page | ||
887 | * 2. Passing coherent DMA memory into the streaming APIs is not allowed | ||
888 | * as we will try to flush the memory through a different alias to that | ||
889 | * actually being used (and the flushes are redundant.) | ||
890 | */ | ||
891 | int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, | 865 | int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, |
892 | void *cpu_addr, dma_addr_t handle, size_t size, | 866 | void *cpu_addr, dma_addr_t handle, size_t size, |
893 | unsigned long attrs) | 867 | unsigned long attrs) |
@@ -1132,10 +1106,6 @@ static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent) | |||
1132 | * 32-bit DMA. | 1106 | * 32-bit DMA. |
1133 | * Use the generic dma-direct / swiotlb ops code in that case, as that | 1107 | * Use the generic dma-direct / swiotlb ops code in that case, as that |
1134 | * handles bounce buffering for us. | 1108 | * handles bounce buffering for us. |
1135 | * | ||
1136 | * Note: this checks CONFIG_ARM_LPAE instead of CONFIG_SWIOTLB as the | ||
1137 | * latter is also selected by the Xen code, but that code for now relies | ||
1138 | * on non-NULL dev_dma_ops. To be cleaned up later. | ||
1139 | */ | 1109 | */ |
1140 | if (IS_ENABLED(CONFIG_ARM_LPAE)) | 1110 | if (IS_ENABLED(CONFIG_ARM_LPAE)) |
1141 | return NULL; | 1111 | return NULL; |
@@ -1373,17 +1343,6 @@ static int __iommu_free_buffer(struct device *dev, struct page **pages, | |||
1373 | } | 1343 | } |
1374 | 1344 | ||
1375 | /* | 1345 | /* |
1376 | * Create a CPU mapping for a specified pages | ||
1377 | */ | ||
1378 | static void * | ||
1379 | __iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot, | ||
1380 | const void *caller) | ||
1381 | { | ||
1382 | return dma_common_pages_remap(pages, size, | ||
1383 | VM_ARM_DMA_CONSISTENT | VM_USERMAP, prot, caller); | ||
1384 | } | ||
1385 | |||
1386 | /* | ||
1387 | * Create a mapping in device IO address space for specified pages | 1346 | * Create a mapping in device IO address space for specified pages |
1388 | */ | 1347 | */ |
1389 | static dma_addr_t | 1348 | static dma_addr_t |
@@ -1455,18 +1414,13 @@ static struct page **__atomic_get_pages(void *addr) | |||
1455 | 1414 | ||
1456 | static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs) | 1415 | static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs) |
1457 | { | 1416 | { |
1458 | struct vm_struct *area; | ||
1459 | |||
1460 | if (__in_atomic_pool(cpu_addr, PAGE_SIZE)) | 1417 | if (__in_atomic_pool(cpu_addr, PAGE_SIZE)) |
1461 | return __atomic_get_pages(cpu_addr); | 1418 | return __atomic_get_pages(cpu_addr); |
1462 | 1419 | ||
1463 | if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) | 1420 | if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) |
1464 | return cpu_addr; | 1421 | return cpu_addr; |
1465 | 1422 | ||
1466 | area = find_vm_area(cpu_addr); | 1423 | return dma_common_find_pages(cpu_addr); |
1467 | if (area && (area->flags & VM_ARM_DMA_CONSISTENT)) | ||
1468 | return area->pages; | ||
1469 | return NULL; | ||
1470 | } | 1424 | } |
1471 | 1425 | ||
1472 | static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp, | 1426 | static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp, |
@@ -1539,7 +1493,7 @@ static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size, | |||
1539 | if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) | 1493 | if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) |
1540 | return pages; | 1494 | return pages; |
1541 | 1495 | ||
1542 | addr = __iommu_alloc_remap(pages, size, gfp, prot, | 1496 | addr = dma_common_pages_remap(pages, size, prot, |
1543 | __builtin_return_address(0)); | 1497 | __builtin_return_address(0)); |
1544 | if (!addr) | 1498 | if (!addr) |
1545 | goto err_mapping; | 1499 | goto err_mapping; |
@@ -1622,10 +1576,8 @@ void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, | |||
1622 | return; | 1576 | return; |
1623 | } | 1577 | } |
1624 | 1578 | ||
1625 | if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) { | 1579 | if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) |
1626 | dma_common_free_remap(cpu_addr, size, | 1580 | dma_common_free_remap(cpu_addr, size); |
1627 | VM_ARM_DMA_CONSISTENT | VM_USERMAP); | ||
1628 | } | ||
1629 | 1581 | ||
1630 | __iommu_remove_mapping(dev, handle, size); | 1582 | __iommu_remove_mapping(dev, handle, size); |
1631 | __iommu_free_buffer(dev, pages, size, attrs); | 1583 | __iommu_free_buffer(dev, pages, size, attrs); |
@@ -2363,10 +2315,8 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | |||
2363 | set_dma_ops(dev, dma_ops); | 2315 | set_dma_ops(dev, dma_ops); |
2364 | 2316 | ||
2365 | #ifdef CONFIG_XEN | 2317 | #ifdef CONFIG_XEN |
2366 | if (xen_initial_domain()) { | 2318 | if (xen_initial_domain()) |
2367 | dev->archdata.dev_dma_ops = dev->dma_ops; | 2319 | dev->dma_ops = &xen_swiotlb_dma_ops; |
2368 | dev->dma_ops = xen_dma_ops; | ||
2369 | } | ||
2370 | #endif | 2320 | #endif |
2371 | dev->archdata.dma_ops_setup = true; | 2321 | dev->archdata.dma_ops_setup = true; |
2372 | } | 2322 | } |
@@ -2402,12 +2352,6 @@ long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr, | |||
2402 | return dma_to_pfn(dev, dma_addr); | 2352 | return dma_to_pfn(dev, dma_addr); |
2403 | } | 2353 | } |
2404 | 2354 | ||
2405 | pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, | ||
2406 | unsigned long attrs) | ||
2407 | { | ||
2408 | return __get_dma_pgprot(attrs, prot); | ||
2409 | } | ||
2410 | |||
2411 | void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, | 2355 | void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, |
2412 | gfp_t gfp, unsigned long attrs) | 2356 | gfp_t gfp, unsigned long attrs) |
2413 | { | 2357 | { |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 941356d95a67..88c121ac14b3 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -70,9 +70,6 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page | |||
70 | #define VM_ARM_MTYPE(mt) ((mt) << 20) | 70 | #define VM_ARM_MTYPE(mt) ((mt) << 20) |
71 | #define VM_ARM_MTYPE_MASK (0x1f << 20) | 71 | #define VM_ARM_MTYPE_MASK (0x1f << 20) |
72 | 72 | ||
73 | /* consistent regions used by dma_alloc_attrs() */ | ||
74 | #define VM_ARM_DMA_CONSISTENT 0x20000000 | ||
75 | |||
76 | 73 | ||
77 | struct static_vm { | 74 | struct static_vm { |
78 | struct vm_struct vm; | 75 | struct vm_struct vm; |
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c index d33b77e9add3..2b2c208408bb 100644 --- a/arch/arm/xen/mm.c +++ b/arch/arm/xen/mm.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <linux/cpu.h> | 2 | #include <linux/cpu.h> |
3 | #include <linux/dma-mapping.h> | 3 | #include <linux/dma-noncoherent.h> |
4 | #include <linux/gfp.h> | 4 | #include <linux/gfp.h> |
5 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
6 | #include <linux/export.h> | 6 | #include <linux/export.h> |
@@ -35,105 +35,56 @@ unsigned long xen_get_swiotlb_free_pages(unsigned int order) | |||
35 | return __get_free_pages(flags, order); | 35 | return __get_free_pages(flags, order); |
36 | } | 36 | } |
37 | 37 | ||
38 | enum dma_cache_op { | ||
39 | DMA_UNMAP, | ||
40 | DMA_MAP, | ||
41 | }; | ||
42 | static bool hypercall_cflush = false; | 38 | static bool hypercall_cflush = false; |
43 | 39 | ||
44 | /* functions called by SWIOTLB */ | 40 | /* buffers in highmem or foreign pages cannot cross page boundaries */ |
45 | 41 | static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op) | |
46 | static void dma_cache_maint(dma_addr_t handle, unsigned long offset, | ||
47 | size_t size, enum dma_data_direction dir, enum dma_cache_op op) | ||
48 | { | 42 | { |
49 | struct gnttab_cache_flush cflush; | 43 | struct gnttab_cache_flush cflush; |
50 | unsigned long xen_pfn; | ||
51 | size_t left = size; | ||
52 | 44 | ||
53 | xen_pfn = (handle >> XEN_PAGE_SHIFT) + offset / XEN_PAGE_SIZE; | 45 | cflush.a.dev_bus_addr = handle & XEN_PAGE_MASK; |
54 | offset %= XEN_PAGE_SIZE; | 46 | cflush.offset = xen_offset_in_page(handle); |
47 | cflush.op = op; | ||
55 | 48 | ||
56 | do { | 49 | do { |
57 | size_t len = left; | 50 | if (size + cflush.offset > XEN_PAGE_SIZE) |
58 | 51 | cflush.length = XEN_PAGE_SIZE - cflush.offset; | |
59 | /* buffers in highmem or foreign pages cannot cross page | 52 | else |
60 | * boundaries */ | 53 | cflush.length = size; |
61 | if (len + offset > XEN_PAGE_SIZE) | ||
62 | len = XEN_PAGE_SIZE - offset; | ||
63 | |||
64 | cflush.op = 0; | ||
65 | cflush.a.dev_bus_addr = xen_pfn << XEN_PAGE_SHIFT; | ||
66 | cflush.offset = offset; | ||
67 | cflush.length = len; | ||
68 | |||
69 | if (op == DMA_UNMAP && dir != DMA_TO_DEVICE) | ||
70 | cflush.op = GNTTAB_CACHE_INVAL; | ||
71 | if (op == DMA_MAP) { | ||
72 | if (dir == DMA_FROM_DEVICE) | ||
73 | cflush.op = GNTTAB_CACHE_INVAL; | ||
74 | else | ||
75 | cflush.op = GNTTAB_CACHE_CLEAN; | ||
76 | } | ||
77 | if (cflush.op) | ||
78 | HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1); | ||
79 | 54 | ||
80 | offset = 0; | 55 | HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1); |
81 | xen_pfn++; | ||
82 | left -= len; | ||
83 | } while (left); | ||
84 | } | ||
85 | 56 | ||
86 | static void __xen_dma_page_dev_to_cpu(struct device *hwdev, dma_addr_t handle, | 57 | cflush.offset = 0; |
87 | size_t size, enum dma_data_direction dir) | 58 | cflush.a.dev_bus_addr += cflush.length; |
88 | { | 59 | size -= cflush.length; |
89 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, DMA_UNMAP); | 60 | } while (size); |
90 | } | 61 | } |
91 | 62 | ||
92 | static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle, | 63 | /* |
93 | size_t size, enum dma_data_direction dir) | 64 | * Dom0 is mapped 1:1, and while the Linux page can span across multiple Xen |
65 | * pages, it is not possible for it to contain a mix of local and foreign Xen | ||
66 | * pages. Calling pfn_valid on a foreign mfn will always return false, so if | ||
67 | * pfn_valid returns true the pages is local and we can use the native | ||
68 | * dma-direct functions, otherwise we call the Xen specific version. | ||
69 | */ | ||
70 | void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle, | ||
71 | phys_addr_t paddr, size_t size, enum dma_data_direction dir) | ||
94 | { | 72 | { |
95 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, DMA_MAP); | 73 | if (pfn_valid(PFN_DOWN(handle))) |
74 | arch_sync_dma_for_cpu(dev, paddr, size, dir); | ||
75 | else if (dir != DMA_TO_DEVICE) | ||
76 | dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL); | ||
96 | } | 77 | } |
97 | 78 | ||
98 | void __xen_dma_map_page(struct device *hwdev, struct page *page, | 79 | void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle, |
99 | dma_addr_t dev_addr, unsigned long offset, size_t size, | 80 | phys_addr_t paddr, size_t size, enum dma_data_direction dir) |
100 | enum dma_data_direction dir, unsigned long attrs) | ||
101 | { | 81 | { |
102 | if (is_device_dma_coherent(hwdev)) | 82 | if (pfn_valid(PFN_DOWN(handle))) |
103 | return; | 83 | arch_sync_dma_for_device(dev, paddr, size, dir); |
104 | if (attrs & DMA_ATTR_SKIP_CPU_SYNC) | 84 | else if (dir == DMA_FROM_DEVICE) |
105 | return; | 85 | dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL); |
106 | 86 | else | |
107 | __xen_dma_page_cpu_to_dev(hwdev, dev_addr, size, dir); | 87 | dma_cache_maint(handle, size, GNTTAB_CACHE_CLEAN); |
108 | } | ||
109 | |||
110 | void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
111 | size_t size, enum dma_data_direction dir, | ||
112 | unsigned long attrs) | ||
113 | |||
114 | { | ||
115 | if (is_device_dma_coherent(hwdev)) | ||
116 | return; | ||
117 | if (attrs & DMA_ATTR_SKIP_CPU_SYNC) | ||
118 | return; | ||
119 | |||
120 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
121 | } | ||
122 | |||
123 | void __xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
124 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
125 | { | ||
126 | if (is_device_dma_coherent(hwdev)) | ||
127 | return; | ||
128 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
129 | } | ||
130 | |||
131 | void __xen_dma_sync_single_for_device(struct device *hwdev, | ||
132 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
133 | { | ||
134 | if (is_device_dma_coherent(hwdev)) | ||
135 | return; | ||
136 | __xen_dma_page_cpu_to_dev(hwdev, handle, size, dir); | ||
137 | } | 88 | } |
138 | 89 | ||
139 | bool xen_arch_need_swiotlb(struct device *dev, | 90 | bool xen_arch_need_swiotlb(struct device *dev, |
@@ -159,7 +110,7 @@ bool xen_arch_need_swiotlb(struct device *dev, | |||
159 | * memory and we are not able to flush the cache. | 110 | * memory and we are not able to flush the cache. |
160 | */ | 111 | */ |
161 | return (!hypercall_cflush && (xen_pfn != bfn) && | 112 | return (!hypercall_cflush && (xen_pfn != bfn) && |
162 | !is_device_dma_coherent(dev)); | 113 | !dev_is_dma_coherent(dev)); |
163 | } | 114 | } |
164 | 115 | ||
165 | int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, | 116 | int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, |
@@ -173,16 +124,11 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, | |||
173 | *dma_handle = pstart; | 124 | *dma_handle = pstart; |
174 | return 0; | 125 | return 0; |
175 | } | 126 | } |
176 | EXPORT_SYMBOL_GPL(xen_create_contiguous_region); | ||
177 | 127 | ||
178 | void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) | 128 | void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) |
179 | { | 129 | { |
180 | return; | 130 | return; |
181 | } | 131 | } |
182 | EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); | ||
183 | |||
184 | const struct dma_map_ops *xen_dma_ops; | ||
185 | EXPORT_SYMBOL(xen_dma_ops); | ||
186 | 132 | ||
187 | int __init xen_mm_init(void) | 133 | int __init xen_mm_init(void) |
188 | { | 134 | { |
@@ -190,7 +136,6 @@ int __init xen_mm_init(void) | |||
190 | if (!xen_initial_domain()) | 136 | if (!xen_initial_domain()) |
191 | return 0; | 137 | return 0; |
192 | xen_swiotlb_init(1, false); | 138 | xen_swiotlb_init(1, false); |
193 | xen_dma_ops = &xen_swiotlb_dma_ops; | ||
194 | 139 | ||
195 | cflush.op = 0; | 140 | cflush.op = 0; |
196 | cflush.a.dev_bus_addr = 0; | 141 | cflush.a.dev_bus_addr = 0; |