aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaura Abbott <labbott@redhat.com>2017-04-18 14:27:05 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-18 14:41:12 -0400
commit204f672255c228ef7a66c29ae48123778da938a1 (patch)
tree038f782b7abb1290f34fad60659e9dede9d681ad
parente4231bcda72daef497af45e195a33daa0f9357d0 (diff)
staging: android: ion: Use CMA APIs directly
When CMA was first introduced, its primary use was for DMA allocation and the only way to get CMA memory was to call dma_alloc_coherent. This put Ion in an awkward position since there was no device structure readily available and setting one up messed up the coherency model. These days, CMA can be allocated directly from the APIs. Switch to using this model to avoid needing a dummy device. This also mitigates some of the caching problems (e.g. dma_alloc_coherent only returning uncached memory). Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/android/ion/Kconfig7
-rw-r--r--drivers/staging/android/ion/Makefile3
-rw-r--r--drivers/staging/android/ion/ion_cma_heap.c97
-rw-r--r--drivers/staging/android/ion/ion_heap.c4
4 files changed, 39 insertions, 72 deletions
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 206c4de8feac..15108c40c81f 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -10,3 +10,10 @@ menuconfig ION
10 If you're not using Android its probably safe to 10 If you're not using Android its probably safe to
11 say N here. 11 say N here.
12 12
13config ION_CMA_HEAP
14 bool "Ion CMA heap support"
15 depends on ION && CMA
16 help
17 Choose this option to enable CMA heaps with Ion. This heap is backed
18 by the Contiguous Memory Allocator (CMA). If your system has these
19 regions, you should say Y here.
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 26672a061b34..66d0c4a31ed7 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ 1obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \
2 ion_page_pool.o ion_system_heap.o \ 2 ion_page_pool.o ion_system_heap.o \
3 ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o 3 ion_carveout_heap.o ion_chunk_heap.o
4obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
4ifdef CONFIG_COMPAT 5ifdef CONFIG_COMPAT
5obj-$(CONFIG_ION) += compat_ion.o 6obj-$(CONFIG_ION) += compat_ion.o
6endif 7endif
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index d562fd75c131..f3e0f599b25b 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -19,24 +19,19 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/dma-mapping.h> 22#include <linux/cma.h>
23#include <linux/scatterlist.h>
23 24
24#include "ion.h" 25#include "ion.h"
25#include "ion_priv.h" 26#include "ion_priv.h"
26 27
27struct ion_cma_heap { 28struct ion_cma_heap {
28 struct ion_heap heap; 29 struct ion_heap heap;
29 struct device *dev; 30 struct cma *cma;
30}; 31};
31 32
32#define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap) 33#define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap)
33 34
34struct ion_cma_buffer_info {
35 void *cpu_addr;
36 dma_addr_t handle;
37 struct sg_table *table;
38};
39
40 35
41/* ION CMA heap operations functions */ 36/* ION CMA heap operations functions */
42static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, 37static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
@@ -44,93 +39,53 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
44 unsigned long flags) 39 unsigned long flags)
45{ 40{
46 struct ion_cma_heap *cma_heap = to_cma_heap(heap); 41 struct ion_cma_heap *cma_heap = to_cma_heap(heap);
47 struct device *dev = cma_heap->dev; 42 struct sg_table *table;
48 struct ion_cma_buffer_info *info; 43 struct page *pages;
49 44 int ret;
50 dev_dbg(dev, "Request buffer allocation len %ld\n", len);
51
52 if (buffer->flags & ION_FLAG_CACHED)
53 return -EINVAL;
54 45
55 info = kzalloc(sizeof(*info), GFP_KERNEL); 46 pages = cma_alloc(cma_heap->cma, len, 0, GFP_KERNEL);
56 if (!info) 47 if (!pages)
57 return -ENOMEM; 48 return -ENOMEM;
58 49
59 info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), 50 table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
60 GFP_HIGHUSER | __GFP_ZERO); 51 if (!table)
61
62 if (!info->cpu_addr) {
63 dev_err(dev, "Fail to allocate buffer\n");
64 goto err; 52 goto err;
65 }
66 53
67 info->table = kmalloc(sizeof(*info->table), GFP_KERNEL); 54 ret = sg_alloc_table(table, 1, GFP_KERNEL);
68 if (!info->table) 55 if (ret)
69 goto free_mem; 56 goto free_mem;
70 57
71 if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle, 58 sg_set_page(table->sgl, pages, len, 0);
72 len)) 59
73 goto free_table; 60 buffer->priv_virt = pages;
74 /* keep this for memory release */ 61 buffer->sg_table = table;
75 buffer->priv_virt = info;
76 buffer->sg_table = info->table;
77 dev_dbg(dev, "Allocate buffer %p\n", buffer);
78 return 0; 62 return 0;
79 63
80free_table:
81 kfree(info->table);
82free_mem: 64free_mem:
83 dma_free_coherent(dev, len, info->cpu_addr, info->handle); 65 kfree(table);
84err: 66err:
85 kfree(info); 67 cma_release(cma_heap->cma, pages, buffer->size);
86 return -ENOMEM; 68 return -ENOMEM;
87} 69}
88 70
89static void ion_cma_free(struct ion_buffer *buffer) 71static void ion_cma_free(struct ion_buffer *buffer)
90{ 72{
91 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); 73 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
92 struct device *dev = cma_heap->dev; 74 struct page *pages = buffer->priv_virt;
93 struct ion_cma_buffer_info *info = buffer->priv_virt;
94 75
95 dev_dbg(dev, "Release buffer %p\n", buffer);
96 /* release memory */ 76 /* release memory */
97 dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); 77 cma_release(cma_heap->cma, pages, buffer->size);
98 /* release sg table */ 78 /* release sg table */
99 sg_free_table(info->table); 79 sg_free_table(buffer->sg_table);
100 kfree(info->table); 80 kfree(buffer->sg_table);
101 kfree(info);
102}
103
104static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
105 struct vm_area_struct *vma)
106{
107 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
108 struct device *dev = cma_heap->dev;
109 struct ion_cma_buffer_info *info = buffer->priv_virt;
110
111 return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle,
112 buffer->size);
113}
114
115static void *ion_cma_map_kernel(struct ion_heap *heap,
116 struct ion_buffer *buffer)
117{
118 struct ion_cma_buffer_info *info = buffer->priv_virt;
119 /* kernel memory mapping has been done at allocation time */
120 return info->cpu_addr;
121}
122
123static void ion_cma_unmap_kernel(struct ion_heap *heap,
124 struct ion_buffer *buffer)
125{
126} 81}
127 82
128static struct ion_heap_ops ion_cma_ops = { 83static struct ion_heap_ops ion_cma_ops = {
129 .allocate = ion_cma_allocate, 84 .allocate = ion_cma_allocate,
130 .free = ion_cma_free, 85 .free = ion_cma_free,
131 .map_user = ion_cma_mmap, 86 .map_user = ion_heap_map_user,
132 .map_kernel = ion_cma_map_kernel, 87 .map_kernel = ion_heap_map_kernel,
133 .unmap_kernel = ion_cma_unmap_kernel, 88 .unmap_kernel = ion_heap_unmap_kernel,
134}; 89};
135 90
136struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) 91struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
@@ -147,7 +102,7 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
147 * get device from private heaps data, later it will be 102 * get device from private heaps data, later it will be
148 * used to make the link with reserved CMA memory 103 * used to make the link with reserved CMA memory
149 */ 104 */
150 cma_heap->dev = data->priv; 105 cma_heap->cma = data->priv;
151 cma_heap->heap.type = ION_HEAP_TYPE_DMA; 106 cma_heap->heap.type = ION_HEAP_TYPE_DMA;
152 return &cma_heap->heap; 107 return &cma_heap->heap;
153} 108}
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index c69d0bd53693..66f8fc5c8cee 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -333,9 +333,11 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
333 case ION_HEAP_TYPE_CHUNK: 333 case ION_HEAP_TYPE_CHUNK:
334 heap = ion_chunk_heap_create(heap_data); 334 heap = ion_chunk_heap_create(heap_data);
335 break; 335 break;
336#ifdef CONFIG_ION_CMA_HEAP
336 case ION_HEAP_TYPE_DMA: 337 case ION_HEAP_TYPE_DMA:
337 heap = ion_cma_heap_create(heap_data); 338 heap = ion_cma_heap_create(heap_data);
338 break; 339 break;
340#endif
339 default: 341 default:
340 pr_err("%s: Invalid heap type %d\n", __func__, 342 pr_err("%s: Invalid heap type %d\n", __func__,
341 heap_data->type); 343 heap_data->type);
@@ -373,9 +375,11 @@ void ion_heap_destroy(struct ion_heap *heap)
373 case ION_HEAP_TYPE_CHUNK: 375 case ION_HEAP_TYPE_CHUNK:
374 ion_chunk_heap_destroy(heap); 376 ion_chunk_heap_destroy(heap);
375 break; 377 break;
378#ifdef CONFIG_ION_CMA_HEAP
376 case ION_HEAP_TYPE_DMA: 379 case ION_HEAP_TYPE_DMA:
377 ion_cma_heap_destroy(heap); 380 ion_cma_heap_destroy(heap);
378 break; 381 break;
382#endif
379 default: 383 default:
380 pr_err("%s: Invalid heap type %d\n", __func__, 384 pr_err("%s: Invalid heap type %d\n", __func__,
381 heap->type); 385 heap->type);