diff --git a/[refs] b/[refs] index b87bc707a1b8..6ceb81115b26 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: aa99b16faadcc9a5b6bd9550fda117a8e9e46d26 +refs/heads/master: da60cab4dd922cd933e82bace490f6155a32a90e diff --git a/trunk/arch/x86/kernel/pci-dma_32.c b/trunk/arch/x86/kernel/pci-dma_32.c index 5450bd142cb0..f134de3833a2 100644 --- a/trunk/arch/x86/kernel/pci-dma_32.c +++ b/trunk/arch/x86/kernel/pci-dma_32.c @@ -116,12 +116,42 @@ void *dma_alloc_coherent(struct device *dev, size_t size, gfp = (gfp & ~GFP_DMA32) | GFP_DMA; goto again; } + + /* Let low level make its own zone decisions */ + gfp &= ~(GFP_DMA32|GFP_DMA); + + if (dma_ops->alloc_coherent) + return dma_ops->alloc_coherent(dev, size, + dma_handle, gfp); + return NULL; + } memset(ret, 0, size); - *dma_handle = bus; + if (!mmu) { + *dma_handle = bus; + return ret; + } + } + + if (dma_ops->alloc_coherent) { + free_pages((unsigned long)ret, get_order(size)); + gfp &= ~(GFP_DMA|GFP_DMA32); + return dma_ops->alloc_coherent(dev, size, dma_handle, gfp); + } + + if (dma_ops->map_simple) { + *dma_handle = dma_ops->map_simple(dev, virt_to_phys(ret), + size, + PCI_DMA_BIDIRECTIONAL); + if (*dma_handle != bad_dma_address) + return ret; } - return ret; + if (panic_on_overflow) + panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", + (unsigned long)size); + free_pages((unsigned long)ret, get_order(size)); + return NULL; } EXPORT_SYMBOL(dma_alloc_coherent);