ARM: dma-mapping: add support for DMA_ATTR_NO_KERNEL_MAPPING attribute
[pandora-kernel.git] / arch / arm / mm / dma-mapping.c
index eaa8906..4fadb7a 100644 (file)
@@ -1090,10 +1090,13 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si
        return 0;
 }
 
-static struct page **__iommu_get_pages(void *cpu_addr)
+static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
 {
        struct vm_struct *area;
 
+       if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+               return cpu_addr;
+
        area = find_vm_area(cpu_addr);
        if (area && (area->flags & VM_ARM_DMA_CONSISTENT))
                return area->pages;
@@ -1118,6 +1121,9 @@ 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))
+               return pages;
+
        addr = __iommu_alloc_remap(pages, size, gfp, prot,
                                   __builtin_return_address(0));
        if (!addr)
@@ -1138,7 +1144,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 {
        unsigned long uaddr = vma->vm_start;
        unsigned long usize = vma->vm_end - vma->vm_start;
-       struct page **pages = __iommu_get_pages(cpu_addr);
+       struct page **pages = __iommu_get_pages(cpu_addr, attrs);
 
        vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
 
@@ -1165,7 +1171,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                          dma_addr_t handle, struct dma_attrs *attrs)
 {
-       struct page **pages = __iommu_get_pages(cpu_addr);
+       struct page **pages = __iommu_get_pages(cpu_addr, attrs);
        size = PAGE_ALIGN(size);
 
        if (!pages) {
@@ -1173,8 +1179,10 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                return;
        }
 
-       unmap_kernel_range((unsigned long)cpu_addr, size);
-       vunmap(cpu_addr);
+       if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
+               unmap_kernel_range((unsigned long)cpu_addr, size);
+               vunmap(cpu_addr);
+       }
 
        __iommu_remove_mapping(dev, handle, size);
        __iommu_free_buffer(dev, pages, size);