aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/dma-coherent.c
diff options
context:
space:
mode:
authorAndrew Morton <akpm@linux-foundation.org>2009-01-06 17:43:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 18:59:30 -0500
commit0bef3c2dc7d0c8238330785c8f4504761b0e370b (patch)
treef43e7c7e49f5e67823e7e077c821e8f8d2571e48 /kernel/dma-coherent.c
parent8375d4909aee4c18798f373ecf24a79f040f75fc (diff)
dma_alloc_from_coherent(): fix fallback to generic memory
If bitmap_find_free_region() fails and DMA_MEMORY_EXCLUSIVE is not set, the function will fail to write anything to *ret and will return 1. This will cause dma_alloc_coherent() to return an uninitialised value, crashing the kernel, perhaps via DMA to a random address. Fix that by changing it to return zero in this case, so the caller will proceed to allocate the memory from the generic memory allocator. Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> Cc: Dmitry Baryshkov <dbaryshkov@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/dma-coherent.c')
-rw-r--r--kernel/dma-coherent.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c
index f013a0c2e111..4bdcea822b45 100644
--- a/kernel/dma-coherent.c
+++ b/kernel/dma-coherent.c
@@ -116,11 +116,25 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
116 int page = bitmap_find_free_region(mem->bitmap, mem->size, 116 int page = bitmap_find_free_region(mem->bitmap, mem->size,
117 order); 117 order);
118 if (page >= 0) { 118 if (page >= 0) {
119 /*
120 * Memory was found in the per-device arena.
121 */
119 *dma_handle = mem->device_base + (page << PAGE_SHIFT); 122 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
120 *ret = mem->virt_base + (page << PAGE_SHIFT); 123 *ret = mem->virt_base + (page << PAGE_SHIFT);
121 memset(*ret, 0, size); 124 memset(*ret, 0, size);
122 } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) 125 } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) {
126 /*
127 * The per-device arena is exhausted and we are not
128 * permitted to fall back to generic memory.
129 */
123 *ret = NULL; 130 *ret = NULL;
131 } else {
132 /*
133 * The per-device arena is exhausted and we are
134 * permitted to fall back to generic memory.
135 */
136 return 0;
137 }
124 } 138 }
125 return (mem != NULL); 139 return (mem != NULL);
126} 140}