aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@ozlabs.org>2008-04-09 03:21:28 -0400
committerPaul Mackerras <paulus@samba.org>2008-04-16 17:46:11 -0400
commite6768a4f392d05bc11ed508d35938932c73aac5a (patch)
tree29c04586b34437d80626222e4660926dda428cc7 /arch/powerpc/kernel
parent7c6352a4699e9a3a2d91b2cddbf3f1048207e904 (diff)
[POWERPC] Fixup softirq preempt count
This fixes the handling of the preempt count when switching interrupt stacks so that HW interrupt properly get the softirq mask copied over from the previous stack. It also initializes the softirq stack preempt_count to 0 instead of SOFTIRQ_OFFSET, like x86, as __do_softirq() does the increment, and we hit some lockdep checks if we have it twice. That means we do run for a little while off the softirq stack with the preempt-count set to 0, which could be deadly if we try to take a softirq at that point, however we do so with interrupts disabled, so I think we are ok. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/irq.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 292163f5b39..4617b65d464 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -310,8 +310,21 @@ void do_IRQ(struct pt_regs *regs)
310 handler = &__do_IRQ; 310 handler = &__do_IRQ;
311 irqtp->task = curtp->task; 311 irqtp->task = curtp->task;
312 irqtp->flags = 0; 312 irqtp->flags = 0;
313
314 /* Copy the softirq bits in preempt_count so that the
315 * softirq checks work in the hardirq context.
316 */
317 irqtp->preempt_count =
318 (irqtp->preempt_count & ~SOFTIRQ_MASK) |
319 (curtp->preempt_count & SOFTIRQ_MASK);
320
313 call_handle_irq(irq, desc, irqtp, handler); 321 call_handle_irq(irq, desc, irqtp, handler);
314 irqtp->task = NULL; 322 irqtp->task = NULL;
323
324
325 /* Set any flag that may have been set on the
326 * alternate stack
327 */
315 if (irqtp->flags) 328 if (irqtp->flags)
316 set_bits(irqtp->flags, &curtp->flags); 329 set_bits(irqtp->flags, &curtp->flags);
317 } else 330 } else
@@ -357,7 +370,7 @@ void irq_ctx_init(void)
357 memset((void *)softirq_ctx[i], 0, THREAD_SIZE); 370 memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
358 tp = softirq_ctx[i]; 371 tp = softirq_ctx[i];
359 tp->cpu = i; 372 tp->cpu = i;
360 tp->preempt_count = SOFTIRQ_OFFSET; 373 tp->preempt_count = 0;
361 374
362 memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); 375 memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
363 tp = hardirq_ctx[i]; 376 tp = hardirq_ctx[i];