aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-02-21 00:49:58 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-01 00:37:25 -0400
commit62cc67b9df273be18fcb09a071592dedf751c90a (patch)
tree604363a8a8ea577b59c58e10ba7cf36a67ced624 /arch
parente872e41b79f61dbc22f85577613925a4a7de1c1a (diff)
powerpc/pmac/smp: Properly NAP offlined CPU on G5
The current code soft-disables, and then goes to NAP mode which turns interrupts on. That means that if an interrupt occurs, we will hit the masked interrupt code path which isn't what we want, as it will return with EE off, which will either get us out of NAP mode, or fail to enter it (according to spec). Instead, let's just rely on the fact that it is safe to take decrementer interrupts on an offline CPU and leave interrupts enabled. We can also get rid of the special case in asm for power4_cpu_offline_powersave() and just use power4_idle(). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/machdep.h1
-rw-r--r--arch/powerpc/kernel/head_64.S7
-rw-r--r--arch/powerpc/kernel/idle_power4.S21
-rw-r--r--arch/powerpc/platforms/powermac/smp.c14
4 files changed, 15 insertions, 28 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index bcfc0da2cef1..578d3309e109 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -266,7 +266,6 @@ struct machdep_calls {
266 266
267extern void e500_idle(void); 267extern void e500_idle(void);
268extern void power4_idle(void); 268extern void power4_idle(void);
269extern void power4_cpu_offline_powersave(void);
270extern void ppc6xx_idle(void); 269extern void ppc6xx_idle(void);
271extern void book3e_idle(void); 270extern void book3e_idle(void);
272 271
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 782f23df7c85..271140b38b6f 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -536,6 +536,13 @@ _GLOBAL(pmac_secondary_start)
536 add r13,r13,r4 /* for this processor. */ 536 add r13,r13,r4 /* for this processor. */
537 mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ 537 mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/
538 538
539 /* Mark interrupts soft and hard disabled (they might be enabled
540 * in the PACA when doing hotplug)
541 */
542 li r0,0
543 stb r0,PACASOFTIRQEN(r13)
544 stb r0,PACAHARDIRQEN(r13)
545
539 /* Create a temp kernel stack for use before relocation is on. */ 546 /* Create a temp kernel stack for use before relocation is on. */
540 ld r1,PACAEMERGSP(r13) 547 ld r1,PACAEMERGSP(r13)
541 subi r1,r1,STACK_FRAME_OVERHEAD 548 subi r1,r1,STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 5328709eeedc..ba3195478600 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -53,24 +53,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
53 isync 53 isync
54 b 1b 54 b 1b
55 55
56_GLOBAL(power4_cpu_offline_powersave)
57 /* Go to NAP now */
58 mfmsr r7
59 rldicl r0,r7,48,1
60 rotldi r0,r0,16
61 mtmsrd r0,1 /* hard-disable interrupts */
62 li r0,1
63 li r6,0
64 stb r0,PACAHARDIRQEN(r13) /* we'll hard-enable shortly */
65 stb r6,PACASOFTIRQEN(r13) /* soft-disable irqs */
66BEGIN_FTR_SECTION
67 DSSALL
68 sync
69END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
70 ori r7,r7,MSR_EE
71 oris r7,r7,MSR_POW@h
72 sync
73 isync
74 mtmsrd r7
75 isync
76 blr
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 53bee660ff3d..837989e72ca1 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -916,18 +916,20 @@ static void pmac_cpu_die(void)
916 preempt_enable(); 916 preempt_enable();
917 917
918 /* 918 /*
919 * hard-disable interrupts for the non-NAP case, the NAP code 919 * Re-enable interrupts. The NAP code needs to enable them
920 * needs to re-enable interrupts (but soft-disables them) 920 * anyways, do it now so we deal with the case where one already
921 * happened while soft-disabled.
922 * We shouldn't get any external interrupts, only decrementer, and the
923 * decrementer handler is safe for use on offline CPUs
921 */ 924 */
922 hard_irq_disable(); 925 local_irq_enable();
923 926
924 while (1) { 927 while (1) {
925 /* let's not take timer interrupts too often ... */ 928 /* let's not take timer interrupts too often ... */
926 set_dec(0x7fffffff); 929 set_dec(0x7fffffff);
927 930
928 /* should always be true at this point */ 931 /* Enter NAP mode */
929 if (cpu_has_feature(CPU_FTR_CAN_NAP)) 932 power4_idle();
930 power4_cpu_offline_powersave();
931 } 933 }
932} 934}
933 935