Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f58dc01b authored by Tejun Heo's avatar Tejun Heo
Browse files

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: default avatarTejun Heo <tj@kernel.org>
parent 08fc4580
Loading
Loading
Loading
Loading
+6 −5
Original line number Original line Diff line number Diff line
@@ -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.
+6 −18
Original line number Original line Diff line number Diff line
@@ -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);
+12 −0
Original line number Original line Diff line number Diff line
@@ -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 −0
Original line number Original line Diff line number Diff line
@@ -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)