diff options
Diffstat (limited to 'kernel/dma-coherent.c')
| -rw-r--r-- | kernel/dma-coherent.c | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c index 038707404b76..962a3b574f21 100644 --- a/kernel/dma-coherent.c +++ b/kernel/dma-coherent.c | |||
| @@ -98,7 +98,7 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | |||
| 98 | * @size: size of requested memory area | 98 | * @size: size of requested memory area |
| 99 | * @dma_handle: This will be filled with the correct dma handle | 99 | * @dma_handle: This will be filled with the correct dma handle |
| 100 | * @ret: This pointer will be filled with the virtual address | 100 | * @ret: This pointer will be filled with the virtual address |
| 101 | * to allocated area. | 101 | * to allocated area. |
| 102 | * | 102 | * |
| 103 | * This function should be only called from per-arch dma_alloc_coherent() | 103 | * This function should be only called from per-arch dma_alloc_coherent() |
| 104 | * to support allocation from per-device coherent memory pools. | 104 | * to support allocation from per-device coherent memory pools. |
| @@ -118,31 +118,32 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, | |||
| 118 | mem = dev->dma_mem; | 118 | mem = dev->dma_mem; |
| 119 | if (!mem) | 119 | if (!mem) |
| 120 | return 0; | 120 | return 0; |
| 121 | if (unlikely(size > mem->size)) | 121 | |
| 122 | return 0; | 122 | *ret = NULL; |
| 123 | |||
| 124 | if (unlikely(size > (mem->size << PAGE_SHIFT))) | ||
| 125 | goto err; | ||
| 123 | 126 | ||
| 124 | pageno = bitmap_find_free_region(mem->bitmap, mem->size, order); | 127 | pageno = bitmap_find_free_region(mem->bitmap, mem->size, order); |
| 125 | if (pageno >= 0) { | 128 | if (unlikely(pageno < 0)) |
| 126 | /* | 129 | goto err; |
| 127 | * Memory was found in the per-device arena. | 130 | |
| 128 | */ | 131 | /* |
| 129 | *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); | 132 | * Memory was found in the per-device area. |
| 130 | *ret = mem->virt_base + (pageno << PAGE_SHIFT); | 133 | */ |
| 131 | memset(*ret, 0, size); | 134 | *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); |
| 132 | } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) { | 135 | *ret = mem->virt_base + (pageno << PAGE_SHIFT); |
| 133 | /* | 136 | memset(*ret, 0, size); |
| 134 | * The per-device arena is exhausted and we are not | 137 | |
| 135 | * permitted to fall back to generic memory. | ||
| 136 | */ | ||
| 137 | *ret = NULL; | ||
| 138 | } else { | ||
| 139 | /* | ||
| 140 | * The per-device arena is exhausted and we are | ||
| 141 | * permitted to fall back to generic memory. | ||
| 142 | */ | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | return 1; | 138 | return 1; |
| 139 | |||
| 140 | err: | ||
| 141 | /* | ||
| 142 | * In the case where the allocation can not be satisfied from the | ||
| 143 | * per-device area, try to fall back to generic memory if the | ||
| 144 | * constraints allow it. | ||
| 145 | */ | ||
| 146 | return mem->flags & DMA_MEMORY_EXCLUSIVE; | ||
| 146 | } | 147 | } |
| 147 | EXPORT_SYMBOL(dma_alloc_from_coherent); | 148 | EXPORT_SYMBOL(dma_alloc_from_coherent); |
| 148 | 149 | ||
