/* Native ICP */
 #ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
+extern void icp_native_flush_interrupt(void);
 #else
 static inline int icp_native_init(void) { return -ENODEV; }
 #endif
 
 
        /* Check if something happened while soft-disabled */
        lbz     r0,PACAIRQHAPPENED(r13)
-       cmpwi   cr0,r0,0
+       andi.   r0,r0,~PACA_IRQ_HARD_DIS@l
        beq     1f
        cmpwi   cr0,r4,0
        beq     1f
 
                power7_nap(1);
                ppc64_runlatch_on();
 
-               /* Reenable IRQs briefly to clear the IPI that woke us */
-               local_irq_enable();
-               local_irq_disable();
+               /* Clear the IPI that woke us up */
+               icp_native_flush_interrupt();
+               local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
                mb();
 
                if (cpu_core_split_required())
 
                icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
+/*
+ * Called when an interrupt is received on an off-line CPU to
+ * clear the interrupt, so that the CPU can go back to nap mode.
+ */
+void icp_native_flush_interrupt(void)
+{
+       unsigned int xirr = icp_native_get_xirr();
+       unsigned int vec = xirr & 0x00ffffff;
+
+       if (vec == XICS_IRQ_SPURIOUS)
+               return;
+       if (vec == XICS_IPI) {
+               /* Clear pending IPI */
+               int cpu = smp_processor_id();
+               kvmppc_set_host_ipi(cpu, 0);
+               icp_native_set_qirr(cpu, 0xff);
+       } else {
+               pr_err("XICS: hw interrupt 0x%x to offline cpu, disabling\n",
+                      vec);
+               xics_mask_unknown_vec(vec);
+       }
+       /* EOI the interrupt */
+       icp_native_set_xirr(xirr);
+}
+
 void xics_wake_cpu(int cpu)
 {
        icp_native_set_qirr(cpu, IPI_PRIORITY);