Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62cc67b9 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent e872e41b
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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);

+7 −0
Original line number Diff line number Diff line
@@ -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
+0 −21
Original line number Diff line number Diff line
@@ -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
+8 −6
Original line number Diff line number Diff line
@@ -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();
	}
}