forked from Minki/linux
percpu: generalize first chunk allocator selection
Now that all first chunk allocators are in mm/percpu.c, it makes sense to make generalize percpu_alloc kernel parameter. Define PCPU_FC_* and set pcpu_chosen_fc using early_param() in mm/percpu.c. Arch code can use the set value to determine which first chunk allocator to use. Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
08fc458061
commit
f58dc01ba2
@ -1919,11 +1919,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||||||
Format: { 0 | 1 }
|
Format: { 0 | 1 }
|
||||||
See arch/parisc/kernel/pdc_chassis.c
|
See arch/parisc/kernel/pdc_chassis.c
|
||||||
|
|
||||||
percpu_alloc= [X86] Select which percpu first chunk allocator to use.
|
percpu_alloc= Select which percpu first chunk allocator to use.
|
||||||
Allowed values are one of "lpage", "embed" and "page".
|
Currently supported values are "embed", "page" and
|
||||||
See comments in arch/x86/kernel/setup_percpu.c for
|
"lpage". Archs may support subset or none of the
|
||||||
details on each allocator. This parameter is primarily
|
selections. See comments in mm/percpu.c for details
|
||||||
for debugging and performance comparison.
|
on each allocator. This parameter is primarily for
|
||||||
|
debugging and performance comparison.
|
||||||
|
|
||||||
pf. [PARIDE]
|
pf. [PARIDE]
|
||||||
See Documentation/blockdev/paride.txt.
|
See Documentation/blockdev/paride.txt.
|
||||||
|
@ -267,16 +267,6 @@ static ssize_t __init setup_pcpu_page(size_t static_size)
|
|||||||
pcpup_populate_pte);
|
pcpup_populate_pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for explicit first chunk allocator selection */
|
|
||||||
static char pcpu_chosen_alloc[16] __initdata;
|
|
||||||
|
|
||||||
static int __init percpu_alloc_setup(char *str)
|
|
||||||
{
|
|
||||||
strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
early_param("percpu_alloc", percpu_alloc_setup);
|
|
||||||
|
|
||||||
static inline void setup_percpu_segment(int cpu)
|
static inline void setup_percpu_segment(int cpu)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
@ -307,19 +297,17 @@ void __init setup_per_cpu_areas(void)
|
|||||||
* each allocator for details.
|
* each allocator for details.
|
||||||
*/
|
*/
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (strlen(pcpu_chosen_alloc)) {
|
if (pcpu_chosen_fc != PCPU_FC_AUTO) {
|
||||||
if (strcmp(pcpu_chosen_alloc, "page")) {
|
if (pcpu_chosen_fc != PCPU_FC_PAGE) {
|
||||||
if (!strcmp(pcpu_chosen_alloc, "lpage"))
|
if (pcpu_chosen_fc == PCPU_FC_LPAGE)
|
||||||
ret = setup_pcpu_lpage(static_size, true);
|
ret = setup_pcpu_lpage(static_size, true);
|
||||||
else if (!strcmp(pcpu_chosen_alloc, "embed"))
|
|
||||||
ret = setup_pcpu_embed(static_size, true);
|
|
||||||
else
|
else
|
||||||
pr_warning("PERCPU: unknown allocator %s "
|
ret = setup_pcpu_embed(static_size, true);
|
||||||
"specified\n", pcpu_chosen_alloc);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
pr_warning("PERCPU: %s allocator failed (%zd), "
|
pr_warning("PERCPU: %s allocator failed (%zd), "
|
||||||
"falling back to page size\n",
|
"falling back to page size\n",
|
||||||
pcpu_chosen_alloc, ret);
|
pcpu_fc_names[pcpu_chosen_fc], ret);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = setup_pcpu_lpage(static_size, false);
|
ret = setup_pcpu_lpage(static_size, false);
|
||||||
|
@ -59,6 +59,18 @@
|
|||||||
extern void *pcpu_base_addr;
|
extern void *pcpu_base_addr;
|
||||||
extern const int *pcpu_unit_map;
|
extern const int *pcpu_unit_map;
|
||||||
|
|
||||||
|
enum pcpu_fc {
|
||||||
|
PCPU_FC_AUTO,
|
||||||
|
PCPU_FC_EMBED,
|
||||||
|
PCPU_FC_PAGE,
|
||||||
|
PCPU_FC_LPAGE,
|
||||||
|
|
||||||
|
PCPU_FC_NR,
|
||||||
|
};
|
||||||
|
extern const char *pcpu_fc_names[PCPU_FC_NR];
|
||||||
|
|
||||||
|
extern enum pcpu_fc pcpu_chosen_fc;
|
||||||
|
|
||||||
typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size);
|
typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size);
|
||||||
typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
|
typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
|
||||||
typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
|
typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
|
||||||
|
32
mm/percpu.c
32
mm/percpu.c
@ -1414,6 +1414,38 @@ size_t __init pcpu_setup_first_chunk(size_t static_size, size_t reserved_size,
|
|||||||
return pcpu_unit_size;
|
return pcpu_unit_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
|
||||||
|
[PCPU_FC_AUTO] = "auto",
|
||||||
|
[PCPU_FC_EMBED] = "embed",
|
||||||
|
[PCPU_FC_PAGE] = "page",
|
||||||
|
[PCPU_FC_LPAGE] = "lpage",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
|
||||||
|
|
||||||
|
static int __init percpu_alloc_setup(char *str)
|
||||||
|
{
|
||||||
|
if (0)
|
||||||
|
/* nada */;
|
||||||
|
#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||||
|
else if (!strcmp(str, "embed"))
|
||||||
|
pcpu_chosen_fc = PCPU_FC_EMBED;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||||
|
else if (!strcmp(str, "page"))
|
||||||
|
pcpu_chosen_fc = PCPU_FC_PAGE;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK
|
||||||
|
else if (!strcmp(str, "lpage"))
|
||||||
|
pcpu_chosen_fc = PCPU_FC_LPAGE;
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
pr_warning("PERCPU: unknown allocator %s specified\n", str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("percpu_alloc", percpu_alloc_setup);
|
||||||
|
|
||||||
static inline size_t pcpu_calc_fc_sizes(size_t static_size,
|
static inline size_t pcpu_calc_fc_sizes(size_t static_size,
|
||||||
size_t reserved_size,
|
size_t reserved_size,
|
||||||
ssize_t *dyn_sizep)
|
ssize_t *dyn_sizep)
|
||||||
|
Loading…
Reference in New Issue
Block a user