powerpc64: convert to dynamic percpu allocator
Now that percpu allows arbitrary embedding of the first chunk, powerpc64 can easily be converted to dynamic percpu allocator. Convert it. powerpc supports several large page sizes. Cap atom_size at 1M. There isn't much to gain by going above that anyway. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
bcb2107fdb
commit
c2a7e81801
|
@ -46,10 +46,10 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
|
|||
bool
|
||||
default y
|
||||
|
||||
config HAVE_LEGACY_PER_CPU_AREA
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool PPC64
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool PPC64
|
||||
|
||||
config IRQ_PER_CPU
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <asm/cache.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/mmu-hash64.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/xmon.h>
|
||||
#include <asm/udbg.h>
|
||||
|
@ -569,25 +570,53 @@ void cpu_die(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define PCPU_DYN_SIZE ()
|
||||
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
|
||||
{
|
||||
return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
|
||||
__pa(MAX_DMA_ADDRESS));
|
||||
}
|
||||
|
||||
static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
free_bootmem(__pa(ptr), size);
|
||||
}
|
||||
|
||||
static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (cpu_to_node(from) == cpu_to_node(to))
|
||||
return LOCAL_DISTANCE;
|
||||
else
|
||||
return REMOTE_DISTANCE;
|
||||
}
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long size;
|
||||
char *ptr;
|
||||
const size_t dyn_size = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
|
||||
size_t atom_size;
|
||||
unsigned long delta;
|
||||
unsigned int cpu;
|
||||
int rc;
|
||||
|
||||
/* Copy section for each CPU (we discard the original) */
|
||||
size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE);
|
||||
#ifdef CONFIG_MODULES
|
||||
if (size < PERCPU_ENOUGH_ROOM)
|
||||
size = PERCPU_ENOUGH_ROOM;
|
||||
#endif
|
||||
/*
|
||||
* Linear mapping is one of 4K, 1M and 16M. For 4K, no need
|
||||
* to group units. For larger mappings, use 1M atom which
|
||||
* should be large enough to contain a number of units.
|
||||
*/
|
||||
if (mmu_linear_psize == MMU_PAGE_4K)
|
||||
atom_size = PAGE_SIZE;
|
||||
else
|
||||
atom_size = 1 << 20;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
|
||||
rc = pcpu_embed_first_chunk(0, dyn_size, atom_size, pcpu_cpu_distance,
|
||||
pcpu_fc_alloc, pcpu_fc_free);
|
||||
if (rc < 0)
|
||||
panic("cannot initialize percpu area (err=%d)", rc);
|
||||
|
||||
paca[i].data_offset = ptr - __per_cpu_start;
|
||||
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
||||
}
|
||||
delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
|
||||
for_each_possible_cpu(cpu)
|
||||
paca[cpu].data_offset = delta + pcpu_unit_offsets[cpu];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue