arm64: Enable CMA
[cascardo/linux.git] / arch / arm64 / mm / dma-mapping.c
index 83e6431..45b5ab5 100644 (file)
@@ -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 = {