aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/numa.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/numa.c')
-rw-r--r--arch/powerpc/mm/numa.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 08397217e8ac..5850798826cd 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>
@@ -1318,7 +1319,8 @@ static int update_cpu_associativity_changes_mask(void)
1318 } 1319 }
1319 } 1320 }
1320 if (changed) { 1321 if (changed) {
1321 cpumask_set_cpu(cpu, changes); 1322 cpumask_or(changes, changes, cpu_sibling_mask(cpu));
1323 cpu = cpu_last_thread_sibling(cpu);
1322 } 1324 }
1323 } 1325 }
1324 1326
@@ -1426,7 +1428,7 @@ static int update_cpu_topology(void *data)
1426 if (!data) 1428 if (!data)
1427 return -EINVAL; 1429 return -EINVAL;
1428 1430
1429 cpu = get_cpu(); 1431 cpu = smp_processor_id();
1430 1432
1431 for (update = data; update; update = update->next) { 1433 for (update = data; update; update = update->next) {
1432 if (cpu != update->cpu) 1434 if (cpu != update->cpu)
@@ -1446,12 +1448,12 @@ static int update_cpu_topology(void *data)
1446 */ 1448 */
1447int arch_update_cpu_topology(void) 1449int arch_update_cpu_topology(void)
1448{ 1450{
1449 unsigned int cpu, changed = 0; 1451 unsigned int cpu, sibling, changed = 0;
1450 struct topology_update_data *updates, *ud; 1452 struct topology_update_data *updates, *ud;
1451 unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; 1453 unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
1452 cpumask_t updated_cpus; 1454 cpumask_t updated_cpus;
1453 struct device *dev; 1455 struct device *dev;
1454 int weight, i = 0; 1456 int weight, new_nid, i = 0;
1455 1457
1456 weight = cpumask_weight(&cpu_associativity_changes_mask); 1458 weight = cpumask_weight(&cpu_associativity_changes_mask);
1457 if (!weight) 1459 if (!weight)
@@ -1464,19 +1466,46 @@ int arch_update_cpu_topology(void)
1464 cpumask_clear(&updated_cpus); 1466 cpumask_clear(&updated_cpus);
1465 1467
1466 for_each_cpu(cpu, &cpu_associativity_changes_mask) { 1468 for_each_cpu(cpu, &cpu_associativity_changes_mask) {
1467 ud = &updates[i++]; 1469 /*
1468 ud->cpu = cpu; 1470 * If siblings aren't flagged for changes, updates list
1469 vphn_get_associativity(cpu, associativity); 1471 * will be too short. Skip on this update and set for next
1470 ud->new_nid = associativity_to_nid(associativity); 1472 * update.
1471 1473 */
1472 if (ud->new_nid < 0 || !node_online(ud->new_nid)) 1474 if (!cpumask_subset(cpu_sibling_mask(cpu),
1473 ud->new_nid = first_online_node; 1475 &cpu_associativity_changes_mask)) {
1476 pr_info("Sibling bits not set for associativity "
1477 "change, cpu%d\n", cpu);
1478 cpumask_or(&cpu_associativity_changes_mask,
1479 &cpu_associativity_changes_mask,
1480 cpu_sibling_mask(cpu));
1481 cpu = cpu_last_thread_sibling(cpu);
1482 continue;
1483 }
1474 1484
1475 ud->old_nid = numa_cpu_lookup_table[cpu]; 1485 /* Use associativity from first thread for all siblings */
1476 cpumask_set_cpu(cpu, &updated_cpus); 1486 vphn_get_associativity(cpu, associativity);
1487 new_nid = associativity_to_nid(associativity);
1488 if (new_nid < 0 || !node_online(new_nid))
1489 new_nid = first_online_node;
1490
1491 if (new_nid == numa_cpu_lookup_table[cpu]) {
1492 cpumask_andnot(&cpu_associativity_changes_mask,
1493 &cpu_associativity_changes_mask,
1494 cpu_sibling_mask(cpu));
1495 cpu = cpu_last_thread_sibling(cpu);
1496 continue;
1497 }
1477 1498
1478 if (i < weight) 1499 for_each_cpu(sibling, cpu_sibling_mask(cpu)) {
1479 ud->next = &updates[i]; 1500 ud = &updates[i++];
1501 ud->cpu = sibling;
1502 ud->new_nid = new_nid;
1503 ud->old_nid = numa_cpu_lookup_table[sibling];
1504 cpumask_set_cpu(sibling, &updated_cpus);
1505 if (i < weight)
1506 ud->next = &updates[i];
1507 }
1508 cpu = cpu_last_thread_sibling(cpu);
1480 } 1509 }
1481 1510
1482 stop_machine(update_cpu_topology, &updates[0], &updated_cpus); 1511 stop_machine(update_cpu_topology, &updates[0], &updated_cpus);