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 | |
| 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>
| -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. |
