summaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/smp.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@parisc-linux.org>2005-11-17 16:27:02 -0500
committerKyle McMartin <kyle@parisc-linux.org>2005-11-17 16:27:02 -0500
commitd911aed8adf74e1fae88d082b8474b2175b7f1da (patch)
treedc3271e33b2951a8fd43824300b790610c7cd221 /arch/parisc/kernel/smp.c
parent3f902886a81c6d4e6c399760936b645b5c7a7342 (diff)
[PARISC] Fix our interrupts not to use smp_call_function
Fix our interrupts not to use smp_call_function On K and D class smp, the generic code calls this under an irq spinlock, which causes the WARN_ON() message in smp_call_function() (and is also illegal because it could deadlock). The fix is to use a new scheme based on the IPI_NOP. Signed-off-by: James Bottomley <jejb@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Diffstat (limited to 'arch/parisc/kernel/smp.c')
-rw-r--r--arch/parisc/kernel/smp.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 268b0f2a328..ce89da0f654 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -181,12 +181,19 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
while (ops) {
unsigned long which = ffz(~ops);
+ ops &= ~(1 << which);
+
switch (which) {
+ case IPI_NOP:
+#if (kDEBUG>=100)
+ printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu);
+#endif /* kDEBUG */
+ break;
+
case IPI_RESCHEDULE:
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
#endif /* kDEBUG */
- ops &= ~(1 << IPI_RESCHEDULE);
/*
* Reschedule callback. Everything to be
* done is done by the interrupt return path.
@@ -197,7 +204,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
#endif /* kDEBUG */
- ops &= ~(1 << IPI_CALL_FUNC);
{
volatile struct smp_call_struct *data;
void (*func)(void *info);
@@ -231,7 +237,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
#endif /* kDEBUG */
- ops &= ~(1 << IPI_CPU_START);
#ifdef ENTRY_SYS_CPUS
p->state = STATE_RUNNING;
#endif
@@ -241,7 +246,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
#endif /* kDEBUG */
- ops &= ~(1 << IPI_CPU_STOP);
#ifdef ENTRY_SYS_CPUS
#else
halt_processor();
@@ -252,13 +256,11 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
#endif /* kDEBUG */
- ops &= ~(1 << IPI_CPU_TEST);
break;
default:
printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
this_cpu, which);
- ops &= ~(1 << which);
return IRQ_NONE;
} /* Switch */
} /* while (ops) */
@@ -312,6 +314,12 @@ smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); }
void
smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); }
+void
+smp_send_all_nop(void)
+{
+ send_IPI_allbutself(IPI_NOP);
+}
+
/**
* Run a function on all other CPUs.