powerpc/pmac/smp: Properly NAP offlined CPU on G5
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 21 Feb 2011 05:49:58 +0000 (16:49 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 1 Apr 2011 04:37:25 +0000 (15:37 +1100)
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>
arch/powerpc/include/asm/machdep.h
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/idle_power4.S
arch/powerpc/platforms/powermac/smp.c

index bcfc0da2cef17c311b7f563c0d358850d1e8f14e..578d3309e1092c2e7c50dcb11b03dd8b24c33062 100644 (file)
@@ -266,7 +266,6 @@ struct machdep_calls {
 
 extern void e500_idle(void);
 extern void power4_idle(void);
-extern void power4_cpu_offline_powersave(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
 
index 782f23df7c85495714c85353ace0aca1d146a0cf..271140b38b6f9d5867c66b23bf6b6e4d6642314a 100644 (file)
@@ -536,6 +536,13 @@ _GLOBAL(pmac_secondary_start)
        add     r13,r13,r4              /* for this processor.          */
        mtspr   SPRN_SPRG_PACA,r13      /* Save vaddr of paca in an SPRG*/
 
+       /* Mark interrupts soft and hard disabled (they might be enabled
+        * in the PACA when doing hotplug)
+        */
+       li      r0,0
+       stb     r0,PACASOFTIRQEN(r13)
+       stb     r0,PACAHARDIRQEN(r13)
+
        /* Create a temp kernel stack for use before relocation is on.  */
        ld      r1,PACAEMERGSP(r13)
        subi    r1,r1,STACK_FRAME_OVERHEAD
index 5328709eeedcf952b3fa32445f8a6aea1c3e82cb..ba3195478600998a72bbdbabeaf7761963a435ed 100644 (file)
@@ -53,24 +53,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        isync
        b       1b
 
-_GLOBAL(power4_cpu_offline_powersave)
-       /* Go to NAP now */
-       mfmsr   r7
-       rldicl  r0,r7,48,1
-       rotldi  r0,r0,16
-       mtmsrd  r0,1                    /* hard-disable interrupts */
-       li      r0,1
-       li      r6,0
-       stb     r0,PACAHARDIRQEN(r13)   /* we'll hard-enable shortly */
-       stb     r6,PACASOFTIRQEN(r13)   /* soft-disable irqs */
-BEGIN_FTR_SECTION
-       DSSALL
-       sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-       ori     r7,r7,MSR_EE
-       oris    r7,r7,MSR_POW@h
-       sync
-       isync
-       mtmsrd  r7
-       isync
-       blr
index 53bee660ff3d0439b98ebc5ea08bfa61b82d4217..837989e72ca18afef2fe3b029049324e0372f8a5 100644 (file)
@@ -916,18 +916,20 @@ static void pmac_cpu_die(void)
        preempt_enable();
 
        /*
-        * hard-disable interrupts for the non-NAP case, the NAP code
-        * needs to re-enable interrupts (but soft-disables them)
+        * Re-enable interrupts. The NAP code needs to enable them
+        * anyways, do it now so we deal with the case where one already
+        * happened while soft-disabled.
+        * We shouldn't get any external interrupts, only decrementer, and the
+        * decrementer handler is safe for use on offline CPUs
         */
-       hard_irq_disable();
+       local_irq_enable();
 
        while (1) {
                /* let's not take timer interrupts too often ... */
                set_dec(0x7fffffff);
 
-               /* should always be true at this point */
-               if (cpu_has_feature(CPU_FTR_CAN_NAP))
-                       power4_cpu_offline_powersave();
+               /* Enter NAP mode */
+               power4_idle();
        }
 }