From: Preeti U Murthy <pre...@linux.vnet.ibm.com>

Split timer_interrupt(), which is the local timer interrupt handler on ppc
into routines called during regular interrupt handling and __timer_interrupt(),
which takes care of running local timers and collecting time related stats.

This will enable callers interested only in running expired local timers to
directly call into __timer_interupt(). One of the use cases of this is the
tick broadcast IPI handling in which the sleeping CPUs need to handle the local
timers that have expired.

Signed-off-by: Preeti U Murthy <pre...@linux.vnet.ibm.com>
---

 arch/powerpc/kernel/time.c |   81 +++++++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 35 deletions(-)

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 3ff97db..df2989b 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -478,6 +478,47 @@ void arch_irq_work_raise(void)
 
 #endif /* CONFIG_IRQ_WORK */
 
+void __timer_interrupt(void)
+{
+       struct pt_regs *regs = get_irq_regs();
+       u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
+       struct clock_event_device *evt = &__get_cpu_var(decrementers);
+       u64 now;
+
+       trace_timer_interrupt_entry(regs);
+
+       if (test_irq_work_pending()) {
+               clear_irq_work_pending();
+               irq_work_run();
+       }
+
+       now = get_tb_or_rtc();
+       if (now >= *next_tb) {
+               *next_tb = ~(u64)0;
+               if (evt->event_handler)
+                       evt->event_handler(evt);
+               __get_cpu_var(irq_stat).timer_irqs_event++;
+       } else {
+               now = *next_tb - now;
+               if (now <= DECREMENTER_MAX)
+                       set_dec((int)now);
+               /* We may have raced with new irq work */
+               if (test_irq_work_pending())
+                       set_dec(1);
+               __get_cpu_var(irq_stat).timer_irqs_others++;
+       }
+
+#ifdef CONFIG_PPC64
+       /* collect purr register values often, for accurate calculations */
+       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+               struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+               cu->current_tb = mfspr(SPRN_PURR);
+       }
+#endif
+
+       trace_timer_interrupt_exit(regs);
+}
+
 /*
  * timer_interrupt - gets called when the decrementer overflows,
  * with interrupts disabled.
@@ -486,8 +527,6 @@ void timer_interrupt(struct pt_regs * regs)
 {
        struct pt_regs *old_regs;
        u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
-       struct clock_event_device *evt = &__get_cpu_var(decrementers);
-       u64 now;
 
        /* Ensure a positive value is written to the decrementer, or else
         * some CPUs will continue to take decrementer exceptions.
@@ -519,39 +558,7 @@ void timer_interrupt(struct pt_regs * regs)
        old_regs = set_irq_regs(regs);
        irq_enter();
 
-       trace_timer_interrupt_entry(regs);
-
-       if (test_irq_work_pending()) {
-               clear_irq_work_pending();
-               irq_work_run();
-       }
-
-       now = get_tb_or_rtc();
-       if (now >= *next_tb) {
-               *next_tb = ~(u64)0;
-               if (evt->event_handler)
-                       evt->event_handler(evt);
-               __get_cpu_var(irq_stat).timer_irqs_event++;
-       } else {
-               now = *next_tb - now;
-               if (now <= DECREMENTER_MAX)
-                       set_dec((int)now);
-               /* We may have raced with new irq work */
-               if (test_irq_work_pending())
-                       set_dec(1);
-               __get_cpu_var(irq_stat).timer_irqs_others++;
-       }
-
-#ifdef CONFIG_PPC64
-       /* collect purr register values often, for accurate calculations */
-       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-               struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
-               cu->current_tb = mfspr(SPRN_PURR);
-       }
-#endif
-
-       trace_timer_interrupt_exit(regs);
-
+       __timer_interrupt();
        irq_exit();
        set_irq_regs(old_regs);
 }
@@ -828,6 +835,10 @@ static void decrementer_set_mode(enum clock_event_mode 
mode,
 /* Interrupt handler for the timer broadcast IPI */
 void tick_broadcast_ipi_handler(void)
 {
+       u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
+
+       *next_tb = get_tb_or_rtc();
+       __timer_interrupt();
 }
 
 static void register_decrementer_clockevent(int cpu)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to