aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRebecca Schultz Zavin2012-11-15 12:52:45 -0600
committerArve Hjønnevåg2013-02-19 19:56:03 -0600
commit234f61055f4889dbff5060c4d954ead9a02c6e90 (patch)
treec3bc31f52fce5d55328ab360a08da2a63c6bec42
parentcc7a12852b165a0c3e61dbe576c8df8c7abd1525 (diff)
downloadkernel-common-234f61055f4889dbff5060c4d954ead9a02c6e90.tar.gz
kernel-common-234f61055f4889dbff5060c4d954ead9a02c6e90.tar.xz
kernel-common-234f61055f4889dbff5060c4d954ead9a02c6e90.zip
gpu: ion: Add chunk heap
This patch adds support for a chunk heap that allows for buffers that are made up of a list of fixed size chunks taken from a carveout. Chunk sizes are configured when the heaps are created by passing the chunk size in the priv field of the heap platform data. Change-Id: Ia9e003f727b553a92804264debe119dcf78b14e0 Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
-rw-r--r--drivers/gpu/ion/Makefile2
-rw-r--r--drivers/gpu/ion/ion_chunk_heap.c174
-rw-r--r--drivers/gpu/ion/ion_heap.c6
-rw-r--r--drivers/gpu/ion/ion_priv.h4
-rw-r--r--include/linux/ion.h5
5 files changed, 189 insertions, 2 deletions
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index d1ddebb74a3..306fff970de 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,3 +1,3 @@
1obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ 1obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
2 ion_carveout_heap.o 2 ion_carveout_heap.o ion_chunk_heap.o
3obj-$(CONFIG_ION_TEGRA) += tegra/ 3obj-$(CONFIG_ION_TEGRA) += tegra/
diff --git a/drivers/gpu/ion/ion_chunk_heap.c b/drivers/gpu/ion/ion_chunk_heap.c
new file mode 100644
index 00000000000..01381827f58
--- /dev/null
+++ b/drivers/gpu/ion/ion_chunk_heap.c
@@ -0,0 +1,174 @@
1/*
2 * drivers/gpu/ion/ion_chunk_heap.c
3 *
4 * Copyright (C) 2012 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16//#include <linux/spinlock.h>
17#include <linux/dma-mapping.h>
18#include <linux/err.h>
19#include <linux/genalloc.h>
20#include <linux/io.h>
21#include <linux/ion.h>
22#include <linux/mm.h>
23#include <linux/scatterlist.h>
24#include <linux/slab.h>
25#include <linux/vmalloc.h>
26#include "ion_priv.h"
27
28#include <asm/mach/map.h>
29
30struct ion_chunk_heap {
31 struct ion_heap heap;
32 struct gen_pool *pool;
33 ion_phys_addr_t base;
34 unsigned long chunk_size;
35 unsigned long size;
36 unsigned long allocated;
37};
38
39static int ion_chunk_heap_allocate(struct ion_heap *heap,
40 struct ion_buffer *buffer,
41 unsigned long size, unsigned long align,
42 unsigned long flags)
43{
44 struct ion_chunk_heap *chunk_heap =
45 container_of(heap, struct ion_chunk_heap, heap);
46 struct sg_table *table;
47 struct scatterlist *sg;
48 int ret, i;
49 unsigned long num_chunks;
50
51 if (ion_buffer_fault_user_mappings(buffer))
52 return -ENOMEM;
53
54 num_chunks = ALIGN(size, chunk_heap->chunk_size) /
55 chunk_heap->chunk_size;
56 buffer->size = num_chunks * chunk_heap->chunk_size;
57
58 if (buffer->size > chunk_heap->size - chunk_heap->allocated)
59 return -ENOMEM;
60
61 table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
62 if (!table)
63 return -ENOMEM;
64 ret = sg_alloc_table(table, num_chunks, GFP_KERNEL);
65 if (ret) {
66 kfree(table);
67 return ret;
68 }
69
70 sg = table->sgl;
71 for (i = 0; i < num_chunks; i++) {
72 unsigned long paddr = gen_pool_alloc(chunk_heap->pool,
73 chunk_heap->chunk_size);
74 if (!paddr)
75 goto err;
76 sg_set_page(sg, phys_to_page(paddr), chunk_heap->chunk_size, 0);
77 sg = sg_next(sg);
78 }
79
80 buffer->priv_virt = table;
81 chunk_heap->allocated += buffer->size;
82 return 0;
83err:
84 sg = table->sgl;
85 for (i -= 1; i >= 0; i--) {
86 gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
87 sg_dma_len(sg));
88 sg = sg_next(sg);
89 }
90 sg_free_table(table);
91 kfree(table);
92 return -ENOMEM;
93}
94
95static void ion_chunk_heap_free(struct ion_buffer *buffer)
96{
97 struct ion_heap *heap = buffer->heap;
98 struct ion_chunk_heap *chunk_heap =
99 container_of(heap, struct ion_chunk_heap, heap);
100 struct sg_table *table = buffer->priv_virt;
101 struct scatterlist *sg;
102 int i;
103
104 for_each_sg(table->sgl, sg, table->nents, i) {
105 __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg),
106 DMA_BIDIRECTIONAL);
107 gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
108 sg_dma_len(sg));
109 }
110 chunk_heap->allocated -= buffer->size;
111 sg_free_table(table);
112 kfree(table);
113}
114
115struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap,
116 struct ion_buffer *buffer)
117{
118 return buffer->priv_virt;
119}
120
121void ion_chunk_heap_unmap_dma(struct ion_heap *heap,
122 struct ion_buffer *buffer)
123{
124 return;
125}
126
127static struct ion_heap_ops chunk_heap_ops = {
128 .allocate = ion_chunk_heap_allocate,
129 .free = ion_chunk_heap_free,
130 .map_dma = ion_chunk_heap_map_dma,
131 .unmap_dma = ion_chunk_heap_unmap_dma,
132 .map_user = ion_heap_map_user,
133 .map_kernel = ion_heap_map_kernel,
134 .unmap_kernel = ion_heap_unmap_kernel,
135};
136
137struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
138{
139 struct ion_chunk_heap *chunk_heap;
140
141 chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL);
142 if (!chunk_heap)
143 return ERR_PTR(-ENOMEM);
144
145 chunk_heap->chunk_size = (unsigned long)heap_data->priv;
146 chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) +
147 PAGE_SHIFT, -1);
148 if (!chunk_heap->pool) {
149 kfree(chunk_heap);
150 return ERR_PTR(-ENOMEM);
151 }
152 chunk_heap->base = heap_data->base;
153 chunk_heap->size = heap_data->size;
154 chunk_heap->allocated = 0;
155 __dma_page_cpu_to_dev(phys_to_page(heap_data->base), 0, heap_data->size,
156 DMA_BIDIRECTIONAL);
157 gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1);
158 chunk_heap->heap.ops = &chunk_heap_ops;
159 chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
160 pr_info("%s: base %lu size %ld align %ld\n", __func__, chunk_heap->base,
161 heap_data->size, heap_data->align);
162
163 return &chunk_heap->heap;
164}
165
166void ion_chunk_heap_destroy(struct ion_heap *heap)
167{
168 struct ion_chunk_heap *chunk_heap =
169 container_of(heap, struct ion_chunk_heap, heap);
170
171 gen_pool_destroy(chunk_heap->pool);
172 kfree(chunk_heap);
173 chunk_heap = NULL;
174}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index b000eb39294..fee9c2a8b15 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -107,6 +107,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
107 case ION_HEAP_TYPE_CARVEOUT: 107 case ION_HEAP_TYPE_CARVEOUT:
108 heap = ion_carveout_heap_create(heap_data); 108 heap = ion_carveout_heap_create(heap_data);
109 break; 109 break;
110 case ION_HEAP_TYPE_CHUNK:
111 heap = ion_chunk_heap_create(heap_data);
112 break;
110 default: 113 default:
111 pr_err("%s: Invalid heap type %d\n", __func__, 114 pr_err("%s: Invalid heap type %d\n", __func__,
112 heap_data->type); 115 heap_data->type);
@@ -140,6 +143,9 @@ void ion_heap_destroy(struct ion_heap *heap)
140 case ION_HEAP_TYPE_CARVEOUT: 143 case ION_HEAP_TYPE_CARVEOUT:
141 ion_carveout_heap_destroy(heap); 144 ion_carveout_heap_destroy(heap);
142 break; 145 break;
146 case ION_HEAP_TYPE_CHUNK:
147 ion_chunk_heap_destroy(heap);
148 break;
143 default: 149 default:
144 pr_err("%s: Invalid heap type %d\n", __func__, 150 pr_err("%s: Invalid heap type %d\n", __func__,
145 heap->type); 151 heap->type);
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 24bf3ebdf42..cdd65da515d 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -194,7 +194,6 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *,
194 194
195struct ion_heap *ion_heap_create(struct ion_platform_heap *); 195struct ion_heap *ion_heap_create(struct ion_platform_heap *);
196void ion_heap_destroy(struct ion_heap *); 196void ion_heap_destroy(struct ion_heap *);
197
198struct ion_heap *ion_system_heap_create(struct ion_platform_heap *); 197struct ion_heap *ion_system_heap_create(struct ion_platform_heap *);
199void ion_system_heap_destroy(struct ion_heap *); 198void ion_system_heap_destroy(struct ion_heap *);
200 199
@@ -203,6 +202,9 @@ void ion_system_contig_heap_destroy(struct ion_heap *);
203 202
204struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *); 203struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *);
205void ion_carveout_heap_destroy(struct ion_heap *); 204void ion_carveout_heap_destroy(struct ion_heap *);
205
206struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *);
207void ion_chunk_heap_destroy(struct ion_heap *);
206/** 208/**
207 * kernel api to allocate/free from carveout -- used when carveout is 209 * kernel api to allocate/free from carveout -- used when carveout is
208 * used to back an architecture specific custom heap 210 * used to back an architecture specific custom heap
diff --git a/include/linux/ion.h b/include/linux/ion.h
index a7d399c4f0b..814a7f4981a 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -35,6 +35,7 @@ enum ion_heap_type {
35 ION_HEAP_TYPE_SYSTEM, 35 ION_HEAP_TYPE_SYSTEM,
36 ION_HEAP_TYPE_SYSTEM_CONTIG, 36 ION_HEAP_TYPE_SYSTEM_CONTIG,
37 ION_HEAP_TYPE_CARVEOUT, 37 ION_HEAP_TYPE_CARVEOUT,
38 ION_HEAP_TYPE_CHUNK,
38 ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always 39 ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
39 are at the end of this enum */ 40 are at the end of this enum */
40 ION_NUM_HEAPS = 16, 41 ION_NUM_HEAPS = 16,
@@ -77,6 +78,8 @@ struct ion_buffer;
77 * @name: used for debug purposes 78 * @name: used for debug purposes
78 * @base: base address of heap in physical memory if applicable 79 * @base: base address of heap in physical memory if applicable
79 * @size: size of the heap in bytes if applicable 80 * @size: size of the heap in bytes if applicable
81 * @align: required alignment in physical memory if applicable
82 * @priv: private info passed from the board file
80 * 83 *
81 * Provided by the board file. 84 * Provided by the board file.
82 */ 85 */
@@ -86,6 +89,8 @@ struct ion_platform_heap {
86 const char *name; 89 const char *name;
87 ion_phys_addr_t base; 90 ion_phys_addr_t base;
88 size_t size; 91 size_t size;
92 ion_phys_addr_t align;
93 void *priv;
89}; 94};
90 95
91/** 96/**