Merge tag 'xtensa-20210902' of git://github.com/jcmvbkbc/linux-xtensa
[linux-2.6-microblaze.git] / kernel / dma / coherent.c
index 794e76b..25fc85a 100644 (file)
@@ -20,8 +20,6 @@ struct dma_coherent_mem {
        bool            use_dev_dma_pfn_offset;
 };
 
-static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
-
 static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *dev)
 {
        if (dev && dev->dma_mem)
@@ -37,51 +35,44 @@ static inline dma_addr_t dma_get_device_base(struct device *dev,
        return mem->device_base;
 }
 
-static int dma_init_coherent_memory(phys_addr_t phys_addr,
-               dma_addr_t device_addr, size_t size,
-               struct dma_coherent_mem **mem)
+static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr,
+               dma_addr_t device_addr, size_t size, bool use_dma_pfn_offset)
 {
-       struct dma_coherent_mem *dma_mem = NULL;
-       void *mem_base = NULL;
+       struct dma_coherent_mem *dma_mem;
        int pages = size >> PAGE_SHIFT;
        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-       int ret;
+       void *mem_base;
 
-       if (!size) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!size)
+               return ERR_PTR(-EINVAL);
 
        mem_base = memremap(phys_addr, size, MEMREMAP_WC);
-       if (!mem_base) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!mem_base)
+               return ERR_PTR(-EINVAL);
+
        dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-       if (!dma_mem) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!dma_mem)
+               goto out_unmap_membase;
        dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-       if (!dma_mem->bitmap) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!dma_mem->bitmap)
+               goto out_free_dma_mem;
 
        dma_mem->virt_base = mem_base;
        dma_mem->device_base = device_addr;
        dma_mem->pfn_base = PFN_DOWN(phys_addr);
        dma_mem->size = pages;
+       dma_mem->use_dev_dma_pfn_offset = use_dma_pfn_offset;
        spin_lock_init(&dma_mem->spinlock);
 
-       *mem = dma_mem;
-       return 0;
+       return dma_mem;
 
-out:
+out_free_dma_mem:
        kfree(dma_mem);
-       if (mem_base)
-               memunmap(mem_base);
-       return ret;
+out_unmap_membase:
+       memunmap(mem_base);
+       pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %zd MiB\n",
+               &phys_addr, size / SZ_1M);
+       return ERR_PTR(-ENOMEM);
 }
 
 static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
@@ -130,9 +121,9 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
        struct dma_coherent_mem *mem;
        int ret;
 
-       ret = dma_init_coherent_memory(phys_addr, device_addr, size, &mem);
-       if (ret)
-               return ret;
+       mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
 
        ret = dma_assign_coherent_memory(dev, mem);
        if (ret)
@@ -198,16 +189,6 @@ int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
        return 1;
 }
 
-void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
-                                    dma_addr_t *dma_handle)
-{
-       if (!dma_coherent_default_memory)
-               return NULL;
-
-       return __dma_alloc_from_coherent(dev, dma_coherent_default_memory, size,
-                                        dma_handle);
-}
-
 static int __dma_release_from_coherent(struct dma_coherent_mem *mem,
                                       int order, void *vaddr)
 {
@@ -243,15 +224,6 @@ int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr)
        return __dma_release_from_coherent(mem, order, vaddr);
 }
 
