Commit f6826a07 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86_64: Fallback to swiotlb for dma_alloc_coherent

From: Suresh B Siddha

Coresponding change to IA64 code is in, so this can be merged too.

- fallback to swiotlb for consistent DMA mappings
- fix a memory leak in dma_alloc_coherent
Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6eb10fe9
...@@ -236,11 +236,21 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, ...@@ -236,11 +236,21 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
mmu = 1; mmu = 1;
if (no_iommu || dma_mask < 0xffffffffUL) { if (no_iommu || dma_mask < 0xffffffffUL) {
if (high) { if (high) {
free_pages((unsigned long)memory,
get_order(size));
if (swiotlb) {
return
swiotlb_alloc_coherent(dev, size,
dma_handle,
gfp);
}
if (!(gfp & GFP_DMA)) { if (!(gfp & GFP_DMA)) {
gfp |= GFP_DMA; gfp |= GFP_DMA;
goto again; goto again;
} }
goto free; return NULL;
} }
mmu = 0; mmu = 0;
} }
...@@ -260,9 +270,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, ...@@ -260,9 +270,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
error: error:
if (panic_on_overflow) if (panic_on_overflow)
panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size); panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size);
free:
free_pages((unsigned long)memory, get_order(size)); free_pages((unsigned long)memory, get_order(size));
/* XXX Could use the swiotlb pool here too */
return NULL; return NULL;
} }
...@@ -273,6 +281,11 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, ...@@ -273,6 +281,11 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
void dma_free_coherent(struct device *dev, size_t size, void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t bus) void *vaddr, dma_addr_t bus)
{ {
if (swiotlb) {
swiotlb_free_coherent(dev, size, vaddr, bus);
return;
}
dma_unmap_single(dev, bus, size, 0); dma_unmap_single(dev, bus, size, 0);
free_pages((unsigned long)vaddr, get_order(size)); free_pages((unsigned long)vaddr, get_order(size));
} }
......
...@@ -26,6 +26,10 @@ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, ...@@ -26,6 +26,10 @@ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction); int nents, int direction);
extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr); extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
extern void *swiotlb_alloc_coherent (struct device *hwdev, size_t size,
dma_addr_t *dma_handle, int flags);
extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
#ifdef CONFIG_SWIOTLB #ifdef CONFIG_SWIOTLB
extern int swiotlb; extern int swiotlb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment