1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/staging/android/ion/ion_heap.c
5 * Copyright (C) 2011 Google, Inc.
9 #include <linux/freezer.h>
10 #include <linux/kthread.h>
12 #include <linux/rtmutex.h>
13 #include <linux/sched.h>
14 #include <uapi/linux/sched/types.h>
15 #include <linux/scatterlist.h>
16 #include <linux/vmalloc.h>
19 void *ion_heap_map_kernel(struct ion_heap *heap,
20 struct ion_buffer *buffer)
22 struct scatterlist *sg;
26 struct sg_table *table = buffer->sg_table;
27 int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
28 struct page **pages = vmalloc(sizeof(struct page *) * npages);
29 struct page **tmp = pages;
34 if (buffer->flags & ION_FLAG_CACHED)
37 pgprot = pgprot_writecombine(PAGE_KERNEL);
39 for_each_sg(table->sgl, sg, table->nents, i) {
40 int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE;
41 struct page *page = sg_page(sg);
44 for (j = 0; j < npages_this_entry; j++)
47 vaddr = vmap(pages, npages, VM_MAP, pgprot);
51 return ERR_PTR(-ENOMEM);
56 void ion_heap_unmap_kernel(struct ion_heap *heap,
57 struct ion_buffer *buffer)
59 vunmap(buffer->vaddr);
62 int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
63 struct vm_area_struct *vma)
65 struct sg_table *table = buffer->sg_table;
66 unsigned long addr = vma->vm_start;
67 unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
68 struct scatterlist *sg;
72 for_each_sg(table->sgl, sg, table->nents, i) {
73 struct page *page = sg_page(sg);
74 unsigned long remainder = vma->vm_end - addr;
75 unsigned long len = sg->length;
77 if (offset >= sg->length) {
81 page += offset / PAGE_SIZE;
82 len = sg->length - offset;
85 len = min(len, remainder);
86 ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
91 if (addr >= vma->vm_end)
97 static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot)
99 void *addr = vm_map_ram(pages, num, -1, pgprot);
103 memset(addr, 0, PAGE_SIZE * num);
104 vm_unmap_ram(addr, num);
109 static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents,
114 struct sg_page_iter piter;
115 struct page *pages[32];
117 for_each_sg_page(sgl, &piter, nents, 0) {
118 pages[p++] = sg_page_iter_page(&piter);
119 if (p == ARRAY_SIZE(pages)) {
120 ret = ion_heap_clear_pages(pages, p, pgprot);
127 ret = ion_heap_clear_pages(pages, p, pgprot);
132 int ion_heap_buffer_zero(struct ion_buffer *buffer)
134 struct sg_table *table = buffer->sg_table;
137 if (buffer->flags & ION_FLAG_CACHED)
138 pgprot = PAGE_KERNEL;
140 pgprot = pgprot_writecombine(PAGE_KERNEL);
142 return ion_heap_sglist_zero(table->sgl, table->nents, pgprot);
145 int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot)
147 struct scatterlist sg;
149 sg_init_table(&sg, 1);
150 sg_set_page(&sg, page, size, 0);
151 return ion_heap_sglist_zero(&sg, 1, pgprot);
154 void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer)
156 spin_lock(&heap->free_lock);
157 list_add(&buffer->list, &heap->free_list);
158 heap->free_list_size += buffer->size;
159 spin_unlock(&heap->free_lock);
160 wake_up(&heap->waitqueue);
163 size_t ion_heap_freelist_size(struct ion_heap *heap)
167 spin_lock(&heap->free_lock);
168 size = heap->free_list_size;
169 spin_unlock(&heap->free_lock);
174 static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size,
177 struct ion_buffer *buffer;
178 size_t total_drained = 0;
180 if (ion_heap_freelist_size(heap) == 0)
183 spin_lock(&heap->free_lock);
185 size = heap->free_list_size;
187 while (!list_empty(&heap->free_list)) {
188 if (total_drained >= size)
190 buffer = list_first_entry(&heap->free_list, struct ion_buffer,
192 list_del(&buffer->list);
193 heap->free_list_size -= buffer->size;
195 buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE;
196 total_drained += buffer->size;
197 spin_unlock(&heap->free_lock);
198 ion_buffer_destroy(buffer);
199 spin_lock(&heap->free_lock);
201 spin_unlock(&heap->free_lock);
203 return total_drained;
206 size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size)
208 return _ion_heap_freelist_drain(heap, size, false);
211 size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size)
213 return _ion_heap_freelist_drain(heap, size, true);
216 static int ion_heap_deferred_free(void *data)
218 struct ion_heap *heap = data;
221 struct ion_buffer *buffer;
223 wait_event_freezable(heap->waitqueue,
224 ion_heap_freelist_size(heap) > 0);
226 spin_lock(&heap->free_lock);
227 if (list_empty(&heap->free_list)) {
228 spin_unlock(&heap->free_lock);
231 buffer = list_first_entry(&heap->free_list, struct ion_buffer,
233 list_del(&buffer->list);
234 heap->free_list_size -= buffer->size;
235 spin_unlock(&heap->free_lock);
236 ion_buffer_destroy(buffer);
242 int ion_heap_init_deferred_free(struct ion_heap *heap)
244 struct sched_param param = { .sched_priority = 0 };
246 INIT_LIST_HEAD(&heap->free_list);
247 init_waitqueue_head(&heap->waitqueue);
248 heap->task = kthread_run(ion_heap_deferred_free, heap,
250 if (IS_ERR(heap->task)) {
251 pr_err("%s: creating thread for deferred free failed\n",
253 return PTR_ERR_OR_ZERO(heap->task);
255 sched_setscheduler(heap->task, SCHED_IDLE, ¶m);
259 static unsigned long ion_heap_shrink_count(struct shrinker *shrinker,
260 struct shrink_control *sc)
262 struct ion_heap *heap = container_of(shrinker, struct ion_heap,
266 total = ion_heap_freelist_size(heap) / PAGE_SIZE;
267 if (heap->ops->shrink)
268 total += heap->ops->shrink(heap, sc->gfp_mask, 0);
272 static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker,
273 struct shrink_control *sc)
275 struct ion_heap *heap = container_of(shrinker, struct ion_heap,
278 int to_scan = sc->nr_to_scan;
284 * shrink the free list first, no point in zeroing the memory if we're
285 * just going to reclaim it. Also, skip any possible page pooling.
287 if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
288 freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) /
295 if (heap->ops->shrink)
296 freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan);
300 int ion_heap_init_shrinker(struct ion_heap *heap)
302 heap->shrinker.count_objects = ion_heap_shrink_count;
303 heap->shrinker.scan_objects = ion_heap_shrink_scan;
304 heap->shrinker.seeks = DEFAULT_SEEKS;
305 heap->shrinker.batch = 0;
307 return register_shrinker(&heap->shrinker);