]> git.ipfire.org Git - thirdparty/kernel/linux.git/blame - drivers/staging/android/ion/ion_page_pool.c
staging: android: ion: Remove unused include files for ion_page_pool.c
[thirdparty/kernel/linux.git] / drivers / staging / android / ion / ion_page_pool.c
CommitLineData
bdcb7be6 1// SPDX-License-Identifier: GPL-2.0
0214c7f2
RSZ
2/*
3 * drivers/staging/android/ion/ion_mem_pool.c
4 *
5 * Copyright (C) 2011 Google, Inc.
0214c7f2
RSZ
6 */
7
0214c7f2 8#include <linux/list.h>
30d79792 9#include <linux/init.h>
0214c7f2 10#include <linux/slab.h>
0cd2dc4d 11#include <linux/swap.h>
eb9751db
LA
12
13#include "ion.h"
0214c7f2 14
0214c7f2
RSZ
15static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
16{
17 struct page *page = alloc_pages(pool->gfp_mask, pool->order);
18
19 if (!page)
20 return NULL;
0214c7f2
RSZ
21 return page;
22}
23
24static void ion_page_pool_free_pages(struct ion_page_pool *pool,
25 struct page *page)
26{
27 __free_pages(page, pool->order);
28}
29
30static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page)
31{
efee5a0c 32 mutex_lock(&pool->mutex);
0fb9b815 33 if (PageHighMem(page)) {
38c003b1 34 list_add_tail(&page->lru, &pool->high_items);
0fb9b815
RSZ
35 pool->high_count++;
36 } else {
38c003b1 37 list_add_tail(&page->lru, &pool->low_items);
0fb9b815
RSZ
38 pool->low_count++;
39 }
efee5a0c 40 mutex_unlock(&pool->mutex);
0214c7f2
RSZ
41 return 0;
42}
43
0fb9b815 44static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high)
0214c7f2 45{
0214c7f2
RSZ
46 struct page *page;
47
0fb9b815
RSZ
48 if (high) {
49 BUG_ON(!pool->high_count);
38c003b1 50 page = list_first_entry(&pool->high_items, struct page, lru);
0fb9b815
RSZ
51 pool->high_count--;
52 } else {
53 BUG_ON(!pool->low_count);
38c003b1 54 page = list_first_entry(&pool->low_items, struct page, lru);
0fb9b815
RSZ
55 pool->low_count--;
56 }
0214c7f2 57
38c003b1 58 list_del(&page->lru);
0214c7f2
RSZ
59 return page;
60}
61
79240748 62struct page *ion_page_pool_alloc(struct ion_page_pool *pool)
0214c7f2
RSZ
63{
64 struct page *page = NULL;
65
66 BUG_ON(!pool);
67
68 mutex_lock(&pool->mutex);
0fb9b815
RSZ
69 if (pool->high_count)
70 page = ion_page_pool_remove(pool, true);
71 else if (pool->low_count)
72 page = ion_page_pool_remove(pool, false);
0214c7f2
RSZ
73 mutex_unlock(&pool->mutex);
74
0fb9b815
RSZ
75 if (!page)
76 page = ion_page_pool_alloc_pages(pool);
77
0214c7f2
RSZ
78 return page;
79}
80
e1d855b0 81void ion_page_pool_free(struct ion_page_pool *pool, struct page *page)
0214c7f2
RSZ
82{
83 int ret;
84
bdeb9f1c
HS
85 BUG_ON(pool->order != compound_order(page));
86
0214c7f2
RSZ
87 ret = ion_page_pool_add(pool, page);
88 if (ret)
89 ion_page_pool_free_pages(pool, page);
0214c7f2
RSZ
90}
91
ea313b5f 92static int ion_page_pool_total(struct ion_page_pool *pool, bool high)
797a95c4 93{
80cb77dc 94 int count = pool->low_count;
797a95c4 95
80cb77dc
HS
96 if (high)
97 count += pool->high_count;
98
99 return count << pool->order;
797a95c4
RSZ
100}
101
ea313b5f 102int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
679011bd 103 int nr_to_scan)
0214c7f2 104{
b44d9ce3 105 int freed = 0;
0fb9b815
RSZ
106 bool high;
107
0cd2dc4d 108 if (current_is_kswapd())
17fbab1e 109 high = true;
0cd2dc4d
HS
110 else
111 high = !!(gfp_mask & __GFP_HIGHMEM);
0214c7f2 112
797a95c4 113 if (nr_to_scan == 0)
ea313b5f
RSZ
114 return ion_page_pool_total(pool, high);
115
b44d9ce3 116 while (freed < nr_to_scan) {
ea313b5f
RSZ
117 struct page *page;
118
119 mutex_lock(&pool->mutex);
ce3d1093 120 if (pool->low_count) {
ea313b5f 121 page = ion_page_pool_remove(pool, false);
ce3d1093
CC
122 } else if (high && pool->high_count) {
123 page = ion_page_pool_remove(pool, true);
ea313b5f 124 } else {
0fb9b815 125 mutex_unlock(&pool->mutex);
ea313b5f 126 break;
0214c7f2 127 }
ea313b5f
RSZ
128 mutex_unlock(&pool->mutex);
129 ion_page_pool_free_pages(pool, page);
b44d9ce3 130 freed += (1 << pool->order);
0214c7f2 131 }
0214c7f2 132
b9daf0b6 133 return freed;
0214c7f2
RSZ
134}
135
e7f63771
CF
136struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
137 bool cached)
0214c7f2 138{
8fb78ad6
BM
139 struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
140
0214c7f2
RSZ
141 if (!pool)
142 return NULL;
0fb9b815
RSZ
143 pool->high_count = 0;
144 pool->low_count = 0;
145 INIT_LIST_HEAD(&pool->low_items);
146 INIT_LIST_HEAD(&pool->high_items);
bdeb9f1c 147 pool->gfp_mask = gfp_mask | __GFP_COMP;
0214c7f2
RSZ
148 pool->order = order;
149 mutex_init(&pool->mutex);
797a95c4 150 plist_node_init(&pool->list, order);
e7f63771
CF
151 if (cached)
152 pool->cached = true;
0214c7f2
RSZ
153
154 return pool;
155}
156
157void ion_page_pool_destroy(struct ion_page_pool *pool)
158{
0214c7f2
RSZ
159 kfree(pool);
160}
161
797a95c4
RSZ
162static int __init ion_page_pool_init(void)
163{
797a95c4
RSZ
164 return 0;
165}
30d79792 166device_initcall(ion_page_pool_init);