diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-06-16 11:27:18 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-16 11:27:18 +0200 |
commit | 33ee375b2ea5dd11581a57d67bedd0ca39b19a5e (patch) | |
tree | 411d3a04936e281e54680ad082f98d985561bce5 /arch/x86/kernel/pci-dma.c | |
parent | 6703f6d10dcd3316e03641a5ecaa6c8a04374d98 (diff) | |
parent | 066519068ad2fbe98c7f45552b1f592903a9c8c8 (diff) | |
download | op-kernel-dev-33ee375b2ea5dd11581a57d67bedd0ca39b19a5e.zip op-kernel-dev-33ee375b2ea5dd11581a57d67bedd0ca39b19a5e.tar.gz |
Merge branch 'linus' into x86/gart
Diffstat (limited to 'arch/x86/kernel/pci-dma.c')
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 7747bc8..09c4dac 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -379,6 +379,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, struct page *page; unsigned long dma_mask = 0; dma_addr_t bus; + int noretry = 0; /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); @@ -398,20 +399,25 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, if (dev->dma_mask == NULL) return NULL; - /* Don't invoke OOM killer */ - gfp |= __GFP_NORETRY; + /* Don't invoke OOM killer or retry in lower 16MB DMA zone */ + if (gfp & __GFP_DMA) + noretry = 1; #ifdef CONFIG_X86_64 /* Why <=? Even when the mask is smaller than 4GB it is often larger than 16MB and in this case we have a chance of finding fitting memory in the next higher zone first. If not retry with true GFP_DMA. -AK */ - if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) + if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) { gfp |= GFP_DMA32; + if (dma_mask < DMA_32BIT_MASK) + noretry = 1; + } #endif again: - page = dma_alloc_pages(dev, gfp, get_order(size)); + page = dma_alloc_pages(dev, + noretry ? gfp | __GFP_NORETRY : gfp, get_order(size)); if (page == NULL) return NULL; |