diff options
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 12 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 59 |
2 files changed, 54 insertions, 17 deletions
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 3f0c30ae4791..c33d939120c9 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -43,6 +43,7 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
43 | { | 43 | { |
44 | unsigned long va; | 44 | unsigned long va; |
45 | unsigned int penc; | 45 | unsigned int penc; |
46 | unsigned long sllp; | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * We need 14 to 65 bits of va for a tlibe of 4K page | 49 | * We need 14 to 65 bits of va for a tlibe of 4K page |
@@ -64,7 +65,9 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
64 | /* clear out bits after (52) [0....52.....63] */ | 65 | /* clear out bits after (52) [0....52.....63] */ |
65 | va &= ~((1ul << (64 - 52)) - 1); | 66 | va &= ~((1ul << (64 - 52)) - 1); |
66 | va |= ssize << 8; | 67 | va |= ssize << 8; |
67 | va |= mmu_psize_defs[apsize].sllp << 6; | 68 | sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) | |
69 | ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4); | ||
70 | va |= sllp << 5; | ||
68 | asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2) | 71 | asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2) |
69 | : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206) | 72 | : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206) |
70 | : "memory"); | 73 | : "memory"); |
@@ -98,6 +101,7 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) | |||
98 | { | 101 | { |
99 | unsigned long va; | 102 | unsigned long va; |
100 | unsigned int penc; | 103 | unsigned int penc; |
104 | unsigned long sllp; | ||
101 | 105 | ||
102 | /* VPN_SHIFT can be atmost 12 */ | 106 | /* VPN_SHIFT can be atmost 12 */ |
103 | va = vpn << VPN_SHIFT; | 107 | va = vpn << VPN_SHIFT; |
@@ -113,7 +117,9 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) | |||
113 | /* clear out bits after(52) [0....52.....63] */ | 117 | /* clear out bits after(52) [0....52.....63] */ |
114 | va &= ~((1ul << (64 - 52)) - 1); | 118 | va &= ~((1ul << (64 - 52)) - 1); |
115 | va |= ssize << 8; | 119 | va |= ssize << 8; |
116 | va |= mmu_psize_defs[apsize].sllp << 6; | 120 | sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) | |
121 | ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4); | ||
122 | va |= sllp << 5; | ||
117 | asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" | 123 | asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" |
118 | : : "r"(va) : "memory"); | 124 | : : "r"(va) : "memory"); |
119 | break; | 125 | break; |
@@ -554,6 +560,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
554 | seg_off |= vpi << shift; | 560 | seg_off |= vpi << shift; |
555 | } | 561 | } |
556 | *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT; | 562 | *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT; |
563 | break; | ||
557 | case MMU_SEGSIZE_1T: | 564 | case MMU_SEGSIZE_1T: |
558 | /* We only have 40 - 23 bits of seg_off in avpn */ | 565 | /* We only have 40 - 23 bits of seg_off in avpn */ |
559 | seg_off = (avpn & 0x1ffff) << 23; | 566 | seg_off = (avpn & 0x1ffff) << 23; |
@@ -563,6 +570,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
563 | seg_off |= vpi << shift; | 570 | seg_off |= vpi << shift; |
564 | } | 571 | } |
565 | *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT; | 572 | *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT; |
573 | break; | ||
566 | default: | 574 | default: |
567 | *vpn = size = 0; | 575 | *vpn = size = 0; |
568 | } | 576 | } |
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 | */ |
1447 | int arch_update_cpu_topology(void) | 1449 | int 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); |