[2/3] cpu: Do an isync after setting LPCR

Message ID 20180511064121.18122-2-benh@kernel.crashing.org
State Accepted
Headers show
Series
  • [1/3] cpu: Remove duplicate setting of LPCR
Related show

Commit Message

Benjamin Herrenschmidt May 11, 2018, 6:41 a.m.
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(+)

Patch

diff --git a/core/cpu.c b/core/cpu.c
index 0a1d58f2..3e5e5922 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -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)
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index a09efd85..3022fdd7 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -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();
 	}
diff --git a/hw/slw.c b/hw/slw.c
index 2b305db1..a5e1e902 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -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.