Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / arch / arm / mm / dma-mapping.c
index ff7ed5697d3e4b67ba1691dded0f79029ec8f921..c6834c0cfd1cfdb3830d777495aaddbe06d5d301 100644 (file)
@@ -49,6 +49,7 @@ struct arm_dma_alloc_args {
        pgprot_t prot;
        const void *caller;
        bool want_vaddr;
+       int coherent_flag;
 };
 
 struct arm_dma_free_args {
@@ -59,6 +60,9 @@ struct arm_dma_free_args {
        bool want_vaddr;
 };
 
+#define NORMAL     0
+#define COHERENT    1
+
 struct arm_dma_allocator {
        void *(*alloc)(struct arm_dma_alloc_args *args,
                       struct page **ret_page);
@@ -124,16 +128,16 @@ static void __dma_page_dev_to_cpu(struct page *, unsigned long,
  */
 static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
-            struct dma_attrs *attrs)
+            unsigned long attrs)
 {
-       if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+       if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                __dma_page_cpu_to_dev(page, offset, size, dir);
        return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
 
 static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
-            struct dma_attrs *attrs)
+            unsigned long attrs)
 {
        return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
@@ -153,10 +157,9 @@ static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *pag
  * whatever the device wrote there.
  */
 static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir,
-               struct dma_attrs *attrs)
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
-       if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+       if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
                                      handle & ~PAGE_MASK, size, dir);
 }
@@ -194,12 +197,12 @@ struct dma_map_ops arm_dma_ops = {
 EXPORT_SYMBOL(arm_dma_ops);
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-       dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
+       dma_addr_t *handle, gfp_t gfp, unsigned long attrs);
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-                                 dma_addr_t handle, struct dma_attrs *attrs);
+                                 dma_addr_t handle, unsigned long attrs);
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-                struct dma_attrs *attrs);
+                unsigned long attrs);
 
 struct dma_map_ops arm_coherent_dma_ops = {
        .alloc                  = arm_coherent_dma_alloc,
@@ -272,7 +275,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
        return mask;
 }
 
-static void __dma_clear_buffer(struct page *page, size_t size)
+static void __dma_clear_buffer(struct page *page, size_t size, int coherent_flag)
 {
        /*
         * Ensure that the allocated pages are zeroed, and that any data
@@ -284,17 +287,21 @@ static void __dma_clear_buffer(struct page *page, size_t size)
                while (size > 0) {
                        void *ptr = kmap_atomic(page);
                        memset(ptr, 0, PAGE_SIZE);
-                       dmac_flush_range(ptr, ptr + PAGE_SIZE);
+                       if (coherent_flag != COHERENT)
+                               dmac_flush_range(ptr, ptr + PAGE_SIZE);
                        kunmap_atomic(ptr);
                        page++;
                        size -= PAGE_SIZE;
                }
-               outer_flush_range(base, end);
+               if (coherent_flag != COHERENT)
+                       outer_flush_range(base, end);
        } else {
                void *ptr = page_address(page);
                memset(ptr, 0, size);
-               dmac_flush_range(ptr, ptr + size);
-               outer_flush_range(__pa(ptr), __pa(ptr) + size);
+               if (coherent_flag != COHERENT) {
+                       dmac_flush_range(ptr, ptr + size);
+                       outer_flush_range(__pa(ptr), __pa(ptr) + size);
+               }
        }
 }
 
@@ -302,7 +309,8 @@ static void __dma_clear_buffer(struct page *page, size_t size)
  * Allocate a DMA buffer for 'dev' of size 'size' using the
  * specified gfp mask.  Note that 'size' must be page aligned.
  */
-static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
+static struct page *__dma_alloc_buffer(struct device *dev, size_t size,
+                                      gfp_t gfp, int coherent_flag)
 {
        unsigned long order = get_order(size);
        struct page *page, *p, *e;
@@ -318,7 +326,7 @@ static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gf
        for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
                __free_page(p);
 
-       __dma_clear_buffer(page, size);
+       __dma_clear_buffer(page, size, coherent_flag);
 
        return page;
 }
@@ -340,7 +348,8 @@ static void __dma_free_buffer(struct page *page, size_t size)
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
                                     pgprot_t prot, struct page **ret_page,
-                                    const void *caller, bool want_vaddr);
+                                    const void *caller, bool want_vaddr,
+                                    int coherent_flag);
 
 static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
                                 pgprot_t prot, struct page **ret_page,
@@ -405,10 +414,13 @@ static int __init atomic_pool_init(void)
        atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
        if (!atomic_pool)
                goto out;
