diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/Kconfig | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/smp_64.c | 53 |
2 files changed, 47 insertions, 9 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 97fca4695e0b..ac45aab741a5 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -102,6 +102,9 @@ config HAVE_SETUP_PER_CPU_AREA | |||
102 | config NEED_PER_CPU_EMBED_FIRST_CHUNK | 102 | config NEED_PER_CPU_EMBED_FIRST_CHUNK |
103 | def_bool y if SPARC64 | 103 | def_bool y if SPARC64 |
104 | 104 | ||
105 | config NEED_PER_CPU_PAGE_FIRST_CHUNK | ||
106 | def_bool y if SPARC64 | ||
107 | |||
105 | config GENERIC_HARDIRQS_NO__DO_IRQ | 108 | config GENERIC_HARDIRQS_NO__DO_IRQ |
106 | bool | 109 | bool |
107 | def_bool y if SPARC64 | 110 | def_bool y if SPARC64 |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index ff68373ce6d6..aa36223497b9 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -1420,7 +1420,7 @@ static void __init pcpu_free_bootmem(void *ptr, size_t size) | |||
1420 | free_bootmem(__pa(ptr), size); | 1420 | free_bootmem(__pa(ptr), size); |
1421 | } | 1421 | } |
1422 | 1422 | ||
1423 | static int pcpu_cpu_distance(unsigned int from, unsigned int to) | 1423 | static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) |
1424 | { | 1424 | { |
1425 | if (cpu_to_node(from) == cpu_to_node(to)) | 1425 | if (cpu_to_node(from) == cpu_to_node(to)) |
1426 | return LOCAL_DISTANCE; | 1426 | return LOCAL_DISTANCE; |
@@ -1428,18 +1428,53 @@ static int pcpu_cpu_distance(unsigned int from, unsigned int to) | |||
1428 | return REMOTE_DISTANCE; | 1428 | return REMOTE_DISTANCE; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | static void __init pcpu_populate_pte(unsigned long addr) | ||
1432 | { | ||
1433 | pgd_t *pgd = pgd_offset_k(addr); | ||
1434 | pud_t *pud; | ||
1435 | pmd_t *pmd; | ||
1436 | |||
1437 | pud = pud_offset(pgd, addr); | ||
1438 | if (pud_none(*pud)) { | ||
1439 | pmd_t *new; | ||
1440 | |||
1441 | new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); | ||
1442 | pud_populate(&init_mm, pud, new); | ||
1443 | } | ||
1444 | |||
1445 | pmd = pmd_offset(pud, addr); | ||
1446 | if (!pmd_present(*pmd)) { | ||
1447 | pte_t *new; | ||
1448 | |||
1449 | new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); | ||
1450 | pmd_populate_kernel(&init_mm, pmd, new); | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1431 | void __init setup_per_cpu_areas(void) | 1454 | void __init setup_per_cpu_areas(void) |
1432 | { | 1455 | { |
1433 | unsigned long delta; | 1456 | unsigned long delta; |
1434 | unsigned int cpu; | 1457 | unsigned int cpu; |
1435 | int rc; | 1458 | int rc = -EINVAL; |
1436 | 1459 | ||
1437 | rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE, | 1460 | if (pcpu_chosen_fc != PCPU_FC_PAGE) { |
1438 | PERCPU_DYNAMIC_RESERVE, 4 << 20, | 1461 | rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE, |
1439 | pcpu_cpu_distance, pcpu_alloc_bootmem, | 1462 | PERCPU_DYNAMIC_RESERVE, 4 << 20, |
1440 | pcpu_free_bootmem); | 1463 | pcpu_cpu_distance, |
1441 | if (rc) | 1464 | pcpu_alloc_bootmem, |
1442 | panic("failed to initialize first chunk (%d)", rc); | 1465 | pcpu_free_bootmem); |
1466 | if (rc) | ||
1467 | pr_warning("PERCPU: %s allocator failed (%d), " | ||
1468 | "falling back to page size\n", | ||
1469 | pcpu_fc_names[pcpu_chosen_fc], rc); | ||
1470 | } | ||
1471 | if (rc < 0) | ||
1472 | rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE, | ||
1473 | pcpu_alloc_bootmem, | ||
1474 | pcpu_free_bootmem, | ||
1475 | pcpu_populate_pte); | ||
1476 | if (rc < 0) | ||
1477 | panic("cannot initialize percpu area (err=%d)", rc); | ||
1443 | 1478 | ||
1444 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; | 1479 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; |
1445 | for_each_possible_cpu(cpu) | 1480 | for_each_possible_cpu(cpu) |