summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-11-01 07:15:30 +0300
committerDavid S. Miller <davem@davemloft.net>2015-11-01 07:15:30 +0300
commitb75ec3af27bf011a760e2f44eb25a99b6fbb0fb3 (patch)
tree89f4fbab2c6194b32a46eb771c4b158585bf0bb5 /arch/powerpc/platforms
parente7b63ff115f21ea6c609cbb08f3d489af627af6e (diff)
parent523e13455ec9ec4457a5a1d24ff7132949742b70 (diff)
downloadlinux-b75ec3af27bf011a760e2f44eb25a99b6fbb0fb3.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powernv/smp.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 8f70ba681a78..ca264833ee64 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -171,7 +171,26 @@ static void pnv_smp_cpu_kill_self(void)
* so clear LPCR:PECE1. We keep PECE2 enabled.
*/
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+
+ /*
+ * Hard-disable interrupts, and then clear irq_happened flags
+ * that we can safely ignore while off-line, since they
+ * are for things for which we do no processing when off-line
+ * (or in the case of HMI, all the processing we need to do
+ * is done in lower-level real-mode code).
+ */
+ hard_irq_disable();
+ local_paca->irq_happened &= ~(PACA_IRQ_DEC | PACA_IRQ_HMI);
+
while (!generic_check_cpu_restart(cpu)) {
+ /*
+ * Clear IPI flag, since we don't handle IPIs while
+ * offline, except for those when changing micro-threading
+ * mode, which are handled explicitly below, and those
+ * for coming online, which are handled via
+ * generic_check_cpu_restart() calls.
+ */
+ kvmppc_set_host_ipi(cpu, 0);
ppc64_runlatch_off();
@@ -196,20 +215,20 @@ static void pnv_smp_cpu_kill_self(void)
* having finished executing in a KVM guest, then srr1
* contains 0.
*/
- if ((srr1 & wmask) == SRR1_WAKEEE) {
+ if (((srr1 & wmask) == SRR1_WAKEEE) ||
+ (local_paca->irq_happened & PACA_IRQ_EE)) {
icp_native_flush_interrupt();
- local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
- smp_mb();
} else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
- kvmppc_set_host_ipi(cpu, 0);
}
+ local_paca->irq_happened &= ~(PACA_IRQ_EE | PACA_IRQ_DBELL);
+ smp_mb();
if (cpu_core_split_required())
continue;
- if (!generic_check_cpu_restart(cpu))
+ if (srr1 && !generic_check_cpu_restart(cpu))
DBG("CPU%d Unexpected exit while offline !\n", cpu);
}
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);