diff options
author | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2008-06-29 06:19:31 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-30 06:51:07 -0400 |
commit | 323ec001c6bb98eeabb5abbdbb8c8055d9496554 (patch) | |
tree | 81ecd6918ebf9022af054ff18b06c856e0e6c54b | |
parent | ee7e5516be4f2107535ad5a3d47d9c79f93661a2 (diff) |
x86: use generic per-device dma coherent allocator
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 122 | ||||
-rw-r--r-- | include/asm-x86/dma-mapping.h | 22 |
3 files changed, 4 insertions, 141 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e0edaaa6920a..9d4714e0020c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -25,6 +25,7 @@ config X86 | |||
25 | select HAVE_KRETPROBES | 25 | select HAVE_KRETPROBES |
26 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) | 26 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) |
27 | select HAVE_ARCH_KGDB if !X86_VOYAGER | 27 | select HAVE_ARCH_KGDB if !X86_VOYAGER |
28 | select HAVE_GENERIC_DMA_COHERENT if X86_32 | ||
28 | 29 | ||
29 | config ARCH_DEFCONFIG | 30 | config ARCH_DEFCONFIG |
30 | string | 31 | string |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index dc00a1331ace..b75c81a8d3e6 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -197,124 +197,6 @@ static __init int iommu_setup(char *p) | |||
197 | } | 197 | } |
198 | early_param("iommu", iommu_setup); | 198 | early_param("iommu", iommu_setup); |
199 | 199 | ||
200 | #ifdef CONFIG_X86_32 | ||
201 | int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, | ||
202 | dma_addr_t device_addr, size_t size, int flags) | ||
203 | { | ||
204 | void __iomem *mem_base = NULL; | ||
205 | int pages = size >> PAGE_SHIFT; | ||
206 | int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); | ||
207 | |||
208 | if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) | ||
209 | goto out; | ||
210 | if (!size) | ||
211 | goto out; | ||
212 | if (dev->dma_mem) | ||
213 | goto out; | ||
214 | |||
215 | /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ | ||
216 | |||
217 | mem_base = ioremap(bus_addr, size); | ||
218 | if (!mem_base) | ||
219 | goto out; | ||
220 | |||
221 | dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); | ||
222 | if (!dev->dma_mem) | ||
223 | goto out; | ||
224 | dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); | ||
225 | if (!dev->dma_mem->bitmap) | ||
226 | goto free1_out; | ||
227 | |||
228 | dev->dma_mem->virt_base = mem_base; | ||
229 | dev->dma_mem->device_base = device_addr; | ||
230 | dev->dma_mem->size = pages; | ||
231 | dev->dma_mem->flags = flags; | ||
232 | |||
233 | if (flags & DMA_MEMORY_MAP) | ||
234 | return DMA_MEMORY_MAP; | ||
235 | |||
236 | return DMA_MEMORY_IO; | ||
237 | |||
238 | free1_out: | ||
239 | kfree(dev->dma_mem); | ||
240 | out: | ||
241 | if (mem_base) | ||
242 | iounmap(mem_base); | ||
243 | return 0; | ||
244 | } | ||
245 | EXPORT_SYMBOL(dma_declare_coherent_memory); | ||
246 | |||
247 | void dma_release_declared_memory(struct device *dev) | ||
248 | { | ||
249 | struct dma_coherent_mem *mem = dev->dma_mem; | ||
250 | |||
251 | if (!mem) | ||
252 | return; | ||
253 | dev->dma_mem = NULL; | ||
254 | iounmap(mem->virt_base); | ||
255 | kfree(mem->bitmap); | ||
256 | kfree(mem); | ||
257 | } | ||
258 | EXPORT_SYMBOL(dma_release_declared_memory); | ||
259 | |||
260 | void *dma_mark_declared_memory_occupied(struct device *dev, | ||
261 | dma_addr_t device_addr, size_t size) | ||
262 | { | ||
263 | struct dma_coherent_mem *mem = dev->dma_mem; | ||
264 | int pos, err; | ||
265 | int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1); | ||
266 | |||
267 | pages >>= PAGE_SHIFT; | ||
268 | |||
269 | if (!mem) | ||
270 | return ERR_PTR(-EINVAL); | ||
271 | |||
272 | pos = (device_addr - mem->device_base) >> PAGE_SHIFT; | ||
273 | err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); | ||
274 | if (err != 0) | ||
275 | return ERR_PTR(err); | ||
276 | return mem->virt_base + (pos << PAGE_SHIFT); | ||
277 | } | ||
278 | EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | ||
279 | |||
280 | static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size, | ||
281 | dma_addr_t *dma_handle, void **ret) | ||
282 | { | ||
283 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | ||
284 | int order = get_order(size); | ||
285 | |||
286 | if (mem) { | ||
287 | int page = bitmap_find_free_region(mem->bitmap, mem->size, | ||
288 | order); | ||
289 | if (page >= 0) { | ||
290 | *dma_handle = mem->device_base + (page << PAGE_SHIFT); | ||
291 | *ret = mem->virt_base + (page << PAGE_SHIFT); | ||
292 | memset(*ret, 0, size); | ||
293 | } | ||
294 | if (mem->flags & DMA_MEMORY_EXCLUSIVE) | ||
295 | *ret = NULL; | ||
296 | } | ||
297 | return (mem != NULL); | ||
298 | } | ||
299 | |||
300 | static int dma_release_coherent(struct device *dev, int order, void *vaddr) | ||
301 | { | ||
302 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | ||
303 | |||
304 | if (mem && vaddr >= mem->virt_base && vaddr < | ||
305 | (mem->virt_base + (mem->size << PAGE_SHIFT))) { | ||
306 | int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; | ||
307 | |||
308 | bitmap_release_region(mem->bitmap, page, order); | ||
309 | return 1; | ||
310 | } | ||
311 | return 0; | ||
312 | } | ||
313 | #else | ||
314 | #define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0) | ||
315 | #define dma_release_coherent(dev, order, vaddr) (0) | ||
316 | #endif /* CONFIG_X86_32 */ | ||
317 | |||
318 | int dma_supported(struct device *dev, u64 mask) | 200 | int dma_supported(struct device *dev, u64 mask) |
319 | { | 201 | { |
320 | #ifdef CONFIG_PCI | 202 | #ifdef CONFIG_PCI |
@@ -383,7 +265,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | |||
383 | /* ignore region specifiers */ | 265 | /* ignore region specifiers */ |
384 | gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); | 266 | gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); |
385 | 267 | ||
386 | if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) | 268 | if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) |
387 | return memory; | 269 | return memory; |
388 | 270 | ||
389 | if (!dev) { | 271 | if (!dev) { |
@@ -486,7 +368,7 @@ void dma_free_coherent(struct device *dev, size_t size, | |||
486 | { | 368 | { |
487 | int order = get_order(size); | 369 | int order = get_order(size); |
488 | WARN_ON(irqs_disabled()); /* for portability */ | 370 | WARN_ON(irqs_disabled()); /* for portability */ |
489 | if (dma_release_coherent(dev, order, vaddr)) | 371 | if (dma_release_from_coherent(dev, order, vaddr)) |
490 | return; | 372 | return; |
491 | if (dma_ops->unmap_single) | 373 | if (dma_ops->unmap_single) |
492 | dma_ops->unmap_single(dev, bus, size, 0); | 374 | dma_ops->unmap_single(dev, bus, size, 0); |
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index a1a4dc7fe6ec..c68f360ef564 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h | |||
@@ -213,25 +213,5 @@ static inline int dma_get_cache_alignment(void) | |||
213 | 213 | ||
214 | #define dma_is_consistent(d, h) (1) | 214 | #define dma_is_consistent(d, h) (1) |
215 | 215 | ||
216 | #ifdef CONFIG_X86_32 | 216 | #include <asm-generic/dma-coherent.h> |
217 | # define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY | ||
218 | struct dma_coherent_mem { | ||
219 | void *virt_base; | ||
220 | u32 device_base; | ||
221 | int size; | ||
222 | int flags; | ||
223 | unsigned long *bitmap; | ||
224 | }; | ||
225 | |||
226 | extern int | ||
227 | dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, | ||
228 | dma_addr_t device_addr, size_t size, int flags); | ||
229 | |||
230 | extern void | ||
231 | dma_release_declared_memory(struct device *dev); | ||
232 | |||
233 | extern void * | ||
234 | dma_mark_declared_memory_occupied(struct device *dev, | ||
235 | dma_addr_t device_addr, size_t size); | ||
236 | #endif /* CONFIG_X86_32 */ | ||
237 | #endif | 217 | #endif |