Apply new interface to map external powerpc cpus across multiple nodes to a range of kernel cpu values. Mapping is intended to prevent confusion within the kernel about the cpu+node mapping, and the changes in configuration that may happen due to powerpc LPAR migration or other associativity changes during the lifetime of a system. These interfaces exchange the thread_index provided by the 'ibm,ppc-interrupt-server#s' properties, for an internal index to be used by kernel scheduling interfaces.
Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com> --- arch/powerpc/mm/numa.c | 45 +++++++++++++++++--------- arch/powerpc/platforms/pseries/hotplug-cpu.c | 15 +++++++-- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 460d60f..9825fc9 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1063,7 +1063,8 @@ u64 memory_hotplug_max(void) struct topology_update_data { struct topology_update_data *next; - unsigned int cpu; + unsigned int old_cpu; + unsigned int new_cpu; int old_nid; int new_nid; }; @@ -1253,13 +1254,13 @@ static int update_cpu_topology(void *data) for (update = data; update; update = update->next) { int new_nid = update->new_nid; - if (cpu != update->cpu) + if (cpu != update->new_cpu) continue; - unmap_cpu_from_node(cpu); - map_cpu_to_node(cpu, new_nid); - set_cpu_numa_node(cpu, new_nid); - set_cpu_numa_mem(cpu, local_memory_node(new_nid)); + unmap_cpu_from_node(update->old_cpu); + map_cpu_to_node(update->new_cpu, new_nid); + set_cpu_numa_node(update->new_cpu, new_nid); + set_cpu_numa_mem(update->new_cpu, local_memory_node(new_nid)); vdso_getcpu_init(); } @@ -1283,7 +1284,7 @@ static int update_lookup_table(void *data) int nid, base, j; nid = update->new_nid; - base = cpu_first_thread_sibling(update->cpu); + base = cpu_first_thread_sibling(update->new_cpu); for (j = 0; j < threads_per_core; j++) { update_numa_cpu_lookup_table(base + j, nid); @@ -1305,7 +1306,7 @@ int numa_update_cpu_topology(bool cpus_locked) struct topology_update_data *updates, *ud; cpumask_t updated_cpus; struct device *dev; - int weight, new_nid, i = 0; + int weight, new_nid, i = 0, ii; if (!prrn_enabled && !vphn_enabled && topology_inited) return 0; @@ -1349,12 +1350,16 @@ int numa_update_cpu_topology(bool cpus_locked) continue; } + ii = 0; for_each_cpu(sibling, cpu_sibling_mask(cpu)) { ud = &updates[i++]; ud->next = &updates[i]; - ud->cpu = sibling; ud->new_nid = new_nid; ud->old_nid = numa_cpu_lookup_table[sibling]; + ud->old_cpu = sibling; + ud->new_cpu = cpuremap_map_cpu( + get_hard_smp_processor_id(sibling), + ii++, new_nid); cpumask_set_cpu(sibling, &updated_cpus); } cpu = cpu_last_thread_sibling(cpu); @@ -1370,9 +1375,10 @@ int numa_update_cpu_topology(bool cpus_locked) pr_debug("Topology update for the following CPUs:\n"); if (cpumask_weight(&updated_cpus)) { for (ud = &updates[0]; ud; ud = ud->next) { - pr_debug("cpu %d moving from node %d " - "to %d\n", ud->cpu, - ud->old_nid, ud->new_nid); + pr_debug("cpu %d, node %d moving to" + " cpu %d, node %d\n", + ud->old_cpu, ud->old_nid, + ud->new_cpu, ud->new_nid); } } @@ -1409,13 +1415,20 @@ int numa_update_cpu_topology(bool cpus_locked) cpumask_of(raw_smp_processor_id())); for (ud = &updates[0]; ud; ud = ud->next) { - unregister_cpu_under_node(ud->cpu, ud->old_nid); - register_cpu_under_node(ud->cpu, ud->new_nid); + unregister_cpu_under_node(ud->old_cpu, ud->old_nid); + register_cpu_under_node(ud->new_cpu, ud->new_nid); - dev = get_cpu_device(ud->cpu); + dev = get_cpu_device(ud->old_cpu); if (dev) kobject_uevent(&dev->kobj, KOBJ_CHANGE); - cpumask_clear_cpu(ud->cpu, &cpu_associativity_changes_mask); + cpumask_clear_cpu(ud->old_cpu, &cpu_associativity_changes_mask); + if (ud->old_cpu != ud->new_cpu) { + dev = get_cpu_device(ud->new_cpu); + if (dev) + kobject_uevent(&dev->kobj, KOBJ_CHANGE); + cpumask_clear_cpu(ud->new_cpu, + &cpu_associativity_changes_mask); + } changed = 1; } diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 620cb57..3a11a31 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -259,8 +259,13 @@ static int pseries_add_processor(struct device_node *np) zalloc_cpumask_var(&tmp, GFP_KERNEL); nthreads = len / sizeof(u32); - for (i = 0; i < nthreads; i++) - cpumask_set_cpu(i, tmp); + for (i = 0; i < nthreads; i++) { + int thread_index = be32_to_cpu(intserv[i]); + int nid = find_and_online_cpu_nid(thread_index, false); + int cpu = cpuremap_map_cpu(thread_index, i, nid); + cpumask_set_cpu(cpu, tmp); + cpuremap_reserve_cpu(cpu); + } cpu_maps_update_begin(); @@ -333,6 +338,7 @@ static void pseries_remove_processor(struct device_node *np) set_cpu_present(cpu, false); set_hard_smp_processor_id(cpu, -1); update_numa_cpu_lookup_table(cpu, -1); + cpuremap_release_cpu(cpu); break; } if (cpu >= nr_cpu_ids) @@ -346,7 +352,7 @@ static int dlpar_online_cpu(struct device_node *dn) { int rc = 0; unsigned int cpu; - int len, nthreads, i; + int len, nthreads, i, nid; const __be32 *intserv; u32 thread; @@ -367,9 +373,11 @@ static int dlpar_online_cpu(struct device_node *dn) cpu_maps_update_done(); timed_topology_update(1); find_and_online_cpu_nid(cpu, true); + cpuremap_map_cpu(thread, i, nid); rc = device_online(get_cpu_device(cpu)); if (rc) goto out; + cpuremap_reserve_cpu(cpu); cpu_maps_update_begin(); break; @@ -541,6 +549,7 @@ static int dlpar_offline_cpu(struct device_node *dn) rc = device_offline(get_cpu_device(cpu)); if (rc) goto out; + cpuremap_release_cpu(cpu); cpu_maps_update_begin(); break;