2 * drivers/staging/android/ion/ion_carveout_heap.c
4 * Copyright (C) 2011 Google, Inc.
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.
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.
16 #include <linux/spinlock.h>
18 #include <linux/err.h>
19 #include <linux/genalloc.h>
22 #include <linux/scatterlist.h>
23 #include <linux/slab.h>
24 #include <linux/vmalloc.h>
28 #include <asm/mach/map.h>
30 struct ion_carveout_heap
{
32 struct gen_pool
*pool
;
36 ion_phys_addr_t
ion_carveout_allocate(struct ion_heap
*heap
,
40 struct ion_carveout_heap
*carveout_heap
=
41 container_of(heap
, struct ion_carveout_heap
, heap
);
42 unsigned long offset
= gen_pool_alloc(carveout_heap
->pool
, size
);
45 return ION_CARVEOUT_ALLOCATE_FAIL
;
50 void ion_carveout_free(struct ion_heap
*heap
, ion_phys_addr_t addr
,
53 struct ion_carveout_heap
*carveout_heap
=
54 container_of(heap
, struct ion_carveout_heap
, heap
);
56 if (addr
== ION_CARVEOUT_ALLOCATE_FAIL
)
58 gen_pool_free(carveout_heap
->pool
, addr
, size
);
61 static int ion_carveout_heap_phys(struct ion_heap
*heap
,
62 struct ion_buffer
*buffer
,
63 ion_phys_addr_t
*addr
, size_t *len
)
65 *addr
= buffer
->priv_phys
;
70 static int ion_carveout_heap_allocate(struct ion_heap
*heap
,
71 struct ion_buffer
*buffer
,
72 unsigned long size
, unsigned long align
,
75 buffer
->priv_phys
= ion_carveout_allocate(heap
, size
, align
);
76 return buffer
->priv_phys
== ION_CARVEOUT_ALLOCATE_FAIL
? -ENOMEM
: 0;
79 static void ion_carveout_heap_free(struct ion_buffer
*buffer
)
81 struct ion_heap
*heap
= buffer
->heap
;
83 ion_carveout_free(heap
, buffer
->priv_phys
, buffer
->size
);
84 buffer
->priv_phys
= ION_CARVEOUT_ALLOCATE_FAIL
;
87 struct sg_table
*ion_carveout_heap_map_dma(struct ion_heap
*heap
,
88 struct ion_buffer
*buffer
)
90 struct sg_table
*table
;
93 table
= kzalloc(sizeof(struct sg_table
), GFP_KERNEL
);
95 return ERR_PTR(-ENOMEM
);
96 ret
= sg_alloc_table(table
, 1, GFP_KERNEL
);
101 sg_set_page(table
->sgl
, phys_to_page(buffer
->priv_phys
), buffer
->size
,
106 void ion_carveout_heap_unmap_dma(struct ion_heap
*heap
,
107 struct ion_buffer
*buffer
)
109 sg_free_table(buffer
->sg_table
);
112 void *ion_carveout_heap_map_kernel(struct ion_heap
*heap
,
113 struct ion_buffer
*buffer
)
116 int mtype
= MT_MEMORY_NONCACHED
;
118 if (buffer
->flags
& ION_FLAG_CACHED
)
121 ret
= __arm_ioremap(buffer
->priv_phys
, buffer
->size
,
124 return ERR_PTR(-ENOMEM
);
129 void ion_carveout_heap_unmap_kernel(struct ion_heap
*heap
,
130 struct ion_buffer
*buffer
)
132 __arm_iounmap(buffer
->vaddr
);
133 buffer
->vaddr
= NULL
;
137 int ion_carveout_heap_map_user(struct ion_heap
*heap
, struct ion_buffer
*buffer
,
138 struct vm_area_struct
*vma
)
140 return remap_pfn_range(vma
, vma
->vm_start
,
141 __phys_to_pfn(buffer
->priv_phys
) + vma
->vm_pgoff
,
142 vma
->vm_end
- vma
->vm_start
,
143 pgprot_noncached(vma
->vm_page_prot
));
146 static struct ion_heap_ops carveout_heap_ops
= {
147 .allocate
= ion_carveout_heap_allocate
,
148 .free
= ion_carveout_heap_free
,
149 .phys
= ion_carveout_heap_phys
,
150 .map_dma
= ion_carveout_heap_map_dma
,
151 .unmap_dma
= ion_carveout_heap_unmap_dma
,
152 .map_user
= ion_carveout_heap_map_user
,
153 .map_kernel
= ion_carveout_heap_map_kernel
,
154 .unmap_kernel
= ion_carveout_heap_unmap_kernel
,
157 struct ion_heap
*ion_carveout_heap_create(struct ion_platform_heap
*heap_data
)
159 struct ion_carveout_heap
*carveout_heap
;
161 carveout_heap
= kzalloc(sizeof(struct ion_carveout_heap
), GFP_KERNEL
);
163 return ERR_PTR(-ENOMEM
);
165 carveout_heap
->pool
= gen_pool_create(12, -1);
166 if (!carveout_heap
->pool
) {
167 kfree(carveout_heap
);
168 return ERR_PTR(-ENOMEM
);
170 carveout_heap
->base
= heap_data
->base
;
171 gen_pool_add(carveout_heap
->pool
, carveout_heap
->base
, heap_data
->size
,
173 carveout_heap
->heap
.ops
= &carveout_heap_ops
;
174 carveout_heap
->heap
.type
= ION_HEAP_TYPE_CARVEOUT
;
176 return &carveout_heap
->heap
;
179 void ion_carveout_heap_destroy(struct ion_heap
*heap
)
181 struct ion_carveout_heap
*carveout_heap
=
182 container_of(heap
, struct ion_carveout_heap
, heap
);
184 gen_pool_destroy(carveout_heap
->pool
);
185 kfree(carveout_heap
);
186 carveout_heap
= NULL
;