diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2011-12-29 07:09:51 -0500 |
---|---|---|
committer | Marek Szyprowski <m.szyprowski@samsung.com> | 2012-05-21 09:09:38 -0400 |
commit | 0a2b9a6ea93650b8a00f9fd5ee8fdd25671e2df6 (patch) | |
tree | c930063ff30882db67e110774bf8b46497d23f15 /arch/x86 | |
parent | c64be2bb1c6eb43c838b2c6d57b074078be208dd (diff) |
X86: integrate CMA with DMA-mapping subsystem
This patch adds support for CMA to dma-mapping subsystem for x86
architecture that uses common pci-dma/pci-nommu implementation. This
allows to test CMA on KVM/QEMU and a lot of common x86 boxes.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: Michal Nazarewicz <mina86@mina86.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/dma-contiguous.h | 13 | ||||
-rw-r--r-- | arch/x86/include/asm/dma-mapping.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/pci-nommu.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 2 |
6 files changed, 38 insertions, 9 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c9866b0b77d8..7cbdfdac3c7c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -31,6 +31,7 @@ config X86 | |||
31 | select ARCH_WANT_OPTIONAL_GPIOLIB | 31 | select ARCH_WANT_OPTIONAL_GPIOLIB |
32 | select ARCH_WANT_FRAME_POINTERS | 32 | select ARCH_WANT_FRAME_POINTERS |
33 | select HAVE_DMA_ATTRS | 33 | select HAVE_DMA_ATTRS |
34 | select HAVE_DMA_CONTIGUOUS if !SWIOTLB | ||
34 | select HAVE_KRETPROBES | 35 | select HAVE_KRETPROBES |
35 | select HAVE_OPTPROBES | 36 | select HAVE_OPTPROBES |
36 | select HAVE_FTRACE_MCOUNT_RECORD | 37 | select HAVE_FTRACE_MCOUNT_RECORD |
diff --git a/arch/x86/include/asm/dma-contiguous.h b/arch/x86/include/asm/dma-contiguous.h new file mode 100644 index 000000000000..c09241659971 --- /dev/null +++ b/arch/x86/include/asm/dma-contiguous.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef ASMX86_DMA_CONTIGUOUS_H | ||
2 | #define ASMX86_DMA_CONTIGUOUS_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | #include <linux/types.h> | ||
7 | #include <asm-generic/dma-contiguous.h> | ||
8 | |||
9 | static inline void | ||
10 | dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { } | ||
11 | |||
12 | #endif | ||
13 | #endif | ||
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 4b4331d71935..7b9227b44b9b 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/swiotlb.h> | 14 | #include <asm/swiotlb.h> |
15 | #include <asm-generic/dma-coherent.h> | 15 | #include <asm-generic/dma-coherent.h> |
16 | #include <linux/dma-contiguous.h> | ||
16 | 17 | ||
17 | #ifdef CONFIG_ISA | 18 | #ifdef CONFIG_ISA |
18 | # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24) | 19 | # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24) |
@@ -62,6 +63,10 @@ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, | |||
62 | dma_addr_t *dma_addr, gfp_t flag, | 63 | dma_addr_t *dma_addr, gfp_t flag, |
63 | struct dma_attrs *attrs); | 64 | struct dma_attrs *attrs); |
64 | 65 | ||
66 | extern void dma_generic_free_coherent(struct device *dev, size_t size, | ||
67 | void *vaddr, dma_addr_t dma_addr, | ||
68 | struct dma_attrs *attrs); | ||
69 | |||
65 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | 70 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) |
66 | { | 71 | { |
67 | if (!dev->dma_mask) | 72 | if (!dev->dma_mask) |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 3003250ac51d..62c9457ccd2f 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -100,14 +100,18 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, | |||
100 | struct dma_attrs *attrs) | 100 | struct dma_attrs *attrs) |
101 | { | 101 | { |
102 | unsigned long dma_mask; | 102 | unsigned long dma_mask; |
103 | struct page *page; | 103 | struct page *page = NULL; |
104 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
104 | dma_addr_t addr; | 105 | dma_addr_t addr; |
105 | 106 | ||
106 | dma_mask = dma_alloc_coherent_mask(dev, flag); | 107 | dma_mask = dma_alloc_coherent_mask(dev, flag); |
107 | 108 | ||
108 | flag |= __GFP_ZERO; | 109 | flag |= __GFP_ZERO; |
109 | again: | 110 | again: |
110 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | 111 | if (!(flag & GFP_ATOMIC)) |
112 | page = dma_alloc_from_contiguous(dev, count, get_order(size)); | ||
113 | if (!page) | ||
114 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | ||
111 | if (!page) | 115 | if (!page) |
112 | return NULL; | 116 | return NULL; |
113 | 117 | ||
@@ -127,6 +131,16 @@ again: | |||
127 | return page_address(page); | 131 | return page_address(page); |
128 | } | 132 | } |
129 | 133 | ||
134 | void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
135 | dma_addr_t dma_addr, struct dma_attrs *attrs) | ||
136 | { | ||
137 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
138 | struct page *page = virt_to_page(vaddr); | ||
139 | |||
140 | if (!dma_release_from_contiguous(dev, page, count)) | ||
141 | free_pages((unsigned long)vaddr, get_order(size)); | ||
142 | } | ||
143 | |||
130 | /* | 144 | /* |
131 | * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel | 145 | * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel |
132 | * parameter documentation. | 146 | * parameter documentation. |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index f96050685b46..871be4a84c7d 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c | |||
@@ -74,12 +74,6 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
74 | return nents; | 74 | return nents; |
75 | } | 75 | } |
76 | 76 | ||
77 | static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
78 | dma_addr_t dma_addr, struct dma_attrs *attrs) | ||
79 | { | ||
80 | free_pages((unsigned long)vaddr, get_order(size)); | ||
81 | } | ||
82 | |||
83 | static void nommu_sync_single_for_device(struct device *dev, | 77 | static void nommu_sync_single_for_device(struct device *dev, |
84 | dma_addr_t addr, size_t size, | 78 | dma_addr_t addr, size_t size, |
85 | enum dma_data_direction dir) | 79 | enum dma_data_direction dir) |
@@ -97,7 +91,7 @@ static void nommu_sync_sg_for_device(struct device *dev, | |||
97 | 91 | ||
98 | struct dma_map_ops nommu_dma_ops = { | 92 | struct dma_map_ops nommu_dma_ops = { |
99 | .alloc = dma_generic_alloc_coherent, | 93 | .alloc = dma_generic_alloc_coherent, |
100 | .free = nommu_free_coherent, | 94 | .free = dma_generic_free_coherent, |
101 | .map_sg = nommu_map_sg, | 95 | .map_sg = nommu_map_sg, |
102 | .map_page = nommu_map_page, | 96 | .map_page = nommu_map_page, |
103 | .sync_single_for_device = nommu_sync_single_for_device, | 97 | .sync_single_for_device = nommu_sync_single_for_device, |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 1a2901562059..d6c956e674cc 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <asm/pci-direct.h> | 50 | #include <asm/pci-direct.h> |
51 | #include <linux/init_ohci1394_dma.h> | 51 | #include <linux/init_ohci1394_dma.h> |
52 | #include <linux/kvm_para.h> | 52 | #include <linux/kvm_para.h> |
53 | #include <linux/dma-contiguous.h> | ||
53 | 54 | ||
54 | #include <linux/errno.h> | 55 | #include <linux/errno.h> |
55 | #include <linux/kernel.h> | 56 | #include <linux/kernel.h> |
@@ -934,6 +935,7 @@ void __init setup_arch(char **cmdline_p) | |||
934 | } | 935 | } |
935 | #endif | 936 | #endif |
936 | memblock.current_limit = get_max_mapped(); | 937 | memblock.current_limit = get_max_mapped(); |
938 | dma_contiguous_reserve(0); | ||
937 | 939 | ||
938 | /* | 940 | /* |
939 | * NOTE: On x86-32, only from this point on, fixmaps are ready for use. | 941 | * NOTE: On x86-32, only from this point on, fixmaps are ready for use. |