rk: ion: Add support cma heap placed in highmem zone
authorCMY <cmy@rock-chips.com>
Thu, 26 Jun 2014 03:21:41 +0000 (11:21 +0800)
committerCMY <cmy@rock-chips.com>
Thu, 26 Jun 2014 06:42:20 +0000 (14:42 +0800)
Add CONFIG_ION_CMA_HIGHMEM to support cma that placed in highmem zone.

Use dma_alloc_attrs() with DMA_ATTR_NO_KERNEL_MAPPING to alloc memory from
cma heap that placed in highmem zone, and use dma_free_attrs() with
DMA_ATTR_NO_KERNEL_MAPPING to free the memory.

Use ion_heap_map_kernel/ion_heap_unmap_kernel for map/unmap to the kernel
when support cma in highmem.

drivers/staging/android/ion/Kconfig
drivers/staging/android/ion/ion_cma_heap.c

index 7af1035cf650fb53058da3862895f9054896e3e8..521aa75270d0d32a3b5df84294fd023ba818fd68 100644 (file)
@@ -34,26 +34,33 @@ config ION_TEGRA
          Choose this option if you wish to use ion on an nVidia Tegra.
 
 config ION_ROCKCHIP
-    tristate "Ion for Rockchip"
-    depends on ARCH_ROCKCHIP && ION
-    select ARM_HAS_SG_CHAIN
-    help
-      Choose this option if you wish to use ion on an Rockchip.
+       tristate "Ion for Rockchip"
+       depends on ARCH_ROCKCHIP && ION
+       select ARM_HAS_SG_CHAIN
+       help
+         Choose this option if you wish to use ion on an Rockchip.
 
 if ION_ROCKCHIP
 
+config ION_CMA_HIGHMEM
+       bool "CMA Support HighMem Zone"
+       depends on ION_ROCKCHIP && CMA
+       help
+         Choose this option to support CMA regions placed in highmem zone.
+         This will allocate memory from CMA regions without mapping.
+
 config ION_ROCKCHIP_SNAPSHOT
-    bool "Snapshot for rockchip ion"
-    depends on ION_ROCKCHIP
-    help
+       bool "Snapshot for rockchip ion"
+       depends on ION_ROCKCHIP
+       help
          Provide ion snapshot for debug
 
 config ION_SNAPSHOT_BUF_SHIFT
-   int "ION snapshot buffer size (18 => 256KB, 19 => 512KB)"
-   depends on ION_ROCKCHIP_SNAPSHOT
-   range 12 21
-   default 18
-   help
-     Select ION snapshot buffer size as a power of 2
+       int "ION snapshot buffer size (18 => 256KB, 19 => 512KB)"
+       depends on ION_ROCKCHIP_SNAPSHOT
+       range 12 21
+       default 18
+       help
+         Select ION snapshot buffer size as a power of 2
 
 endif
index e93afd0e7270534b31b42bafdd3a2b7fe8ecb09c..f6b8789312ed812dd0544c48f0b0216d54f232db 100755 (executable)
@@ -47,9 +47,9 @@ struct ion_cma_buffer_info {
  * as soon as it will avalaible.
  */
 static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt,
-                              void *cpu_addr, dma_addr_t handle, size_t size)
+                              dma_addr_t handle, size_t size)
 {
-       struct page *page = virt_to_page(cpu_addr);
+       struct page *page = phys_to_page(handle);
        int ret;
 
        ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
@@ -68,7 +68,11 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
        struct ion_cma_heap *cma_heap = to_cma_heap(heap);
        struct device *dev = cma_heap->dev;
        struct ion_cma_buffer_info *info;
+       DEFINE_DMA_ATTRS(attrs);
 
+#ifdef CONFIG_ION_CMA_HIGHMEM
+       dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+#endif
        dev_dbg(dev, "Request buffer allocation len %ld\n", len);
 
        if (buffer->flags & ION_FLAG_CACHED)
@@ -83,8 +87,8 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
                return ION_CMA_ALLOCATE_FAILED;
        }
 
-       info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle),
-                                               GFP_HIGHUSER | __GFP_ZERO);
+       info->cpu_addr = dma_alloc_attrs(dev, len, &(info->handle),
+                                               GFP_HIGHUSER | __GFP_ZERO, &attrs);
 
        if (!info->cpu_addr) {
                dev_err(dev, "Fail to allocate(%lx) buffer\n", len);
@@ -97,8 +101,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
                goto free_mem;
        }
 
-       if (ion_cma_get_sgtable
-           (dev, info->table, info->cpu_addr, info->handle, len))
+       if (ion_cma_get_sgtable(dev, info->table, info->handle, len))
                goto free_table;
        /* keep this for memory release */
        buffer->priv_virt = info;
@@ -108,7 +111,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
 free_table:
        kfree(info->table);
 free_mem:
-       dma_free_coherent(dev, len, info->cpu_addr, info->handle);
+       dma_free_attrs(dev, len, info->cpu_addr, info->handle, &attrs);
 err:
        kfree(info);
        return ION_CMA_ALLOCATE_FAILED;
@@ -119,10 +122,14 @@ static void ion_cma_free(struct ion_buffer *buffer)
        struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
        struct device *dev = cma_heap->dev;
        struct ion_cma_buffer_info *info = buffer->priv_virt;
+       DEFINE_DMA_ATTRS(attrs);
 
+#ifdef CONFIG_ION_CMA_HIGHMEM
+       dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+#endif
        dev_dbg(dev, "Release buffer %p\n", buffer);
        /* release memory */
-       dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
+       dma_free_attrs(dev, buffer->size, info->cpu_addr, info->handle, &attrs);
        /* release sg table */
        sg_free_table(info->table);
        kfree(info->table);
@@ -171,6 +178,7 @@ static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
                                 buffer->size);
 }
 
+#ifndef CONFIG_ION_CMA_HIGHMEM
 static void *ion_cma_map_kernel(struct ion_heap *heap,
                                struct ion_buffer *buffer)
 {
@@ -183,6 +191,7 @@ static void ion_cma_unmap_kernel(struct ion_heap *heap,
                                        struct ion_buffer *buffer)
 {
 }
+#endif
 
 #ifdef CONFIG_ROCKCHIP_IOMMU
 // get device's vaddr
@@ -226,8 +235,13 @@ static struct ion_heap_ops ion_cma_ops = {
        .unmap_dma = ion_cma_heap_unmap_dma,
        .phys = ion_cma_phys,
        .map_user = ion_cma_mmap,
+#ifdef CONFIG_ION_CMA_HIGHMEM
+       .map_kernel = ion_heap_map_kernel,
+       .unmap_kernel = ion_heap_unmap_kernel,
+#else
        .map_kernel = ion_cma_map_kernel,
        .unmap_kernel = ion_cma_unmap_kernel,
+#endif
 #ifdef CONFIG_ROCKCHIP_IOMMU
        .map_iommu = ion_cma_map_iommu,
        .unmap_iommu = ion_cma_unmap_iommu,