aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-07-03 19:11:00 -0400
committerTejun Heo <tj@kernel.org>2009-07-03 19:11:00 -0400
commitce3141a277ff6cc37e51008b8888dc2cb7456ef1 (patch)
tree8bd43d595d85fa37de5f3a7030580aa56b590028 /arch/sparc/kernel
parentc8a51be4cabb7009db5f865169389242d49c4c60 (diff)
percpu: drop pcpu_chunk->page[]
percpu core doesn't need to tack all the allocated pages. It needs to know whether certain pages are populated and a way to reverse map address to page when freeing. This patch drops pcpu_chunk->page[] and use populated bitmap and vmalloc_to_page() lookup instead. Using vmalloc_to_page() exclusively is also possible but complicates first chunk handling, inflates cache footprint and prevents non-standard memory allocation for percpu memory. pcpu_chunk->page[] was used to track each page's allocation and allowed asymmetric population which happens during failure path; however, with single bitmap for all units, this is no longer possible. Bite the bullet and rewrite (de)populate functions so that things are done in clearly separated steps such that asymmetric population doesn't happen. This makes the (de)population process much more modular and will also ease implementing non-standard memory usage in the future (e.g. large pages). This makes @get_page_fn parameter to pcpu_setup_first_chunk() unnecessary. The parameter is dropped and all first chunk helpers are updated accordingly. Please note that despite the volume most changes to first chunk helpers are symbol renames for variables which don't need to be referenced outside of the helper anymore. This change reduces memory usage and cache footprint of pcpu_chunk. Now only #unit_pages bits are necessary per chunk. [ Impact: reduced memory usage and cache footprint for bookkeeping ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: David Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/smp_64.c42
1 files changed, 15 insertions, 27 deletions
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index ccad7b20ae75..f2f22ee97a7a 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1415,19 +1415,6 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
1415#endif 1415#endif
1416} 1416}
1417 1417
1418static size_t pcpur_size __initdata;
1419static void **pcpur_ptrs __initdata;
1420
1421static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
1422{
1423 size_t off = (size_t)pageno << PAGE_SHIFT;
1424
1425 if (off >= pcpur_size)
1426 return NULL;
1427
1428 return virt_to_page(pcpur_ptrs[cpu] + off);
1429}
1430
1431#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL) 1418#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL)
1432 1419
1433static void __init pcpu_map_range(unsigned long start, unsigned long end, 1420static void __init pcpu_map_range(unsigned long start, unsigned long end,
@@ -1491,25 +1478,26 @@ void __init setup_per_cpu_areas(void)
1491 size_t dyn_size, static_size = __per_cpu_end - __per_cpu_start; 1478 size_t dyn_size, static_size = __per_cpu_end - __per_cpu_start;
1492 static struct vm_struct vm; 1479 static struct vm_struct vm;
1493 unsigned long delta, cpu; 1480 unsigned long delta, cpu;
1494 size_t pcpu_unit_size; 1481 size_t size_sum, pcpu_unit_size;
1495 size_t ptrs_size; 1482 size_t ptrs_size;
1483 void **ptrs;
1496 1484
1497 pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + 1485 size_sum = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
1498 PERCPU_DYNAMIC_RESERVE); 1486 PERCPU_DYNAMIC_RESERVE);
1499 dyn_size = pcpur_size - static_size - PERCPU_MODULE_RESERVE; 1487 dyn_size = size_sum - static_size - PERCPU_MODULE_RESERVE;
1500 1488
1501 1489
1502 ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); 1490 ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(ptrs[0]));
1503 pcpur_ptrs = alloc_bootmem(ptrs_size); 1491 ptrs = alloc_bootmem(ptrs_size);
1504 1492
1505 for_each_possible_cpu(cpu) { 1493 for_each_possible_cpu(cpu) {
1506 pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PCPU_CHUNK_SIZE, 1494 ptrs[cpu] = pcpu_alloc_bootmem(cpu, PCPU_CHUNK_SIZE,
1507 PCPU_CHUNK_SIZE); 1495 PCPU_CHUNK_SIZE);
1508 1496
1509 free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size), 1497 free_bootmem(__pa(ptrs[cpu] + size_sum),
1510 PCPU_CHUNK_SIZE - pcpur_size); 1498 PCPU_CHUNK_SIZE - size_sum);
1511 1499
1512 memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size); 1500 memcpy(ptrs[cpu], __per_cpu_load, static_size);
1513 } 1501 }
1514 1502
1515 /* allocate address and map */ 1503 /* allocate address and map */
@@ -1523,14 +1511,14 @@ void __init setup_per_cpu_areas(void)
1523 1511
1524 start += cpu * PCPU_CHUNK_SIZE; 1512 start += cpu * PCPU_CHUNK_SIZE;
1525 end = start + PCPU_CHUNK_SIZE; 1513 end = start + PCPU_CHUNK_SIZE;
1526 pcpu_map_range(start, end, virt_to_page(pcpur_ptrs[cpu])); 1514 pcpu_map_range(start, end, virt_to_page(ptrs[cpu]));
1527 } 1515 }
1528 1516
1529 pcpu_unit_size = pcpu_setup_first_chunk(pcpur_get_page, static_size, 1517 pcpu_unit_size = pcpu_setup_first_chunk(static_size,
1530 PERCPU_MODULE_RESERVE, dyn_size, 1518 PERCPU_MODULE_RESERVE, dyn_size,
1531 PCPU_CHUNK_SIZE, vm.addr); 1519 PCPU_CHUNK_SIZE, vm.addr);
1532 1520
1533 free_bootmem(__pa(pcpur_ptrs), ptrs_size); 1521 free_bootmem(__pa(ptrs), ptrs_size);
1534 1522
1535 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; 1523 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
1536 for_each_possible_cpu(cpu) { 1524 for_each_possible_cpu(cpu) {