diff options
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 31 | ||||
-rw-r--r-- | arch/x86/kernel/pci-nommu.c | 39 | ||||
-rw-r--r-- | include/asm-x86/dma-mapping.h | 3 |
3 files changed, 35 insertions, 38 deletions
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0a1408abcc62..4e612d20170a 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -134,6 +134,37 @@ unsigned long iommu_num_pages(unsigned long addr, unsigned long len) | |||
134 | EXPORT_SYMBOL(iommu_num_pages); | 134 | EXPORT_SYMBOL(iommu_num_pages); |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | void *dma_generic_alloc_coherent(struct device *dev, size_t size, | ||
138 | dma_addr_t *dma_addr, gfp_t flag) | ||
139 | { | ||
140 | unsigned long dma_mask; | ||
141 | struct page *page; | ||
142 | dma_addr_t addr; | ||
143 | |||
144 | dma_mask = dma_alloc_coherent_mask(dev, flag); | ||
145 | |||
146 | flag |= __GFP_ZERO; | ||
147 | again: | ||
148 | page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); | ||
149 | if (!page) | ||
150 | return NULL; | ||
151 | |||
152 | addr = page_to_phys(page); | ||
153 | if (!is_buffer_dma_capable(dma_mask, addr, size)) { | ||
154 | __free_pages(page, get_order(size)); | ||
155 | |||
156 | if (dma_mask < DMA_32BIT_MASK && !(flag & GFP_DMA)) { | ||
157 | flag = (flag & ~GFP_DMA32) | GFP_DMA; | ||
158 | goto again; | ||
159 | } | ||
160 | |||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | *dma_addr = addr; | ||
165 | return page_address(page); | ||
166 | } | ||
167 | |||
137 | /* | 168 | /* |
138 | * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter | 169 | * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter |
139 | * documentation. | 170 | * documentation. |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 1c1c98a31d57..c70ab5a5d4c8 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c | |||
@@ -72,43 +72,6 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
72 | return nents; | 72 | return nents; |
73 | } | 73 | } |
74 | 74 | ||
75 | static void * | ||
76 | nommu_alloc_coherent(struct device *hwdev, size_t size, | ||
77 | dma_addr_t *dma_addr, gfp_t gfp) | ||
78 | { | ||
79 | unsigned long dma_mask; | ||
80 | int node; | ||
81 | struct page *page; | ||
82 | dma_addr_t addr; | ||
83 | |||
84 | dma_mask = dma_alloc_coherent_mask(hwdev, gfp); | ||
85 | |||
86 | gfp |= __GFP_ZERO; | ||
87 | |||
88 | node = dev_to_node(hwdev); | ||
89 | again: | ||
90 | page = alloc_pages_node(node, gfp, get_order(size)); | ||
91 | if (!page) | ||
92 | return NULL; | ||
93 | |||
94 | addr = page_to_phys(page); | ||
95 | if (!is_buffer_dma_capable(dma_mask, addr, size) && !(gfp & GFP_DMA)) { | ||
96 | free_pages((unsigned long)page_address(page), get_order(size)); | ||
97 | gfp |= GFP_DMA; | ||
98 | goto again; | ||
99 | } | ||
100 | |||
101 | if (check_addr("alloc_coherent", hwdev, addr, size)) { | ||
102 | *dma_addr = addr; | ||
103 | flush_write_buffers(); | ||
104 | return page_address(page); | ||
105 | } | ||
106 | |||
107 | free_pages((unsigned long)page_address(page), get_order(size)); | ||
108 | |||
109 | return NULL; | ||
110 | } | ||
111 | |||
112 | static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, | 75 | static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, |
113 | dma_addr_t dma_addr) | 76 | dma_addr_t dma_addr) |
114 | { | 77 | { |
@@ -116,7 +79,7 @@ static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, | |||
116 | } | 79 | } |
117 | 80 | ||
118 | struct dma_mapping_ops nommu_dma_ops = { | 81 | struct dma_mapping_ops nommu_dma_ops = { |
119 | .alloc_coherent = nommu_alloc_coherent, | 82 | .alloc_coherent = dma_generic_alloc_coherent, |
120 | .free_coherent = nommu_free_coherent, | 83 | .free_coherent = nommu_free_coherent, |
121 | .map_single = nommu_map_single, | 84 | .map_single = nommu_map_single, |
122 | .map_sg = nommu_map_sg, | 85 | .map_sg = nommu_map_sg, |
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index f408e6dd1778..3b808e9bb72c 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h | |||
@@ -89,6 +89,9 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | |||
89 | extern int dma_supported(struct device *hwdev, u64 mask); | 89 | extern int dma_supported(struct device *hwdev, u64 mask); |
90 | extern int dma_set_mask(struct device *dev, u64 mask); | 90 | extern int dma_set_mask(struct device *dev, u64 mask); |
91 | 91 | ||
92 | extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, | ||
93 | dma_addr_t *dma_addr, gfp_t flag); | ||
94 | |||
92 | static inline dma_addr_t | 95 | static inline dma_addr_t |
93 | dma_map_single(struct device *hwdev, void *ptr, size_t size, | 96 | dma_map_single(struct device *hwdev, void *ptr, size_t size, |
94 | int direction) | 97 | int direction) |