@@ -351,6 +351,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)
lpcr |= SPR_LPCR_P8_PECE2 | SPR_LPCR_P8_PECE3;
mtspr(SPR_LPCR, lpcr);
}
+ isync();
/* Enter nap */
enter_p8_pm_state(false);
@@ -404,6 +405,7 @@ static void cpu_idle_p9(enum cpu_wake_cause wake_on)
}
mtspr(SPR_LPCR, lpcr);
+ isync();
if (sreset_enabled) {
/* stop with EC=1 (sreset) and ESL=1 (enable thread switch). */
@@ -984,6 +986,7 @@ static void enable_large_dec(bool on)
lpcr &= ~SPR_LPCR_P9_LD;
mtspr(SPR_LPCR, lpcr);
+ isync();
}
#define HIGH_BIT (1ull << 63)
@@ -239,6 +239,7 @@ static void check_split_core(void)
/* Setup LPCR to wakeup on external interrupts only */
mtspr(SPR_LPCR, ((mfspr(SPR_LPCR) & ~SPR_LPCR_P8_PECE) |
SPR_LPCR_P8_PECE2));
+ isync();
/* Go to nap (doesn't return) */
enter_nap();
}
@@ -73,6 +73,7 @@ static void slw_do_rvwinkle(void *data)
/* Setup LPCR to wakeup on external interrupts only */
mtspr(SPR_LPCR, ((lpcr & ~SPR_LPCR_P8_PECE) | SPR_LPCR_P8_PECE2));
+ isync();
prlog(PR_DEBUG, "SLW: CPU PIR 0x%04x goint to rvwinkle...\n",
cpu->pir);
@@ -99,6 +100,7 @@ static void slw_do_rvwinkle(void *data)
/* Restore LPCR */
mtspr(SPR_LPCR, lpcr);
+ isync();
/* If we are passed a master pointer we are the designated
* waker, let's proceed. If not, return, we are finished.
This is required by the architecture and the implementations, I've observed failures to wake up on big cores without this. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- core/cpu.c | 3 +++ core/fast-reboot.c | 1 + hw/slw.c | 2 ++ 3 files changed, 6 insertions(+)