-
+       /*
+        * The atomic pool is only used for non-coherent allocations
+        * so we must pass NORMAL for coherent_flag.
+        */
        if (dev_get_cma_area(NULL))
                ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot,
-                                             &page, atomic_pool_init, true);
+                                     &page, atomic_pool_init, true, NORMAL);
        else
                ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot,
                                           &page, atomic_pool_init, true);
@@ -522,7 +534,11 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
 {
        struct page *page;
        void *ptr = NULL;
-       page = __dma_alloc_buffer(dev, size, gfp);
+       /*
+        * __alloc_remap_buffer is only called when the device is
+        * non-coherent
+        */
+       page = __dma_alloc_buffer(dev, size, gfp, NORMAL);
        if (!page)
                return NULL;
        if (!want_vaddr)
@@ -577,7 +593,8 @@ static int __free_from_pool(void *start, size_t size)
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
                                     pgprot_t prot, struct page **ret_page,
-                                    const void *caller, bool want_vaddr)
+                                    const void *caller, bool want_vaddr,
+                                    int coherent_flag)
 {
        unsigned long order = get_order(size);
        size_t count = size >> PAGE_SHIFT;
@@ -588,7 +605,7 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size,
        if (!page)
                return NULL;
 
-       __dma_clear_buffer(page, size);
+       __dma_clear_buffer(page, size, coherent_flag);
 
        if (!want_vaddr)
                goto out;
@@ -621,11 +638,11 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
        dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
-static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
 {
-       prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
-                           pgprot_writecombine(prot) :
-                           pgprot_dmacoherent(prot);
+       prot = (attrs & DMA_ATTR_WRITE_COMBINE) ?
+                       pgprot_writecombine(prot) :
+                       pgprot_dmacoherent(prot);
        return prot;
 }
 
@@ -638,7 +655,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
 #define __get_dma_pgprot(attrs, prot)                          __pgprot(0)
 #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv) NULL
 #define __alloc_from_pool(size, ret_page)                      NULL
-#define __alloc_from_contiguous(dev, size, prot, ret, c, wv)   NULL
+#define __alloc_from_contiguous(dev, size, prot, ret, c, wv, coherent_flag)    NULL
 #define __free_from_pool(cpu_addr, size)                       do { } while (0)
 #define __free_from_contiguous(dev, page, cpu_addr, size, wv)  do { } while (0)
 #define __dma_free_remap(cpu_addr, size)                       do { } while (0)
@@ -649,7 +666,8 @@ static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
                                   struct page **ret_page)
 {
        struct page *page;
-       page = __dma_alloc_buffer(dev, size, gfp);
+       /* __alloc_simple_buffer is only called when the device is coherent */
+       page = __dma_alloc_buffer(dev, size, gfp, COHERENT);
        if (!page)
                return NULL;
 
@@ -679,7 +697,7 @@ static void *cma_allocator_alloc(struct arm_dma_alloc_args *args,
 {
        return __alloc_from_contiguous(args->dev, args->size, args->prot,
                                       ret_page, args->caller,
-                                      args->want_vaddr);
+                                      args->want_vaddr, args->coherent_flag);
 }
 
 static void cma_allocator_free(struct arm_dma_free_args *args)
@@ -732,7 +750,7 @@ static struct arm_dma_allocator remap_allocator = {
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent,
-                        struct dma_attrs *attrs, const void *caller)
+                        unsigned long attrs, const void *caller)
 {
        u64 mask = get_coherent_dma_mask(dev);
        struct page *page = NULL;
@@ -745,7 +763,8 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                .gfp = gfp,
                .prot = prot,
                .caller = caller,
-               .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+               .want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0),
+               .coherent_flag = is_coherent ? COHERENT : NORMAL,
        };
 
 #ifdef CONFIG_DMA_API_DEBUG
@@ -814,7 +833,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  * virtual and bus address for that space.
  */
 void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-                   gfp_t gfp, struct dma_attrs *attrs)
+                   gfp_t gfp, unsigned long attrs)
 {
        pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 
@@ -823,7 +842,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 }
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-       dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+       dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
 {
        return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true,
                           attrs, __builtin_return_address(0));
@@ -831,7 +850,7 @@ static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
 
 static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-                struct dma_attrs *attrs)
+                unsigned long attrs)
 {
        int ret = -ENXIO;
 #ifdef CONFIG_MMU
@@ -859,14 +878,14 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  */
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-                struct dma_attrs *attrs)
+                unsigned long attrs)
 {
        return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
 }
 
 int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-                struct dma_attrs *attrs)
