diff options
author | James Bottomley <jejb@parisc-linux.org> | 2005-11-17 16:27:02 -0500 |
---|---|---|
committer | Kyle McMartin <kyle@parisc-linux.org> | 2005-11-17 16:27:02 -0500 |
commit | d911aed8adf74e1fae88d082b8474b2175b7f1da (patch) | |
tree | dc3271e33b2951a8fd43824300b790610c7cd221 /arch/parisc/kernel/smp.c | |
parent | 3f902886a81c6d4e6c399760936b645b5c7a7342 (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.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 268b0f2a328e..ce89da0f654d 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) | |||
181 | while (ops) { | 181 | while (ops) { |
182 | unsigned long which = ffz(~ops); | 182 | unsigned long which = ffz(~ops); |
183 | 183 | ||
184 | ops &= ~(1 << which); | ||
185 | |||
184 | switch (which) { | 186 | switch (which) { |
187 | case IPI_NOP: | ||
188 | #if (kDEBUG>=100) | ||
189 | printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu); | ||
190 | #endif /* kDEBUG */ | ||
191 | break; | ||
192 | |||
185 | case IPI_RESCHEDULE: | 193 | case IPI_RESCHEDULE: |
186 | #if (kDEBUG>=100) | 194 | #if (kDEBUG>=100) |
187 | printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); | 195 | printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); |
188 | #endif /* kDEBUG */ | 196 | #endif /* kDEBUG */ |
189 | ops &= ~(1 << IPI_RESCHEDULE); | ||
190 | /* | 197 | /* |
191 | * Reschedule callback. Everything to be | 198 | * Reschedule callback. Everything to be |
192 | * done is done by the interrupt return path. | 199 | * done is done by the interrupt return path. |
@@ -197,7 +204,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
197 | #if (kDEBUG>=100) | 204 | #if (kDEBUG>=100) |
198 | printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); | 205 | printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); |
199 | #endif /* kDEBUG */ | 206 | #endif /* kDEBUG */ |
200 | ops &= ~(1 << IPI_CALL_FUNC); | ||
201 | { | 207 | { |
202 | volatile struct smp_call_struct *data; | 208 | volatile struct smp_call_struct *data; |
203 | void (*func)(void *info); | 209 | void (*func)(void *info); |
@@ -231,7 +237,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
231 | #if (kDEBUG>=100) | 237 | #if (kDEBUG>=100) |
232 | printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); | 238 | printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); |
233 | #endif /* kDEBUG */ | 239 | #endif /* kDEBUG */ |
234 | ops &= ~(1 << IPI_CPU_START); | ||
235 | #ifdef ENTRY_SYS_CPUS | 240 | #ifdef ENTRY_SYS_CPUS |
236 | p->state = STATE_RUNNING; | 241 | p->state = STATE_RUNNING; |
237 | #endif | 242 | #endif |
@@ -241,7 +246,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
241 | #if (kDEBUG>=100) | 246 | #if (kDEBUG>=100) |
242 | printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); | 247 | printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); |
243 | #endif /* kDEBUG */ | 248 | #endif /* kDEBUG */ |
244 | ops &= ~(1 << IPI_CPU_STOP); | ||
245 | #ifdef ENTRY_SYS_CPUS | 249 | #ifdef ENTRY_SYS_CPUS |
246 | #else | 250 | #else |
247 | halt_processor(); | 251 | halt_processor(); |
@@ -252,13 +256,11 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
252 | #if (kDEBUG>=100) | 256 | #if (kDEBUG>=100) |
253 | printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); | 257 | printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); |
254 | #endif /* kDEBUG */ | 258 | #endif /* kDEBUG */ |
255 | ops &= ~(1 << IPI_CPU_TEST); | ||
256 | break; | 259 | break; |
257 | 260 | ||
258 | default: | 261 | default: |
259 | printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", | 262 | printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", |
260 | this_cpu, which); | 263 | this_cpu, which); |
261 | ops &= ~(1 << which); | ||
262 | return IRQ_NONE; | 264 | return IRQ_NONE; |
263 | } /* Switch */ | 265 | } /* Switch */ |
264 | } /* while (ops) */ | 266 | } /* while (ops) */ |
@@ -312,6 +314,12 @@ smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); } | |||
312 | void | 314 | void |
313 | smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } | 315 | smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } |
314 | 316 | ||
317 | void | ||
318 | smp_send_all_nop(void) | ||
319 | { | ||
320 | send_IPI_allbutself(IPI_NOP); | ||
321 | } | ||
322 | |||
315 | 323 | ||
316 | /** | 324 | /** |
317 | * Run a function on all other CPUs. | 325 | * Run a function on all other CPUs. |