diff options
-rw-r--r-- | arch/powerpc/include/asm/xics.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/smp.c | 6 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xics/icp-native.c | 25 |
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 |
31 | extern int icp_native_init(void); | 31 | extern int icp_native_init(void); |
32 | extern void icp_native_flush_interrupt(void); | ||
32 | #else | 33 | #else |
33 | static inline int icp_native_init(void) { return -ENODEV; } | 34 | static 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 | */ | ||
162 | void 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 | |||
158 | void xics_wake_cpu(int cpu) | 183 | void xics_wake_cpu(int cpu) |
159 | { | 184 | { |
160 | icp_native_set_qirr(cpu, IPI_PRIORITY); | 185 | icp_native_set_qirr(cpu, IPI_PRIORITY); |