+                unsigned long attrs)
 {
 #ifdef CONFIG_MMU
        vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
@@ -878,7 +897,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  * Free a buffer as defined by the above mapping.
  */
 static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-                          dma_addr_t handle, struct dma_attrs *attrs,
+                          dma_addr_t handle, unsigned long attrs,
                           bool is_coherent)
 {
        struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
@@ -888,7 +907,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                .size = PAGE_ALIGN(size),
                .cpu_addr = cpu_addr,
                .page = page,
-               .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+               .want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0),
        };
 
        buf = arm_dma_buffer_find(cpu_addr);
@@ -900,20 +919,20 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 }
 
 void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-                 dma_addr_t handle, struct dma_attrs *attrs)
+                 dma_addr_t handle, unsigned long attrs)
 {
        __arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
 }
 
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-                                 dma_addr_t handle, struct dma_attrs *attrs)
+                                 dma_addr_t handle, unsigned long attrs)
 {
        __arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
 }
 
 int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
                 void *cpu_addr, dma_addr_t handle, size_t size,
-                struct dma_attrs *attrs)
+                unsigned long attrs)
 {
        struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
        int ret;
@@ -1046,7 +1065,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
  * here.
  */
 int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-               enum dma_data_direction dir, struct dma_attrs *attrs)
+               enum dma_data_direction dir, unsigned long attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        struct scatterlist *s;
@@ -1080,7 +1099,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-               enum dma_data_direction dir, struct dma_attrs *attrs)
+               enum dma_data_direction dir, unsigned long attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        struct scatterlist *s;
@@ -1253,7 +1272,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
 static const int iommu_order_array[] = { 9, 8, 4, 0 };
 
 static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
-                                         gfp_t gfp, struct dma_attrs *attrs)
+                                         gfp_t gfp, unsigned long attrs,
+                                         int coherent_flag)
 {
        struct page **pages;
        int count = size >> PAGE_SHIFT;
@@ -1268,7 +1288,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
        if (!pages)
                return NULL;
 
-       if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs))
+       if (attrs & DMA_ATTR_FORCE_CONTIGUOUS)
        {
                unsigned long order = get_order(size);
                struct page *page;
@@ -1277,7 +1297,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                if (!page)
                        goto error;
 
-               __dma_clear_buffer(page, size);
+               __dma_clear_buffer(page, size, coherent_flag);
 
                for (i = 0; i < count; i++)
                        pages[i] = page + i;
@@ -1286,7 +1306,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
        }
 
        /* Go straight to 4K chunks if caller says it's OK. */
-       if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs))
+       if (attrs & DMA_ATTR_ALLOC_SINGLE_PAGES)
                order_idx = ARRAY_SIZE(iommu_order_array) - 1;
 
        /*
@@ -1327,7 +1347,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                                pages[i + j] = pages[i] + j;
                }
 
-               __dma_clear_buffer(pages[i], PAGE_SIZE << order);
+               __dma_clear_buffer(pages[i], PAGE_SIZE << order, coherent_flag);
                i += 1 << order;
                count -= 1 << order;
        }
@@ -1342,12 +1362,12 @@ error:
 }
 
 static int __iommu_free_buffer(struct device *dev, struct page **pages,
-                              size_t size, struct dma_attrs *attrs)
+                              size_t size, unsigned long attrs)
 {
        int count = size >> PAGE_SHIFT;
        int i;
 
-       if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) {
+       if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
                dma_release_from_contiguous(dev, pages[0], count);
        } else {
                for (i = 0; i < count; i++)
@@ -1439,14 +1459,14 @@ static struct page **__atomic_get_pages(void *addr)
        return (struct page **)page;
 }
 
-static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
+static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs)
 {
        struct vm_struct *area;
 
        if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
                return __atomic_get_pages(cpu_addr);
 
-       if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
                return cpu_addr;
 
        area = find_vm_area(cpu_addr);
@@ -1455,13 +1475,16 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
        return NULL;
 }
 
-static void *__iommu_alloc_atomic(struct device *dev, size_t size,
-                                 dma_addr_t *handle)
+static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp,
+                                 dma_addr_t *handle, int coherent_flag)
 {
        struct page *page;
        void *addr;
 
-       addr = __alloc_from_pool(size, &page);
+       if (coherent_flag  == COHERENT)
+               addr = __alloc_simple_buffer(dev, size, gfp, &page);
+       else
+               addr = __alloc_from_pool(size, &page);
        if (!addr)
                return NULL;
 
@@ -1477,14 +1500,18 @@ err_mapping:
 }
 
 static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
-                               dma_addr_t handle, size_t size)
+                       dma_addr_t handle, size_t size, int coherent_flag)
 {
        __iommu_remove_mapping(dev, handle, size);
-       __free_from_pool(cpu_addr, size);
+       if (coherent_flag == COHERENT)
+               __dma_free_buffer(virt_to_page(cpu_addr), size);
+       else
+               __free_from_pool(cpu_addr, size);
 }
 
-static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
-           dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
+           dma_addr_t *handle, gfp_t gfp, unsigned long attrs,
+           int coherent_flag)
 {
        pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
        struct page **pages;
@@ -1493,8 +1520,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
-       if (!gfpflags_allow_blocking(gfp))
-               return __iommu_alloc_atomic(dev, size, handle);
+       if (coherent_flag  == COHERENT || !gfpflags_allow_blocking(gfp))
+               return __iommu_alloc_simple(dev, size, gfp, handle,
+                                           coherent_flag);
 
        /*
         * Following is a work-around (a.k.a. hack) to prevent pages
@@ -1505,7 +1533,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
         */
        gfp &= ~(__GFP_COMP);
 
