aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/smp.h4
-rw-r--r--arch/powerpc/mm/numa.c59
2 files changed, 48 insertions, 15 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index ffbaabebcdca..48cfc858abd6 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -145,6 +145,10 @@ extern void __cpu_die(unsigned int cpu);
145#define smp_setup_cpu_maps() 145#define smp_setup_cpu_maps()
146static inline void inhibit_secondary_onlining(void) {} 146static inline void inhibit_secondary_onlining(void) {}
147static inline void uninhibit_secondary_onlining(void) {} 147static inline void uninhibit_secondary_onlining(void) {}
148static inline const struct cpumask *cpu_sibling_mask(int cpu)
149{
150 return cpumask_of(cpu);
151}
148 152
149#endif /* CONFIG_SMP */ 153#endif /* CONFIG_SMP */
150 154
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 2859a1f52279..cafad4017765 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -27,6 +27,7 @@
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <asm/cputhreads.h>
30#include <asm/sparsemem.h> 31#include <asm/sparsemem.h>
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/smp.h> 33#include <asm/smp.h>
@@ -1319,7 +1320,8 @@ static int update_cpu_associativity_changes_mask(void)
1319 } 1320 }
1320 } 1321 }
1321 if (changed) { 1322 if (changed) {
1322 cpumask_set_cpu(cpu, changes); 1323 cpumask_or(changes, changes, cpu_sibling_mask(cpu));
1324 cpu = cpu_last_thread_sibling(cpu);
1323 } 1325 }
1324 } 1326 }
1325 1327
@@ -1427,7 +1429,7 @@ static int update_cpu_topology(void *data)
1427 if (!data) 1429 if (!data)
1428 return -EINVAL; 1430 return -EINVAL;
1429 1431
1430 cpu = get_cpu(); 1432 cpu = smp_processor_id();
1431 1433
1432 for (update = data; update; update = update->next) { 1434 for (update = data; update; update = update->next) {
1433 if (cpu != update->cpu) 1435 if (cpu != update->cpu)
@@ -1447,12 +1449,12 @@ static int update_cpu_topology(void *data)
1447 */ 1449 */
1448int arch_update_cpu_topology(void) 1450int arch_update_cpu_topology(void)
1449{ 1451{
1450 unsigned int cpu, changed = 0; 1452 unsigned int cpu, sibling, changed = 0;
1451 struct topology_update_data *updates, *ud; 1453 struct topology_update_data *updates, *ud;
1452 unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; 1454 unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
1453 cpumask_t updated_cpus; 1455 cpumask_t updated_cpus;
1454 struct device *dev; 1456 struct device *dev;
1455 int weight, i = 0; 1457 int weight, new_nid, i = 0;
1456 1458
1457 weight = cpumask_weight(&cpu_associativity_changes_mask); 1459 weight = cpumask_weight(&cpu_associativity_changes_mask);
1458 if (!weight) 1460 if (!weight)
@@ -1465,19 +1467,46 @@ int arch_update_cpu_topology(void)
1465 cpumask_clear(&updated_cpus); 1467 cpumask_clear(&updated_cpus);
1466 1468
1467 for_each_cpu(cpu, &cpu_associativity_changes_mask) { 1469 for_each_cpu(cpu, &cpu_associativity_changes_mask) {
1468 ud = &updates[i++]; 1470 /*
1469 ud->cpu = cpu; 1471 * If siblings aren't flagged for changes, updates list
1470 vphn_get_associativity(cpu, associativity); 1472 * will be too short. Skip on this update and set for next
1471 ud->new_nid = associativity_to_nid(associativity); 1473 * update.
1472 1474 */
1473 if (ud->new_nid < 0 || !node_online(ud->new_nid)) 1475 if (!cpumask_subset(cpu_sibling_mask(cpu),
1474 ud->new_nid = first_online_node; 1476 &cpu_associativity_changes_mask)) {
1477 pr_info("Sibling bits not set for associativity "
1478 "change, cpu%d\n", cpu);
1479 cpumask_or(&cpu_associativity_changes_mask,
1480 &cpu_associativity_changes_mask,
1481 cpu_sibling_mask(cpu));
1482 cpu = cpu_last_thread_sibling(cpu);
1483 continue;
1484 }
1475 1485
1476 ud->old_nid = numa_cpu_lookup_table[cpu]; 1486 /* Use associativity from first thread for all siblings */
1477 cpumask_set_cpu(cpu, &updated_cpus); 1487 vphn_get_associativity(cpu, associativity);
1488 new_nid = associativity_to_nid(associativity);
1489 if (new_nid < 0 || !node_online(new_nid))
1490 new_nid = first_online_node;
1491
1492 if (new_nid == numa_cpu_lookup_table[cpu]) {
1493 cpumask_andnot(&cpu_associativity_changes_mask,
1494 &cpu_associativity_changes_mask,
1495 cpu_sibling_mask(cpu));
1496 cpu = cpu_last_thread_sibling(cpu);
1497 continue;
1498 }
1478 1499
1479 if (i < weight) 1500 for_each_cpu(sibling, cpu_sibling_mask(cpu)) {
1480 ud->next = &updates[i]; 1501 ud = &updates[i++];
1502 ud->cpu = sibling;
1503 ud->new_nid = new_nid;
1504 ud->old_nid = numa_cpu_lookup_table[sibling];
1505 cpumask_set_cpu(sibling, &updated_cpus);
1506 if (i < weight)
1507 ud->next = &updates[i];
1508 }
1509 cpu = cpu_last_thread_sibling(cpu);
1481 } 1510 }
1482 1511
1483 stop_machine(update_cpu_topology, &updates[0], &updated_cpus); 1512 stop_machine(update_cpu_topology, &updates[0], &updated_cpus);