@@ -25,6 +25,7 @@
#include <linux/percpu.h>
#include <linux/clockchips.h>
#include <linux/completion.h>
+#include <linux/threads.h>
#include <linux/atomic.h>
#include <asm/cacheflush.h>
@@ -495,11 +496,28 @@ asmlinkage void __exception_irq_entry do_IPI(int
ipinr, struct pt_regs *regs)
handle_IPI(ipinr, regs);
}
+static int ipi_wakeup_nr[NR_CPUS];
+
+void smp_send_wakeup_ipi_begin(unsigned int cpu, unsigned int irq)
+{
+ ipi_wakeup_nr[cpu] = irq + 1;
+ gic_raise_softirq(cpumask_of(cpu),irq);
+}
+
+void smp_send_wakeup_ipi_end(unsigned int cpu, unsigned int irq)
+{
+ BUG_ON(ipi_wakeup_nr[cpu] != irq + 1);
+ ipi_wakeup_nr[cpu] = 0;
+}
+
void handle_IPI(int ipinr, struct pt_regs *regs)
{
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
+ if (ipi_wakeup_nr[cpu] == ipinr + 1)
+ goto Exit;
+
if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
@@ -537,6 +555,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
cpu, ipinr);
break;
}
+Exit:
set_irq_regs(old_regs);
}
@@ -127,7 +127,7 @@ int __cpuinit boot_secondary(unsigned int cpu,
struct task_struct *idle)
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
- gic_raise_softirq(cpumask_of(cpu), 1);
+ smp_send_wakeup_ipi_begin(cpu, 0);
timeout = jiffies + (1 * HZ);