aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/xics.h1
-rw-r--r--arch/powerpc/kernel/idle_power7.S2
-rw-r--r--arch/powerpc/platforms/powernv/smp.c6
-rw-r--r--arch/powerpc/sysdev/xics/icp-native.c25
4 files changed, 30 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
index 282d43a0c855..0d050ea37a04 100644
--- a/arch/powerpc/include/asm/xics.h
+++ b/arch/powerpc/include/asm/xics.h
@@ -29,6 +29,7 @@
29/* Native ICP */ 29/* Native ICP */
30#ifdef CONFIG_PPC_ICP_NATIVE 30#ifdef CONFIG_PPC_ICP_NATIVE
31extern int icp_native_init(void); 31extern int icp_native_init(void);
32extern void icp_native_flush_interrupt(void);
32#else 33#else
33static inline int icp_native_init(void) { return -ENODEV; } 34static inline int icp_native_init(void) { return -ENODEV; }
34#endif 35#endif
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index be05841396cf..c0754bbf8118 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -73,7 +73,7 @@ _GLOBAL(power7_powersave_common)
73 73
74 /* Check if something happened while soft-disabled */ 74 /* Check if something happened while soft-disabled */
75 lbz r0,PACAIRQHAPPENED(r13) 75 lbz r0,PACAIRQHAPPENED(r13)
76 cmpwi cr0,r0,0 76 andi. r0,r0,~PACA_IRQ_HARD_DIS@l
77 beq 1f 77 beq 1f
78 cmpwi cr0,r4,0 78 cmpwi cr0,r4,0
79 beq 1f 79 beq 1f
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index b73adc573031..4753958cd509 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -168,9 +168,9 @@ static void pnv_smp_cpu_kill_self(void)
168 power7_nap(1); 168 power7_nap(1);
169 ppc64_runlatch_on(); 169 ppc64_runlatch_on();
170 170
171 /* Reenable IRQs briefly to clear the IPI that woke us */ 171 /* Clear the IPI that woke us up */
172 local_irq_enable(); 172 icp_native_flush_interrupt();
173 local_irq_disable(); 173 local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
174 mb(); 174 mb();
175 175
176 if (cpu_core_split_required()) 176 if (cpu_core_split_required())
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index de8d9483bbe8..2fc4cf1b7557 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -155,6 +155,31 @@ static void icp_native_cause_ipi(int cpu, unsigned long data)
155 icp_native_set_qirr(cpu, IPI_PRIORITY); 155 icp_native_set_qirr(cpu, IPI_PRIORITY);
156} 156}
157 157
158/*
159 * Called when an interrupt is received on an off-line CPU to
160 * clear the interrupt, so that the CPU can go back to nap mode.
161 */
162void icp_native_flush_interrupt(void)
163{
164 unsigned int xirr = icp_native_get_xirr();
165 unsigned int vec = xirr & 0x00ffffff;
166
167 if (vec == XICS_IRQ_SPURIOUS)
168 return;
169 if (vec == XICS_IPI) {
170 /* Clear pending IPI */
171 int cpu = smp_processor_id();
172 kvmppc_set_host_ipi(cpu, 0);
173 icp_native_set_qirr(cpu, 0xff);
174 } else {
175 pr_err("XICS: hw interrupt 0x%x to offline cpu, disabling\n",
176 vec);
177 xics_mask_unknown_vec(vec);
178 }
179 /* EOI the interrupt */
180 icp_native_set_xirr(xirr);
181}
182
158void xics_wake_cpu(int cpu) 183void xics_wake_cpu(int cpu)
159{ 184{
160 icp_native_set_qirr(cpu, IPI_PRIORITY); 185 icp_native_set_qirr(cpu, IPI_PRIORITY);