-       pages = __iommu_alloc_buffer(dev, size, gfp, attrs);
+       pages = __iommu_alloc_buffer(dev, size, gfp, attrs, coherent_flag);
        if (!pages)
                return NULL;
 
@@ -1513,7 +1541,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        if (*handle == DMA_ERROR_CODE)
                goto err_buffer;
 
-       if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
                return pages;
 
        addr = __iommu_alloc_remap(pages, size, gfp, prot,
@@ -1530,9 +1558,21 @@ err_buffer:
        return NULL;
 }
 
-static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
+           dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
+{
+       return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, NORMAL);
+}
+
+static void *arm_coherent_iommu_alloc_attrs(struct device *dev, size_t size,
+                   dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
+{
+       return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, COHERENT);
+}
+
+static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
                    void *cpu_addr, dma_addr_t dma_addr, size_t size,
-                   struct dma_attrs *attrs)
+                   unsigned long attrs)
 {
        unsigned long uaddr = vma->vm_start;
        unsigned long usize = vma->vm_end - vma->vm_start;
@@ -1540,8 +1580,6 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
        unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long off = vma->vm_pgoff;
 
-       vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-
        if (!pages)
                return -ENXIO;
 
@@ -1562,19 +1600,34 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 
        return 0;
 }
+static int arm_iommu_mmap_attrs(struct device *dev,
+               struct vm_area_struct *vma, void *cpu_addr,
+               dma_addr_t dma_addr, size_t size, unsigned long attrs)
+{
+       vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
+
+       return __arm_iommu_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
+}
+
+static int arm_coherent_iommu_mmap_attrs(struct device *dev,
+               struct vm_area_struct *vma, void *cpu_addr,
+               dma_addr_t dma_addr, size_t size, unsigned long attrs)
+{
+       return __arm_iommu_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
+}
 
 /*
  * free a page as defined by the above mapping.
  * Must not be called with IRQs disabled.
  */
-void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-                         dma_addr_t handle, struct dma_attrs *attrs)
+void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
+       dma_addr_t handle, unsigned long attrs, int coherent_flag)
 {
        struct page **pages;
        size = PAGE_ALIGN(size);
 
-       if (__in_atomic_pool(cpu_addr, size)) {
-               __iommu_free_atomic(dev, cpu_addr, handle, size);
+       if (coherent_flag == COHERENT || __in_atomic_pool(cpu_addr, size)) {
+               __iommu_free_atomic(dev, cpu_addr, handle, size, coherent_flag);
                return;
        }
 
@@ -1584,7 +1637,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                return;
        }
 
-       if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
+       if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) {
                dma_common_free_remap(cpu_addr, size,
                        VM_ARM_DMA_CONSISTENT | VM_USERMAP);
        }
@@ -1593,9 +1646,21 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
        __iommu_free_buffer(dev, pages, size, attrs);
 }
 
+void arm_iommu_free_attrs(struct device *dev, size_t size,
+                   void *cpu_addr, dma_addr_t handle, unsigned long attrs)
+{
+       __arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, NORMAL);
+}
+
+void arm_coherent_iommu_free_attrs(struct device *dev, size_t size,
+                   void *cpu_addr, dma_addr_t handle, unsigned long attrs)
+{
+       __arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, COHERENT);
+}
+
 static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
                                 void *cpu_addr, dma_addr_t dma_addr,
