|
@@ -21,6 +21,7 @@
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/dma-mapping.h>
|
|
|
+#include <linux/dma-contiguous.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
#include <linux/swiotlb.h>
|
|
|
|
|
@@ -41,7 +42,19 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
|
|
|
if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
|
|
|
dev->coherent_dma_mask <= DMA_BIT_MASK(32))
|
|
|
flags |= GFP_DMA32;
|
|
|
- return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
|
|
|
+ if (IS_ENABLED(CONFIG_DMA_CMA)) {
|
|
|
+ struct page *page;
|
|
|
+
|
|
|
+ page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
|
|
|
+ get_order(size));
|
|
|
+ if (!page)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ *dma_handle = phys_to_dma(dev, page_to_phys(page));
|
|
|
+ return page_address(page);
|
|
|
+ } else {
|
|
|
+ return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
|
|
@@ -53,7 +66,15 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- swiotlb_free_coherent(dev, size, vaddr, dma_handle);
|
|
|
+ if (IS_ENABLED(CONFIG_DMA_CMA)) {
|
|
|
+ phys_addr_t paddr = dma_to_phys(dev, dma_handle);
|
|
|
+
|
|
|
+ dma_release_from_contiguous(dev,
|
|
|
+ phys_to_page(paddr),
|
|
|
+ size >> PAGE_SHIFT);
|
|
|
+ } else {
|
|
|
+ swiotlb_free_coherent(dev, size, vaddr, dma_handle);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static struct dma_map_ops arm64_swiotlb_dma_ops = {
|