diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-19 10:20:58 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-19 12:26:30 -0500 |
commit | 7deabca0acfe02b8e18f59a4c95676012f49a304 (patch) | |
tree | 56d9d696cb26de9696cfe591cab9b80d54608cef /arch/arm/kernel | |
parent | 94ae0275d7d6cae84b3af11f9e3d88f529528ac7 (diff) |
ARM: fix rcu stalls on SMP platforms
We can stall RCU processing on SMP platforms if a CPU sits in its idle
loop for a long time. This happens because we don't call irq_enter()
and irq_exit() around generic_smp_call_function_interrupt() and
friends. Add the necessary calls, and remove the one from within
ipi_timer(), so that they're all in a common place.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/smp.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 57db122a4f62..26cdc494ee9b 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -443,9 +443,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); | |||
443 | static void ipi_timer(void) | 443 | static void ipi_timer(void) |
444 | { | 444 | { |
445 | struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); | 445 | struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); |
446 | irq_enter(); | ||
447 | evt->event_handler(evt); | 446 | evt->event_handler(evt); |
448 | irq_exit(); | ||
449 | } | 447 | } |
450 | 448 | ||
451 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 449 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
@@ -548,7 +546,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
548 | 546 | ||
549 | switch (ipinr) { | 547 | switch (ipinr) { |
550 | case IPI_TIMER: | 548 | case IPI_TIMER: |
549 | irq_enter(); | ||
551 | ipi_timer(); | 550 | ipi_timer(); |
551 | irq_exit(); | ||
552 | break; | 552 | break; |
553 | 553 | ||
554 | case IPI_RESCHEDULE: | 554 | case IPI_RESCHEDULE: |
@@ -556,15 +556,21 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
556 | break; | 556 | break; |
557 | 557 | ||
558 | case IPI_CALL_FUNC: | 558 | case IPI_CALL_FUNC: |
559 | irq_enter(); | ||
559 | generic_smp_call_function_interrupt(); | 560 | generic_smp_call_function_interrupt(); |
561 | irq_exit(); | ||
560 | break; | 562 | break; |
561 | 563 | ||
562 | case IPI_CALL_FUNC_SINGLE: | 564 | case IPI_CALL_FUNC_SINGLE: |
565 | irq_enter(); | ||
563 | generic_smp_call_function_single_interrupt(); | 566 | generic_smp_call_function_single_interrupt(); |
567 | irq_exit(); | ||
564 | break; | 568 | break; |
565 | 569 | ||
566 | case IPI_CPU_STOP: | 570 | case IPI_CPU_STOP: |
571 | irq_enter(); | ||
567 | ipi_cpu_stop(cpu); | 572 | ipi_cpu_stop(cpu); |
573 | irq_exit(); | ||
568 | break; | 574 | break; |
569 | 575 | ||
570 | default: | 576 | default: |