-int dma_release_from_global_coherent(int order, void *vaddr)
-{
-       if (!dma_coherent_default_memory)
-               return 0;
-
-       return __dma_release_from_coherent(dma_coherent_default_memory, order,
-                       vaddr);
-}
-
 static int __dma_mmap_from_coherent(struct dma_coherent_mem *mem,
                struct vm_area_struct *vma, void *vaddr, size_t size, int *ret)
 {
@@ -297,6 +269,28 @@ int dma_mmap_from_dev_coherent(struct device *dev, struct vm_area_struct *vma,
        return __dma_mmap_from_coherent(mem, vma, vaddr, size, ret);
 }
 
+#ifdef CONFIG_DMA_GLOBAL_POOL
+static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
+
+void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
+                                    dma_addr_t *dma_handle)
+{
+       if (!dma_coherent_default_memory)
+               return NULL;
+
+       return __dma_alloc_from_coherent(dev, dma_coherent_default_memory, size,
+                                        dma_handle);
+}
+
+int dma_release_from_global_coherent(int order, void *vaddr)
+{
+       if (!dma_coherent_default_memory)
+               return 0;
+
+       return __dma_release_from_coherent(dma_coherent_default_memory, order,
+                       vaddr);
+}
+
 int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
                                   size_t size, int *ret)
 {
@@ -307,6 +301,19 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
                                        vaddr, size, ret);
 }
 
+int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
+{
+       struct dma_coherent_mem *mem;
+
+       mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
+       dma_coherent_default_memory = mem;
+       pr_info("DMA: default coherent area is set\n");
+       return 0;
+}
+#endif /* CONFIG_DMA_GLOBAL_POOL */
+
 /*
  * Support for reserved memory regions defined in device tree
  */
@@ -315,25 +322,22 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
 #include <linux/of_fdt.h>
 #include <linux/of_reserved_mem.h>
 
+#ifdef CONFIG_DMA_GLOBAL_POOL
 static struct reserved_mem *dma_reserved_default_memory __initdata;
+#endif
 
 static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 {
-       struct dma_coherent_mem *mem = rmem->priv;
-       int ret;
-
-       if (!mem) {
-               ret = dma_init_coherent_memory(rmem->base, rmem->base,
-                                              rmem->size, &mem);
-               if (ret) {
-                       pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
-                               &rmem->base, (unsigned long)rmem->size / SZ_1M);
-                       return ret;
-               }
+       if (!rmem->priv) {
+               struct dma_coherent_mem *mem;
+
+               mem = dma_init_coherent_memory(rmem->base, rmem->base,
+                                              rmem->size, true);
+               if (IS_ERR(mem))
+                       return PTR_ERR(mem);
+               rmem->priv = mem;
        }
-       mem->use_dev_dma_pfn_offset = true;
-       rmem->priv = mem;
-       dma_assign_coherent_memory(dev, mem);
+       dma_assign_coherent_memory(dev, rmem->priv);
        return 0;
 }
 
@@ -361,7 +365,9 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
                pr_err("Reserved memory: regions without no-map are not yet supported\n");
                return -EINVAL;
        }
+#endif
 
+#ifdef CONFIG_DMA_GLOBAL_POOL
        if (of_get_flat_dt_prop(node, "linux,dma-default", NULL)) {
                WARN(dma_reserved_default_memory,
                     "Reserved memory: region for default DMA coherent area is redefined\n");
@@ -375,31 +381,16 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
        return 0;
 }
 
+#ifdef CONFIG_DMA_GLOBAL_POOL
 static int __init dma_init_reserved_memory(void)
 {
-       const struct reserved_mem_ops *ops;
-       int ret;
-
        if (!dma_reserved_default_memory)
                return -ENOMEM;
-
-       ops = dma_reserved_default_memory->ops;
-
-       /*
-        * We rely on rmem_dma_device_init() does not propagate error of
-        * dma_assign_coherent_memory() for "NULL" device.
-        */
-       ret = ops->device_init(dma_reserved_default_memory, NULL);
-
-       if (!ret) {
-               dma_coherent_default_memory = dma_reserved_default_memory->priv;
-               pr_info("DMA: default coherent area is set\n");
-       }
-
-       return ret;
+       return dma_init_global_coherent(dma_reserved_default_memory->base,
+                                       dma_reserved_default_memory->size);
 }
-
 core_initcall(dma_init_reserved_memory);
+#endif /* CONFIG_DMA_GLOBAL_POOL */
 
 RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
 #endif