Commit f58dc01ba2ca9fe3ab2ba4ca43d9c8a735cf62d8
1 parent
08fc458061
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 56 additions and 23 deletions Side-by-side Diff
Documentation/kernel-parameters.txt
... | ... | @@ -1919,11 +1919,12 @@ |
1919 | 1919 | Format: { 0 | 1 } |
1920 | 1920 | See arch/parisc/kernel/pdc_chassis.c |
1921 | 1921 | |
1922 | - percpu_alloc= [X86] Select which percpu first chunk allocator to use. | |
1923 | - Allowed values are one of "lpage", "embed" and "page". | |
1924 | - See comments in arch/x86/kernel/setup_percpu.c for | |
1925 | - details on each allocator. This parameter is primarily | |
1926 | - for debugging and performance comparison. | |
1922 | + percpu_alloc= Select which percpu first chunk allocator to use. | |
1923 | + Currently supported values are "embed", "page" and | |
1924 | + "lpage". Archs may support subset or none of the | |
1925 | + selections. See comments in mm/percpu.c for details | |
1926 | + on each allocator. This parameter is primarily for | |
1927 | + debugging and performance comparison. | |
1927 | 1928 | |
1928 | 1929 | pf. [PARIDE] |
1929 | 1930 | See Documentation/blockdev/paride.txt. |
arch/x86/kernel/setup_percpu.c
... | ... | @@ -267,16 +267,6 @@ |
267 | 267 | pcpup_populate_pte); |
268 | 268 | } |
269 | 269 | |
270 | -/* for explicit first chunk allocator selection */ | |
271 | -static char pcpu_chosen_alloc[16] __initdata; | |
272 | - | |
273 | -static int __init percpu_alloc_setup(char *str) | |
274 | -{ | |
275 | - strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1); | |
276 | - return 0; | |
277 | -} | |
278 | -early_param("percpu_alloc", percpu_alloc_setup); | |
279 | - | |
280 | 270 | static inline void setup_percpu_segment(int cpu) |
281 | 271 | { |
282 | 272 | #ifdef CONFIG_X86_32 |
283 | 273 | |
284 | 274 | |
285 | 275 | |
... | ... | @@ -307,19 +297,17 @@ |
307 | 297 | * each allocator for details. |
308 | 298 | */ |
309 | 299 | ret = -EINVAL; |
310 | - if (strlen(pcpu_chosen_alloc)) { | |
311 | - if (strcmp(pcpu_chosen_alloc, "page")) { | |
312 | - if (!strcmp(pcpu_chosen_alloc, "lpage")) | |
300 | + if (pcpu_chosen_fc != PCPU_FC_AUTO) { | |
301 | + if (pcpu_chosen_fc != PCPU_FC_PAGE) { | |
302 | + if (pcpu_chosen_fc == PCPU_FC_LPAGE) | |
313 | 303 | ret = setup_pcpu_lpage(static_size, true); |
314 | - else if (!strcmp(pcpu_chosen_alloc, "embed")) | |
315 | - ret = setup_pcpu_embed(static_size, true); | |
316 | 304 | else |
317 | - pr_warning("PERCPU: unknown allocator %s " | |
318 | - "specified\n", pcpu_chosen_alloc); | |
305 | + ret = setup_pcpu_embed(static_size, true); | |
306 | + | |
319 | 307 | if (ret < 0) |
320 | 308 | pr_warning("PERCPU: %s allocator failed (%zd), " |
321 | 309 | "falling back to page size\n", |
322 | - pcpu_chosen_alloc, ret); | |
310 | + pcpu_fc_names[pcpu_chosen_fc], ret); | |
323 | 311 | } |
324 | 312 | } else { |
325 | 313 | ret = setup_pcpu_lpage(static_size, false); |
include/linux/percpu.h
... | ... | @@ -59,6 +59,18 @@ |
59 | 59 | extern void *pcpu_base_addr; |
60 | 60 | extern const int *pcpu_unit_map; |
61 | 61 | |
62 | +enum pcpu_fc { | |
63 | + PCPU_FC_AUTO, | |
64 | + PCPU_FC_EMBED, | |
65 | + PCPU_FC_PAGE, | |
66 | + PCPU_FC_LPAGE, | |
67 | + | |
68 | + PCPU_FC_NR, | |
69 | +}; | |
70 | +extern const char *pcpu_fc_names[PCPU_FC_NR]; | |
71 | + | |
72 | +extern enum pcpu_fc pcpu_chosen_fc; | |
73 | + | |
62 | 74 | typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size); |
63 | 75 | typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size); |
64 | 76 | typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr); |
mm/percpu.c
... | ... | @@ -1414,6 +1414,38 @@ |
1414 | 1414 | return pcpu_unit_size; |
1415 | 1415 | } |
1416 | 1416 | |
1417 | +const char *pcpu_fc_names[PCPU_FC_NR] __initdata = { | |
1418 | + [PCPU_FC_AUTO] = "auto", | |
1419 | + [PCPU_FC_EMBED] = "embed", | |
1420 | + [PCPU_FC_PAGE] = "page", | |
1421 | + [PCPU_FC_LPAGE] = "lpage", | |
1422 | +}; | |
1423 | + | |
1424 | +enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO; | |
1425 | + | |
1426 | +static int __init percpu_alloc_setup(char *str) | |
1427 | +{ | |
1428 | + if (0) | |
1429 | + /* nada */; | |
1430 | +#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK | |
1431 | + else if (!strcmp(str, "embed")) | |
1432 | + pcpu_chosen_fc = PCPU_FC_EMBED; | |
1433 | +#endif | |
1434 | +#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK | |
1435 | + else if (!strcmp(str, "page")) | |
1436 | + pcpu_chosen_fc = PCPU_FC_PAGE; | |
1437 | +#endif | |
1438 | +#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK | |
1439 | + else if (!strcmp(str, "lpage")) | |
1440 | + pcpu_chosen_fc = PCPU_FC_LPAGE; | |
1441 | +#endif | |
1442 | + else | |
1443 | + pr_warning("PERCPU: unknown allocator %s specified\n", str); | |
1444 | + | |
1445 | + return 0; | |
1446 | +} | |
1447 | +early_param("percpu_alloc", percpu_alloc_setup); | |
1448 | + | |
1417 | 1449 | static inline size_t pcpu_calc_fc_sizes(size_t static_size, |
1418 | 1450 | size_t reserved_size, |
1419 | 1451 | ssize_t *dyn_sizep) |