|
@@ -98,7 +98,7 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
|
|
* @size: size of requested memory area
|
|
* @size: size of requested memory area
|
|
* @dma_handle: This will be filled with the correct dma handle
|
|
* @dma_handle: This will be filled with the correct dma handle
|
|
* @ret: This pointer will be filled with the virtual address
|
|
* @ret: This pointer will be filled with the virtual address
|
|
- * to allocated area.
|
|
|
|
|
|
+ * to allocated area.
|
|
*
|
|
*
|
|
* This function should be only called from per-arch dma_alloc_coherent()
|
|
* This function should be only called from per-arch dma_alloc_coherent()
|
|
* to support allocation from per-device coherent memory pools.
|
|
* to support allocation from per-device coherent memory pools.
|
|
@@ -118,31 +118,32 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
|
mem = dev->dma_mem;
|
|
mem = dev->dma_mem;
|
|
if (!mem)
|
|
if (!mem)
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+ *ret = NULL;
|
|
|
|
+
|
|
if (unlikely(size > (mem->size << PAGE_SHIFT)))
|
|
if (unlikely(size > (mem->size << PAGE_SHIFT)))
|
|
- return 0;
|
|
|
|
|
|
+ goto err;
|
|
|
|
|
|
pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
|
|
pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
|
|
- if (pageno >= 0) {
|
|
|
|
- /*
|
|
|
|
- * Memory was found in the per-device arena.
|
|
|
|
- */
|
|
|
|
- *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
|
|
|
|
- *ret = mem->virt_base + (pageno << PAGE_SHIFT);
|
|
|
|
- memset(*ret, 0, size);
|
|
|
|
- } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) {
|
|
|
|
- /*
|
|
|
|
- * The per-device arena is exhausted and we are not
|
|
|
|
- * permitted to fall back to generic memory.
|
|
|
|
- */
|
|
|
|
- *ret = NULL;
|
|
|
|
- } else {
|
|
|
|
- /*
|
|
|
|
- * The per-device arena is exhausted and we are
|
|
|
|
- * permitted to fall back to generic memory.
|
|
|
|
- */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ if (unlikely(pageno < 0))
|
|
|
|
+ goto err;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Memory was found in the per-device area.
|
|
|
|
+ */
|
|
|
|
+ *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
|
|
|
|
+ *ret = mem->virt_base + (pageno << PAGE_SHIFT);
|
|
|
|
+ memset(*ret, 0, size);
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
|
|
+
|
|
|
|
+err:
|
|
|
|
+ /*
|
|
|
|
+ * In the case where the allocation can not be satisfied from the
|
|
|
|
+ * per-device area, try to fall back to generic memory if the
|
|
|
|
+ * constraints allow it.
|
|
|
|
+ */
|
|
|
|
+ return mem->flags & DMA_MEMORY_EXCLUSIVE;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(dma_alloc_from_coherent);
|
|
EXPORT_SYMBOL(dma_alloc_from_coherent);
|
|
|
|
|