Commit f58dc01ba2ca9fe3ab2ba4ca43d9c8a735cf62d8

Authored by Tejun Heo
1 parent 08fc458061

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);
... ... @@ -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)