forked from Minki/linux
powerpc: Split timer_interrupt() into timer handling and interrupt handling routines
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 <preeti@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
1b67bee129
commit
1b7839559b
@ -478,47 +478,13 @@ void arch_irq_work_raise(void)
|
||||
|
||||
#endif /* CONFIG_IRQ_WORK */
|
||||
|
||||
/*
|
||||
* timer_interrupt - gets called when the decrementer overflows,
|
||||
* with interrupts disabled.
|
||||
*/
|
||||
void timer_interrupt(struct pt_regs * regs)
|
||||
void __timer_interrupt(void)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
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;
|
||||
|
||||
/* Ensure a positive value is written to the decrementer, or else
|
||||
* some CPUs will continue to take decrementer exceptions.
|
||||
*/
|
||||
set_dec(DECREMENTER_MAX);
|
||||
|
||||
/* Some implementations of hotplug will get timer interrupts while
|
||||
* offline, just ignore these and we also need to set
|
||||
* decrementers_next_tb as MAX to make sure __check_irq_replay
|
||||
* don't replay timer interrupt when return, otherwise we'll trap
|
||||
* here infinitely :(
|
||||
*/
|
||||
if (!cpu_online(smp_processor_id())) {
|
||||
*next_tb = ~(u64)0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Conditionally hard-enable interrupts now that the DEC has been
|
||||
* bumped to its maximum value
|
||||
*/
|
||||
may_hard_irq_enable();
|
||||
|
||||
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
|
||||
if (atomic_read(&ppc_n_lost_interrupts) != 0)
|
||||
do_IRQ(regs);
|
||||
#endif
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
irq_enter();
|
||||
|
||||
trace_timer_interrupt_entry(regs);
|
||||
|
||||
if (test_irq_work_pending()) {
|
||||
@ -551,7 +517,48 @@ void timer_interrupt(struct pt_regs * regs)
|
||||
#endif
|
||||
|
||||
trace_timer_interrupt_exit(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* timer_interrupt - gets called when the decrementer overflows,
|
||||
* with interrupts disabled.
|
||||
*/
|
||||
void timer_interrupt(struct pt_regs * regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
|
||||
|
||||
/* Ensure a positive value is written to the decrementer, or else
|
||||
* some CPUs will continue to take decrementer exceptions.
|
||||
*/
|
||||
set_dec(DECREMENTER_MAX);
|
||||
|
||||
/* Some implementations of hotplug will get timer interrupts while
|
||||
* offline, just ignore these and we also need to set
|
||||
* decrementers_next_tb as MAX to make sure __check_irq_replay
|
||||
* don't replay timer interrupt when return, otherwise we'll trap
|
||||
* here infinitely :(
|
||||
*/
|
||||
if (!cpu_online(smp_processor_id())) {
|
||||
*next_tb = ~(u64)0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Conditionally hard-enable interrupts now that the DEC has been
|
||||
* bumped to its maximum value
|
||||
*/
|
||||
may_hard_irq_enable();
|
||||
|
||||
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
|
||||
if (atomic_read(&ppc_n_lost_interrupts) != 0)
|
||||
do_IRQ(regs);
|
||||
#endif
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
irq_enter();
|
||||
|
||||
__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)
|
||||
|
Loading…
Reference in New Issue
Block a user