diff options
author | Christoph Hellwig <hch@lst.de> | 2018-03-19 06:38:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2018-03-20 05:01:56 -0400 |
commit | fec777c385b6376048fc4b08f039366545b335cd (patch) | |
tree | a613e68a5746d74d69bf3aa06818b05119d8e500 | |
parent | 038d07a283d62336b32cc23b62aecdf9418cfc11 (diff) |
x86/dma: Use DMA-direct (CONFIG_DMA_DIRECT_OPS=y)
The generic DMA-direct (CONFIG_DMA_DIRECT_OPS=y) implementation is now
functionally equivalent to the x86 nommu dma_map implementation, so
switch over to using it.
That includes switching from using x86_dma_supported in various IOMMU
drivers to use dma_direct_supported instead, which provides the same
functionality.
Tested-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Jon Mason <jdmason@kudzu.us>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Muli Ben-Yehuda <mulix@mulix.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: iommu@lists.linux-foundation.org
Link: http://lkml.kernel.org/r/20180319103826.12853-4-hch@lst.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/dma-mapping.h | 8 | ||||
-rw-r--r-- | arch/x86/include/asm/iommu.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kernel/amd_gart_64.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/pci-calgary_64.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 66 | ||||
-rw-r--r-- | arch/x86/kernel/pci-swiotlb.c | 5 | ||||
-rw-r--r-- | arch/x86/pci/sta2x11-fixup.c | 2 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu.c | 7 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 3 |
11 files changed, 17 insertions, 90 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 18233e459bff..7dc347217d3a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -83,6 +83,7 @@ config X86 | |||
83 | select CLOCKSOURCE_VALIDATE_LAST_CYCLE | 83 | select CLOCKSOURCE_VALIDATE_LAST_CYCLE |
84 | select CLOCKSOURCE_WATCHDOG | 84 | select CLOCKSOURCE_WATCHDOG |
85 | select DCACHE_WORD_ACCESS | 85 | select DCACHE_WORD_ACCESS |
86 | select DMA_DIRECT_OPS | ||
86 | select EDAC_ATOMIC_SCRUB | 87 | select EDAC_ATOMIC_SCRUB |
87 | select EDAC_SUPPORT | 88 | select EDAC_SUPPORT |
88 | select GENERIC_CLOCKEVENTS | 89 | select GENERIC_CLOCKEVENTS |
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 545bf3721bc0..df9816b385eb 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h | |||
@@ -36,14 +36,6 @@ int arch_dma_supported(struct device *dev, u64 mask); | |||
36 | bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp); | 36 | bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp); |
37 | #define arch_dma_alloc_attrs arch_dma_alloc_attrs | 37 | #define arch_dma_alloc_attrs arch_dma_alloc_attrs |
38 | 38 | ||
39 | extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, | ||
40 | dma_addr_t *dma_addr, gfp_t flag, | ||
41 | unsigned long attrs); | ||
42 | |||
43 | extern void dma_generic_free_coherent(struct device *dev, size_t size, | ||
44 | void *vaddr, dma_addr_t dma_addr, | ||
45 | unsigned long attrs); | ||
46 | |||
47 | static inline gfp_t dma_alloc_coherent_gfp_flags(struct device *dev, gfp_t gfp) | 39 | static inline gfp_t dma_alloc_coherent_gfp_flags(struct device *dev, gfp_t gfp) |
48 | { | 40 | { |
49 | if (dev->coherent_dma_mask <= DMA_BIT_MASK(24)) | 41 | if (dev->coherent_dma_mask <= DMA_BIT_MASK(24)) |
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index 1e5d5d92eb40..baedab8ac538 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h | |||
@@ -2,13 +2,10 @@ | |||
2 | #ifndef _ASM_X86_IOMMU_H | 2 | #ifndef _ASM_X86_IOMMU_H |
3 | #define _ASM_X86_IOMMU_H | 3 | #define _ASM_X86_IOMMU_H |
4 | 4 | ||
5 | extern const struct dma_map_ops nommu_dma_ops; | ||
6 | extern int force_iommu, no_iommu; | 5 | extern int force_iommu, no_iommu; |
7 | extern int iommu_detected; | 6 | extern int iommu_detected; |
8 | extern int iommu_pass_through; | 7 | extern int iommu_pass_through; |
9 | 8 | ||
10 | int x86_dma_supported(struct device *dev, u64 mask); | ||
11 | |||
12 | /* 10 seconds */ | 9 | /* 10 seconds */ |
13 | #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) | 10 | #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) |
14 | 11 | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 29786c87e864..2e8c8a09ecab 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -57,7 +57,7 @@ obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o | |||
57 | obj-$(CONFIG_SYSFS) += ksysfs.o | 57 | obj-$(CONFIG_SYSFS) += ksysfs.o |
58 | obj-y += bootflag.o e820.o | 58 | obj-y += bootflag.o e820.o |
59 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o | 59 | obj-y += pci-dma.o quirks.o topology.o kdebugfs.o |
60 | obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o | 60 | obj-y += alternative.o i8253.o hw_breakpoint.o |
61 | obj-y += tsc.o tsc_msr.o io_delay.o rtc.o | 61 | obj-y += tsc.o tsc_msr.o io_delay.o rtc.o |
62 | obj-y += pci-iommu_table.o | 62 | obj-y += pci-iommu_table.o |
63 | obj-y += resource.o | 63 | obj-y += resource.o |
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index ecd486cb06ab..52e3abcf3e70 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c | |||
@@ -501,8 +501,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, | |||
501 | } | 501 | } |
502 | __free_pages(page, get_order(size)); | 502 | __free_pages(page, get_order(size)); |
503 | } else | 503 | } else |
504 | return dma_generic_alloc_coherent(dev, size, dma_addr, flag, | 504 | return dma_direct_alloc(dev, size, dma_addr, flag, attrs); |
505 | attrs); | ||
506 | 505 | ||
507 | return NULL; | 506 | return NULL; |
508 | } | 507 | } |
@@ -513,7 +512,7 @@ gart_free_coherent(struct device *dev, size_t size, void *vaddr, | |||
513 | dma_addr_t dma_addr, unsigned long attrs) | 512 | dma_addr_t dma_addr, unsigned long attrs) |
514 | { | 513 | { |
515 | gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0); | 514 | gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0); |
516 | dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs); | 515 | dma_direct_free(dev, size, vaddr, dma_addr, attrs); |
517 | } | 516 | } |
518 | 517 | ||
519 | static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr) | 518 | static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr) |
@@ -705,7 +704,7 @@ static const struct dma_map_ops gart_dma_ops = { | |||
705 | .alloc = gart_alloc_coherent, | 704 | .alloc = gart_alloc_coherent, |
706 | .free = gart_free_coherent, | 705 | .free = gart_free_coherent, |
707 | .mapping_error = gart_mapping_error, | 706 | .mapping_error = gart_mapping_error, |
708 | .dma_supported = x86_dma_supported, | 707 | .dma_supported = dma_direct_supported, |
709 | }; | 708 | }; |
710 | 709 | ||
711 | static void gart_iommu_shutdown(void) | 710 | static void gart_iommu_shutdown(void) |
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 35c461f21815..5647853053bd 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/crash_dump.h> | 34 | #include <linux/crash_dump.h> |
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/dma-direct.h> | ||
36 | #include <linux/bitmap.h> | 37 | #include <linux/bitmap.h> |
37 | #include <linux/pci_ids.h> | 38 | #include <linux/pci_ids.h> |
38 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
@@ -493,7 +494,7 @@ static const struct dma_map_ops calgary_dma_ops = { | |||
493 | .map_page = calgary_map_page, | 494 | .map_page = calgary_map_page, |
494 | .unmap_page = calgary_unmap_page, | 495 | .unmap_page = calgary_unmap_page, |
495 | .mapping_error = calgary_mapping_error, | 496 | .mapping_error = calgary_mapping_error, |
496 | .dma_supported = x86_dma_supported, | 497 | .dma_supported = dma_direct_supported, |
497 | }; | 498 | }; |
498 | 499 | ||
499 | static inline void __iomem * busno_to_bbar(unsigned char num) | 500 | static inline void __iomem * busno_to_bbar(unsigned char num) |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index b59820872ec7..db0b88ea8d1b 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | static int forbid_dac __read_mostly; | 19 | static int forbid_dac __read_mostly; |
20 | 20 | ||
21 | const struct dma_map_ops *dma_ops = &nommu_dma_ops; | 21 | const struct dma_map_ops *dma_ops = &dma_direct_ops; |
22 | EXPORT_SYMBOL(dma_ops); | 22 | EXPORT_SYMBOL(dma_ops); |
23 | 23 | ||
24 | static int iommu_sac_force __read_mostly; | 24 | static int iommu_sac_force __read_mostly; |
@@ -76,60 +76,6 @@ void __init pci_iommu_alloc(void) | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | } | 78 | } |
79 | void *dma_generic_alloc_coherent(struct device *dev, size_t size, | ||
80 | dma_addr_t *dma_addr, gfp_t flag, | ||
81 | unsigned long attrs) | ||
82 | { | ||
83 | struct page *page; | ||
84 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
85 | dma_addr_t addr; | ||
86 | |||
87 | again: | ||
88 | page = NULL; | ||
89 | /* CMA can be used only in the context which permits sleeping */ | ||
90 | if (gfpflags_allow_blocking(flag)) { | ||
91 | page = dma_alloc_from_contiguous(dev, count, get_order(size), | ||
92 | flag); | ||
93 | if (page) { | ||
94 | addr = phys_to_dma(dev, page_to_phys(page)); | ||
95 | if (addr + size > dev->coherent_dma_mask) { | ||
96 | dma_release_from_contiguous(dev, page, count); | ||
97 | page = NULL; | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | /* fallback */ | ||
102 | if (!page) | ||
103 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | ||
104 | if (!page) | ||
105 | return NULL; | ||
106 | |||
107 | addr = phys_to_dma(dev, page_to_phys(page)); | ||
108 | if (addr + size > dev->coherent_dma_mask) { | ||
109 | __free_pages(page, get_order(size)); | ||
110 | |||
111 | if (dev->coherent_dma_mask < DMA_BIT_MASK(32) && | ||
112 | !(flag & GFP_DMA)) { | ||
113 | flag = (flag & ~GFP_DMA32) | GFP_DMA; | ||
114 | goto again; | ||
115 | } | ||
116 | |||
117 | return NULL; | ||
118 | } | ||
119 | memset(page_address(page), 0, size); | ||
120 | *dma_addr = addr; | ||
121 | return page_address(page); | ||
122 | } | ||
123 | |||
124 | void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
125 | dma_addr_t dma_addr, unsigned long attrs) | ||
126 | { | ||
127 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
128 | struct page *page = virt_to_page(vaddr); | ||
129 | |||
130 | if (!dma_release_from_contiguous(dev, page, count)) | ||
131 | free_pages((unsigned long)vaddr, get_order(size)); | ||
132 | } | ||
133 | 79 | ||
134 | bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp) | 80 | bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp) |
135 | { | 81 | { |
@@ -243,16 +189,6 @@ int arch_dma_supported(struct device *dev, u64 mask) | |||
243 | } | 189 | } |
244 | EXPORT_SYMBOL(arch_dma_supported); | 190 | EXPORT_SYMBOL(arch_dma_supported); |
245 | 191 | ||
246 | int x86_dma_supported(struct device *dev, u64 mask) | ||
247 | { | ||
248 | /* Copied from i386. Doesn't make much sense, because it will | ||
249 | only work for pci_alloc_coherent. | ||
250 | The caller just has to use GFP_DMA in this case. */ | ||
251 | if (mask < DMA_BIT_MASK(24)) | ||
252 | return 0; | ||
253 | return 1; | ||
254 | } | ||
255 | |||
256 | static int __init pci_iommu_init(void) | 192 | static int __init pci_iommu_init(void) |
257 | { | 193 | { |
258 | struct iommu_table_entry *p; | 194 | struct iommu_table_entry *p; |
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index 0ee0f8f34251..bcb6a9bf64ad 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c | |||
@@ -30,8 +30,7 @@ void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
30 | */ | 30 | */ |
31 | flags |= __GFP_NOWARN; | 31 | flags |= __GFP_NOWARN; |
32 | 32 | ||
33 | vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags, | 33 | vaddr = dma_direct_alloc(hwdev, size, dma_handle, flags, attrs); |
34 | attrs); | ||
35 | if (vaddr) | 34 | if (vaddr) |
36 | return vaddr; | 35 | return vaddr; |
37 | 36 | ||
@@ -45,7 +44,7 @@ void x86_swiotlb_free_coherent(struct device *dev, size_t size, | |||
45 | if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr))) | 44 | if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr))) |
46 | swiotlb_free_coherent(dev, size, vaddr, dma_addr); | 45 | swiotlb_free_coherent(dev, size, vaddr, dma_addr); |
47 | else | 46 | else |
48 | dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs); | 47 | dma_direct_free(dev, size, vaddr, dma_addr, attrs); |
49 | } | 48 | } |
50 | 49 | ||
51 | static const struct dma_map_ops x86_swiotlb_dma_ops = { | 50 | static const struct dma_map_ops x86_swiotlb_dma_ops = { |
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c index 75577c1490c4..6c712fe11bdc 100644 --- a/arch/x86/pci/sta2x11-fixup.c +++ b/arch/x86/pci/sta2x11-fixup.c | |||
@@ -193,7 +193,7 @@ static const struct dma_map_ops sta2x11_dma_ops = { | |||
193 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, | 193 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, |
194 | .sync_sg_for_device = swiotlb_sync_sg_for_device, | 194 | .sync_sg_for_device = swiotlb_sync_sg_for_device, |
195 | .mapping_error = swiotlb_dma_mapping_error, | 195 | .mapping_error = swiotlb_dma_mapping_error, |
196 | .dma_supported = x86_dma_supported, | 196 | .dma_supported = dma_direct_supported, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | /* At setup time, we use our own ops if the device is a ConneXt one */ | 199 | /* At setup time, we use our own ops if the device is a ConneXt one */ |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 74788fdeb773..0bf19423b588 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/debugfs.h> | 28 | #include <linux/debugfs.h> |
29 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
30 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
31 | #include <linux/dma-direct.h> | ||
31 | #include <linux/iommu-helper.h> | 32 | #include <linux/iommu-helper.h> |
32 | #include <linux/iommu.h> | 33 | #include <linux/iommu.h> |
33 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
@@ -2193,7 +2194,7 @@ static int amd_iommu_add_device(struct device *dev) | |||
2193 | dev_name(dev)); | 2194 | dev_name(dev)); |
2194 | 2195 | ||
2195 | iommu_ignore_device(dev); | 2196 | iommu_ignore_device(dev); |
2196 | dev->dma_ops = &nommu_dma_ops; | 2197 | dev->dma_ops = &dma_direct_ops; |
2197 | goto out; | 2198 | goto out; |
2198 | } | 2199 | } |
2199 | init_iommu_group(dev); | 2200 | init_iommu_group(dev); |
@@ -2680,7 +2681,7 @@ free_mem: | |||
2680 | */ | 2681 | */ |
2681 | static int amd_iommu_dma_supported(struct device *dev, u64 mask) | 2682 | static int amd_iommu_dma_supported(struct device *dev, u64 mask) |
2682 | { | 2683 | { |
2683 | if (!x86_dma_supported(dev, mask)) | 2684 | if (!dma_direct_supported(dev, mask)) |
2684 | return 0; | 2685 | return 0; |
2685 | return check_device(dev); | 2686 | return check_device(dev); |
2686 | } | 2687 | } |
@@ -2794,7 +2795,7 @@ int __init amd_iommu_init_dma_ops(void) | |||
2794 | * continue to be SWIOTLB. | 2795 | * continue to be SWIOTLB. |
2795 | */ | 2796 | */ |
2796 | if (!swiotlb) | 2797 | if (!swiotlb) |
2797 | dma_ops = &nommu_dma_ops; | 2798 | dma_ops = &dma_direct_ops; |
2798 | 2799 | ||
2799 | if (amd_iommu_unmap_flush) | 2800 | if (amd_iommu_unmap_flush) |
2800 | pr_info("AMD-Vi: IO/TLB flush on unmap enabled\n"); | 2801 | pr_info("AMD-Vi: IO/TLB flush on unmap enabled\n"); |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 582fd01cb7d1..fd899b2a12bb 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/pci-ats.h> | 45 | #include <linux/pci-ats.h> |
46 | #include <linux/memblock.h> | 46 | #include <linux/memblock.h> |
47 | #include <linux/dma-contiguous.h> | 47 | #include <linux/dma-contiguous.h> |
48 | #include <linux/dma-direct.h> | ||
48 | #include <linux/crash_dump.h> | 49 | #include <linux/crash_dump.h> |
49 | #include <asm/irq_remapping.h> | 50 | #include <asm/irq_remapping.h> |
50 | #include <asm/cacheflush.h> | 51 | #include <asm/cacheflush.h> |
@@ -3871,7 +3872,7 @@ const struct dma_map_ops intel_dma_ops = { | |||
3871 | .unmap_page = intel_unmap_page, | 3872 | .unmap_page = intel_unmap_page, |
3872 | .mapping_error = intel_mapping_error, | 3873 | .mapping_error = intel_mapping_error, |
3873 | #ifdef CONFIG_X86 | 3874 | #ifdef CONFIG_X86 |
3874 | .dma_supported = x86_dma_supported, | 3875 | .dma_supported = dma_direct_supported, |
3875 | #endif | 3876 | #endif |
3876 | }; | 3877 | }; |
3877 | 3878 | ||