1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/staging/android/ion/ion_carveout_heap.c
5 * Copyright (C) 2011 Google, Inc.
7 #include <linux/spinlock.h>
8 #include <linux/dma-mapping.h>
10 #include <linux/genalloc.h>
13 #include <linux/scatterlist.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
18 #define ION_CARVEOUT_ALLOCATE_FAIL -1
20 struct ion_carveout_heap {
22 struct gen_pool *pool;
26 static phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
29 struct ion_carveout_heap *carveout_heap =
30 container_of(heap, struct ion_carveout_heap, heap);
31 unsigned long offset = gen_pool_alloc(carveout_heap->pool, size);
34 return ION_CARVEOUT_ALLOCATE_FAIL;
39 static void ion_carveout_free(struct ion_heap *heap, phys_addr_t addr,
42 struct ion_carveout_heap *carveout_heap =
43 container_of(heap, struct ion_carveout_heap, heap);
45 if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
47 gen_pool_free(carveout_heap->pool, addr, size);
50 static int ion_carveout_heap_allocate(struct ion_heap *heap,
51 struct ion_buffer *buffer,
55 struct sg_table *table;
59 table = kmalloc(sizeof(*table), GFP_KERNEL);
62 ret = sg_alloc_table(table, 1, GFP_KERNEL);
66 paddr = ion_carveout_allocate(heap, size);
67 if (paddr == ION_CARVEOUT_ALLOCATE_FAIL) {
72 sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0);
73 buffer->sg_table = table;
84 static void ion_carveout_heap_free(struct ion_buffer *buffer)
86 struct ion_heap *heap = buffer->heap;
87 struct sg_table *table = buffer->sg_table;
88 struct page *page = sg_page(table->sgl);
89 phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
91 ion_heap_buffer_zero(buffer);
93 ion_carveout_free(heap, paddr, buffer->size);
98 static struct ion_heap_ops carveout_heap_ops = {
99 .allocate = ion_carveout_heap_allocate,
100 .free = ion_carveout_heap_free,
101 .map_user = ion_heap_map_user,
102 .map_kernel = ion_heap_map_kernel,
103 .unmap_kernel = ion_heap_unmap_kernel,
106 struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
108 struct ion_carveout_heap *carveout_heap;
114 page = pfn_to_page(PFN_DOWN(heap_data->base));
115 size = heap_data->size;
117 ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
121 carveout_heap = kzalloc(sizeof(*carveout_heap), GFP_KERNEL);
123 return ERR_PTR(-ENOMEM);
125 carveout_heap->pool = gen_pool_create(PAGE_SHIFT, -1);
126 if (!carveout_heap->pool) {
127 kfree(carveout_heap);
128 return ERR_PTR(-ENOMEM);
130 carveout_heap->base = heap_data->base;
131 gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size,
133 carveout_heap->heap.ops = &carveout_heap_ops;
134 carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
135 carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
137 return &carveout_heap->heap;