aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-04-02 00:19:54 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-08 12:31:30 -0400
commitae9e6bc9f74f8247cbca50a6a93c80e0d686fa19 (patch)
tree6644b5ea22c27b78d9c062186e77fb9d56468090 /mm/percpu.c
parent577c9c456f0e1371cbade38eaf91ae8e8a308555 (diff)
percpu: don't put the first chunk in reverse-map rbtree
Impact: both first chunks don't use rbtree, no functional change There can be two first chunks - reserved and dynamic with the former one being optional. Dynamic first chunk was linked on reverse-mapping rbtree while the reserved one was mapped manually using the start address and reserved offset limit. This patch makes both first chunks to be looked up manually without using the rbtree. This is to help getting rid of the rbtree. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: rusty@rustcorp.com.au Cc: Paul Mundt <lethal@linux-sh.org> Cc: rmk@arm.linux.org.uk Cc: starvik@axis.com Cc: ralf@linux-mips.org Cc: davem@davemloft.net Cc: cooloney@kernel.org Cc: kyle@mcmartin.ca Cc: matthew@wil.cx Cc: grundler@parisc-linux.org Cc: takata@linux-m32r.org Cc: benh@kernel.crashing.org Cc: rth@twiddle.net Cc: ink@jurassic.park.msu.ru Cc: heiko.carstens@de.ibm.com Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nick Piggin <npiggin@suse.de> Cc: Christoph Lameter <cl@linux.com> LKML-Reference: <49D43CEA.3040609@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
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);