diff options
-rw-r--r-- | arch/powerpc/include/asm/smp.h | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 59 |
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() |
146 | static inline void inhibit_secondary_onlining(void) {} | 146 | static inline void inhibit_secondary_onlining(void) {} |
147 | static inline void uninhibit_secondary_onlining(void) {} | 147 | static inline void uninhibit_secondary_onlining(void) {} |
148 | static 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 | */ |
1448 | int arch_update_cpu_topology(void) | 1450 | int 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); |