diff options
Diffstat (limited to 'arch/powerpc/mm/numa.c')
-rw-r--r-- | arch/powerpc/mm/numa.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 3b181b22cd46..b9d1dfdbe5bb 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | #define pr_fmt(fmt) "numa: " fmt | ||
12 | |||
11 | #include <linux/threads.h> | 13 | #include <linux/threads.h> |
12 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
@@ -538,7 +540,7 @@ static int of_drconf_to_nid_single(struct of_drconf_cell *drmem, | |||
538 | */ | 540 | */ |
539 | static int numa_setup_cpu(unsigned long lcpu) | 541 | static int numa_setup_cpu(unsigned long lcpu) |
540 | { | 542 | { |
541 | int nid; | 543 | int nid = -1; |
542 | struct device_node *cpu; | 544 | struct device_node *cpu; |
543 | 545 | ||
544 | /* | 546 | /* |
@@ -555,19 +557,21 @@ static int numa_setup_cpu(unsigned long lcpu) | |||
555 | 557 | ||
556 | if (!cpu) { | 558 | if (!cpu) { |
557 | WARN_ON(1); | 559 | WARN_ON(1); |
558 | nid = 0; | 560 | if (cpu_present(lcpu)) |
559 | goto out; | 561 | goto out_present; |
562 | else | ||
563 | goto out; | ||
560 | } | 564 | } |
561 | 565 | ||
562 | nid = of_node_to_nid_single(cpu); | 566 | nid = of_node_to_nid_single(cpu); |
563 | 567 | ||
568 | out_present: | ||
564 | if (nid < 0 || !node_online(nid)) | 569 | if (nid < 0 || !node_online(nid)) |
565 | nid = first_online_node; | 570 | nid = first_online_node; |
566 | out: | ||
567 | map_cpu_to_node(lcpu, nid); | ||
568 | 571 | ||
572 | map_cpu_to_node(lcpu, nid); | ||
569 | of_node_put(cpu); | 573 | of_node_put(cpu); |
570 | 574 | out: | |
571 | return nid; | 575 | return nid; |
572 | } | 576 | } |
573 | 577 | ||
@@ -611,8 +615,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, | |||
611 | case CPU_UP_CANCELED: | 615 | case CPU_UP_CANCELED: |
612 | case CPU_UP_CANCELED_FROZEN: | 616 | case CPU_UP_CANCELED_FROZEN: |
613 | unmap_cpu_from_node(lcpu); | 617 | unmap_cpu_from_node(lcpu); |
614 | break; | ||
615 | ret = NOTIFY_OK; | 618 | ret = NOTIFY_OK; |
619 | break; | ||
616 | #endif | 620 | #endif |
617 | } | 621 | } |
618 | return ret; | 622 | return ret; |
@@ -1049,7 +1053,7 @@ static void __init mark_reserved_regions_for_nid(int nid) | |||
1049 | 1053 | ||
1050 | void __init do_init_bootmem(void) | 1054 | void __init do_init_bootmem(void) |
1051 | { | 1055 | { |
1052 | int nid; | 1056 | int nid, cpu; |
1053 | 1057 | ||
1054 | min_low_pfn = 0; | 1058 | min_low_pfn = 0; |
1055 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; | 1059 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; |
@@ -1122,16 +1126,14 @@ void __init do_init_bootmem(void) | |||
1122 | 1126 | ||
1123 | reset_numa_cpu_lookup_table(); | 1127 | reset_numa_cpu_lookup_table(); |
1124 | register_cpu_notifier(&ppc64_numa_nb); | 1128 | register_cpu_notifier(&ppc64_numa_nb); |
1125 | cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, | 1129 | /* |
1126 | (void *)(unsigned long)boot_cpuid); | 1130 | * We need the numa_cpu_lookup_table to be accurate for all CPUs, |
1127 | } | 1131 | * even before we online them, so that we can use cpu_to_{node,mem} |
1128 | 1132 | * early in boot, cf. smp_prepare_cpus(). | |
1129 | void __init paging_init(void) | 1133 | */ |
1130 | { | 1134 | for_each_present_cpu(cpu) { |
1131 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 1135 | numa_setup_cpu((unsigned long)cpu); |
1132 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 1136 | } |
1133 | max_zone_pfns[ZONE_DMA] = memblock_end_of_DRAM() >> PAGE_SHIFT; | ||
1134 | free_area_init_nodes(max_zone_pfns); | ||
1135 | } | 1137 | } |
1136 | 1138 | ||
1137 | static int __init early_numa(char *p) | 1139 | static int __init early_numa(char *p) |
@@ -1153,6 +1155,22 @@ static int __init early_numa(char *p) | |||
1153 | } | 1155 | } |
1154 | early_param("numa", early_numa); | 1156 | early_param("numa", early_numa); |
1155 | 1157 | ||
1158 | static bool topology_updates_enabled = true; | ||
1159 | |||
1160 | static int __init early_topology_updates(char *p) | ||
1161 | { | ||
1162 | if (!p) | ||
1163 | return 0; | ||
1164 | |||
1165 | if (!strcmp(p, "off")) { | ||
1166 | pr_info("Disabling topology updates\n"); | ||
1167 | topology_updates_enabled = false; | ||
1168 | } | ||
1169 | |||
1170 | return 0; | ||
1171 | } | ||
1172 | early_param("topology_updates", early_topology_updates); | ||
1173 | |||
1156 | #ifdef CONFIG_MEMORY_HOTPLUG | 1174 | #ifdef CONFIG_MEMORY_HOTPLUG |
1157 | /* | 1175 | /* |
1158 | * Find the node associated with a hot added memory section for | 1176 | * Find the node associated with a hot added memory section for |
@@ -1442,8 +1460,11 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity) | |||
1442 | long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; | 1460 | long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; |
1443 | u64 flags = 1; | 1461 | u64 flags = 1; |
1444 | int hwcpu = get_hard_smp_processor_id(cpu); | 1462 | int hwcpu = get_hard_smp_processor_id(cpu); |
1463 | int i; | ||
1445 | 1464 | ||
1446 | rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu); | 1465 | rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu); |
1466 | for (i = 0; i < 6; i++) | ||
1467 | retbuf[i] = cpu_to_be64(retbuf[i]); | ||
1447 | vphn_unpack_associativity(retbuf, associativity); | 1468 | vphn_unpack_associativity(retbuf, associativity); |
1448 | 1469 | ||
1449 | return rc; | 1470 | return rc; |
@@ -1488,11 +1509,14 @@ static int update_cpu_topology(void *data) | |||
1488 | cpu = smp_processor_id(); | 1509 | cpu = smp_processor_id(); |
1489 | 1510 | ||
1490 | for (update = data; update; update = update->next) { | 1511 | for (update = data; update; update = update->next) { |
1512 | int new_nid = update->new_nid; | ||
1491 | if (cpu != update->cpu) | 1513 | if (cpu != update->cpu) |
1492 | continue; | 1514 | continue; |
1493 | 1515 | ||
1494 | unmap_cpu_from_node(update->cpu); | 1516 | unmap_cpu_from_node(cpu); |
1495 | map_cpu_to_node(update->cpu, update->new_nid); | 1517 | map_cpu_to_node(cpu, new_nid); |
1518 | set_cpu_numa_node(cpu, new_nid); | ||
1519 | set_cpu_numa_mem(cpu, local_memory_node(new_nid)); | ||
1496 | vdso_getcpu_init(); | 1520 | vdso_getcpu_init(); |
1497 | } | 1521 | } |
1498 | 1522 | ||
@@ -1539,6 +1563,9 @@ int arch_update_cpu_topology(void) | |||
1539 | struct device *dev; | 1563 | struct device *dev; |
1540 | int weight, new_nid, i = 0; | 1564 | int weight, new_nid, i = 0; |
1541 | 1565 | ||
1566 | if (!prrn_enabled && !vphn_enabled) | ||
1567 | return 0; | ||
1568 | |||
1542 | weight = cpumask_weight(&cpu_associativity_changes_mask); | 1569 | weight = cpumask_weight(&cpu_associativity_changes_mask); |
1543 | if (!weight) | 1570 | if (!weight) |
1544 | return 0; | 1571 | return 0; |
@@ -1592,6 +1619,15 @@ int arch_update_cpu_topology(void) | |||
1592 | cpu = cpu_last_thread_sibling(cpu); | 1619 | cpu = cpu_last_thread_sibling(cpu); |
1593 | } | 1620 | } |
1594 | 1621 | ||
1622 | pr_debug("Topology update for the following CPUs:\n"); | ||
1623 | if (cpumask_weight(&updated_cpus)) { | ||
1624 | for (ud = &updates[0]; ud; ud = ud->next) { | ||
1625 | pr_debug("cpu %d moving from node %d " | ||
1626 | "to %d\n", ud->cpu, | ||
1627 | ud->old_nid, ud->new_nid); | ||
1628 | } | ||
1629 | } | ||
1630 | |||
1595 | /* | 1631 | /* |
1596 | * In cases where we have nothing to update (because the updates list | 1632 | * In cases where we have nothing to update (because the updates list |
1597 | * is too short or because the new topology is same as the old one), | 1633 | * is too short or because the new topology is same as the old one), |
@@ -1800,8 +1836,12 @@ static const struct file_operations topology_ops = { | |||
1800 | 1836 | ||
1801 | static int topology_update_init(void) | 1837 | static int topology_update_init(void) |
1802 | { | 1838 | { |
1803 | start_topology_update(); | 1839 | /* Do not poll for changes if disabled at boot */ |
1804 | proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops); | 1840 | if (topology_updates_enabled) |
1841 | start_topology_update(); | ||
1842 | |||
1843 | if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops)) | ||
1844 | return -ENOMEM; | ||
1805 | 1845 | ||
1806 | return 0; | 1846 | return 0; |
1807 | } | 1847 | } |