aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/percpu.c')
-rw-r--r--mm/percpu.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index 1aa5d8fbca12..bf1bf1f4a729 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -110,9 +110,21 @@ static size_t pcpu_chunk_struct_size __read_mostly;
110void *pcpu_base_addr __read_mostly; 110void *pcpu_base_addr __read_mostly;
111EXPORT_SYMBOL_GPL(pcpu_base_addr); 111EXPORT_SYMBOL_GPL(pcpu_base_addr);
112 112
113/* optional reserved chunk, only accessible for reserved allocations */ 113/*
114 * The first chunk which always exists. Note that unlike other
115 * chunks, this one can be allocated and mapped in several different
116 * ways and thus often doesn't live in the vmalloc area.
117 */
118static struct pcpu_chunk *pcpu_first_chunk;
119
120/*
121 * Optional reserved chunk. This chunk reserves part of the first
122 * chunk and serves it for reserved allocations. The amount of
123 * reserved offset is in pcpu_reserved_chunk_limit. When reserved
124 * area doesn't exist, the following variables contain NULL and 0
125 * respectively.
126 */
114static struct pcpu_chunk *pcpu_reserved_chunk; 127static struct pcpu_chunk *pcpu_reserved_chunk;
115/* offset limit of the reserved chunk */
116static int pcpu_reserved_chunk_limit; 128static int pcpu_reserved_chunk_limit;
117 129
118/* 130/*
@@ -297,15 +309,16 @@ static struct rb_node **pcpu_chunk_rb_search(void *addr,
297 */ 309 */
298static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr) 310static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
299{ 311{
312 void *first_start = pcpu_first_chunk->vm->addr;
300 struct rb_node *n, *parent; 313 struct rb_node *n, *parent;
301 struct pcpu_chunk *chunk; 314 struct pcpu_chunk *chunk;
302 315
303 /* is it in the reserved chunk? */ 316 /* is it in the first chunk? */
304 if (pcpu_reserved_chunk) { 317 if (addr >= first_start && addr < first_start + pcpu_chunk_size) {
305 void *start = pcpu_reserved_chunk->vm->addr; 318 /* is it in the reserved area? */
306 319 if (addr < first_start + pcpu_reserved_chunk_limit)
307 if (addr >= start && addr < start + pcpu_reserved_chunk_limit)
308 return pcpu_reserved_chunk; 320 return pcpu_reserved_chunk;
321 return pcpu_first_chunk;
309 } 322 }
310 323
311 /* nah... search the regular ones */ 324 /* nah... search the regular ones */
@@ -1147,7 +1160,8 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
1147 1160
1148 if (reserved_size) { 1161 if (reserved_size) {
1149 schunk->free_size = reserved_size; 1162 schunk->free_size = reserved_size;
1150 pcpu_reserved_chunk = schunk; /* not for dynamic alloc */ 1163 pcpu_reserved_chunk = schunk;
1164 pcpu_reserved_chunk_limit = static_size + reserved_size;
1151 } else { 1165 } else {
1152 schunk->free_size = dyn_size; 1166 schunk->free_size = dyn_size;
1153 dyn_size = 0; /* dynamic area covered */ 1167 dyn_size = 0; /* dynamic area covered */
@@ -1158,8 +1172,6 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
1158 if (schunk->free_size) 1172 if (schunk->free_size)
1159 schunk->map[schunk->map_used++] = schunk->free_size; 1173 schunk->map[schunk->map_used++] = schunk->free_size;
1160 1174
1161 pcpu_reserved_chunk_limit = static_size + schunk->free_size;
1162
1163 /* init dynamic chunk if necessary */ 1175 /* init dynamic chunk if necessary */
1164 if (dyn_size) { 1176 if (dyn_size) {
1165 dchunk = alloc_bootmem(sizeof(struct pcpu_chunk)); 1177 dchunk = alloc_bootmem(sizeof(struct pcpu_chunk));
@@ -1226,13 +1238,8 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
1226 } 1238 }
1227 1239
1228 /* link the first chunk in */ 1240 /* link the first chunk in */
1229 if (!dchunk) { 1241 pcpu_first_chunk = dchunk ?: schunk;
1230 pcpu_chunk_relocate(schunk, -1); 1242 pcpu_chunk_relocate(pcpu_first_chunk, -1);
1231 pcpu_chunk_addr_insert(schunk);
1232 } else {
1233 pcpu_chunk_relocate(dchunk, -1);
1234 pcpu_chunk_addr_insert(dchunk);
1235 }
1236 1243
1237 /* we're done */ 1244 /* we're done */
1238 pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0); 1245 pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0);