Merge branch 'for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping
[firefly-linux-kernel-4.4.55.git] / arch / powerpc / kernel / dma.c
index 4f0959fbfbee02d4538427b7be1ab2a988adeb9d..b1ec983dcec8954ada2bf1cd9937c9d52706b333 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/dma-debug.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/export.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 #include <asm/machdep.h>
@@ -25,7 +26,8 @@
 
 
 void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-                               dma_addr_t *dma_handle, gfp_t flag)
+                               dma_addr_t *dma_handle, gfp_t flag,
+                               struct dma_attrs *attrs)
 {
        void *ret;
 #ifdef CONFIG_NOT_COHERENT_CACHE
@@ -53,7 +55,8 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 }
 
 void dma_direct_free_coherent(struct device *dev, size_t size,
-                             void *vaddr, dma_addr_t dma_handle)
+                             void *vaddr, dma_addr_t dma_handle,
+                             struct dma_attrs *attrs)
 {
 #ifdef CONFIG_NOT_COHERENT_CACHE
        __dma_free_coherent(size, vaddr);
@@ -96,6 +99,18 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+       u64 end, mask;
+
+       end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
                                             struct page *page,
                                             unsigned long offset,
@@ -137,13 +152,14 @@ static inline void dma_direct_sync_single(struct device *dev,
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent  = dma_direct_free_coherent,
-       .map_sg         = dma_direct_map_sg,
-       .unmap_sg       = dma_direct_unmap_sg,
-       .dma_supported  = dma_direct_dma_supported,
-       .map_page       = dma_direct_map_page,
-       .unmap_page     = dma_direct_unmap_page,
+       .alloc                          = dma_direct_alloc_coherent,
+       .free                           = dma_direct_free_coherent,
+       .map_sg                         = dma_direct_map_sg,
+       .unmap_sg                       = dma_direct_unmap_sg,
+       .dma_supported                  = dma_direct_dma_supported,
+       .map_page                       = dma_direct_map_page,
+       .unmap_page                     = dma_direct_unmap_page,
+       .get_required_mask              = dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
        .sync_single_for_cpu            = dma_direct_sync_single,
        .sync_single_for_device         = dma_direct_sync_single,
@@ -170,6 +186,23 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (ppc_md.dma_get_required_mask)
+               return ppc_md.dma_get_required_mask(dev);
+
+       if (unlikely(dma_ops == NULL))
+               return 0;
+
+       if (dma_ops->get_required_mask)
+               return dma_ops->get_required_mask(dev);
+
+       return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);