-                                size_t size, struct dma_attrs *attrs)
+                                size_t size, unsigned long attrs)
 {
        unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        struct page **pages = __iommu_get_pages(cpu_addr, attrs);
@@ -1633,7 +1698,7 @@ static int __dma_direction_to_prot(enum dma_data_direction dir)
  */
 static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
                          size_t size, dma_addr_t *handle,
-                         enum dma_data_direction dir, struct dma_attrs *attrs,
+                         enum dma_data_direction dir, unsigned long attrs,
                          bool is_coherent)
 {
        struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
@@ -1654,8 +1719,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
                phys_addr_t phys = page_to_phys(sg_page(s));
                unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
-               if (!is_coherent &&
-                       !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+               if (!is_coherent && (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                        __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
                prot = __dma_direction_to_prot(dir);
@@ -1676,7 +1740,7 @@ fail:
 }
 
 static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-                    enum dma_data_direction dir, struct dma_attrs *attrs,
+                    enum dma_data_direction dir, unsigned long attrs,
                     bool is_coherent)
 {
        struct scatterlist *s = sg, *dma = sg, *start = sg;
@@ -1734,7 +1798,7 @@ bad_mapping:
  * obtained via sg_dma_{address,length}.
  */
 int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-               int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+               int nents, enum dma_data_direction dir, unsigned long attrs)
 {
        return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1752,14 +1816,14 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
  * sg_dma_{address,length}.
  */
 int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-               int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+               int nents, enum dma_data_direction dir, unsigned long attrs)
 {
        return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
 }
 
 static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-               int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
-               bool is_coherent)
+               int nents, enum dma_data_direction dir,
+               unsigned long attrs, bool is_coherent)
 {
        struct scatterlist *s;
        int i;
@@ -1768,8 +1832,7 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
                if (sg_dma_len(s))
                        __iommu_remove_mapping(dev, sg_dma_address(s),
                                               sg_dma_len(s));
-               if (!is_coherent &&
-                   !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+               if (!is_coherent && (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                        __dma_page_dev_to_cpu(sg_page(s), s->offset,
                                              s->length, dir);
        }
@@ -1786,7 +1849,8 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-               int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+               int nents, enum dma_data_direction dir,
+               unsigned long attrs)
 {
        __iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1802,7 +1866,8 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-                       enum dma_data_direction dir, struct dma_attrs *attrs)
+                       enum dma_data_direction dir,
+                       unsigned long attrs)
 {
        __iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
 }
@@ -1855,7 +1920,7 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
-            struct dma_attrs *attrs)
+            unsigned long attrs)
 {
        struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
        dma_addr_t dma_addr;
@@ -1889,9 +1954,9 @@ fail:
  */
 static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
-            struct dma_attrs *attrs)
+            unsigned long attrs)
 {
-       if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+       if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                __dma_page_cpu_to_dev(page, offset, size, dir);
 
        return arm_coherent_iommu_map_page(dev, page, offset, size, dir, attrs);
@@ -1907,8 +1972,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
  * Coherent IOMMU aware version of arm_dma_unmap_page()
  */
 static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir,
-               struct dma_attrs *attrs)
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
        struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
        dma_addr_t iova = handle & PAGE_MASK;
@@ -1932,8 +1996,7 @@ static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
  * IOMMU aware version of arm_dma_unmap_page()
  */
 static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir,
-               struct dma_attrs *attrs)
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
        struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
        dma_addr_t iova = handle & PAGE_MASK;
@@ -1944,7 +2007,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
        if (!iova)
                return;
 
-       if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+       if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
                __dma_page_dev_to_cpu(page, offset, size, dir);
 
        iommu_unmap(mapping->domain, iova, len);
@@ -1997,9 +2060,9 @@ struct dma_map_ops iommu_ops = {
 };
 
 struct dma_map_ops iommu_coherent_ops = {
-       .alloc          = arm_iommu_alloc_attrs,
-       .free           = arm_iommu_free_attrs,
-       .mmap           = arm_iommu_mmap_attrs,
+       .alloc          = arm_coherent_iommu_alloc_attrs,
+       .free           = arm_coherent_iommu_free_attrs,
+       .mmap           = arm_coherent_iommu_mmap_attrs,
        .get_sgtable    = arm_iommu_get_sgtable,
 
        .map_page       = arm_coherent_iommu_map_page,
This page took 0.122004 seconds and 5 git commands to generate.