1. Use CONFIG_OPROFILE to get rid of overhead for null_perf_irq() call. 2. Call perf_irq from timer_interrupt instead of ll_timer_interrupt. Most (non-SMP) boards will use timer_interrupt (instead of ll_timer_interrupt), so it would be better to move calling of perf_irq() to timer_interrupt(). 3. Use jiffies instead of local timer_tick_count. I can not test it by myself for now while I do not have any MIPS32/MIPS64 board. Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx> diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 7050b4f..7b5c5b9 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -414,6 +414,18 @@ void local_timer_interrupt(int irq, void update_process_times(user_mode(regs)); } +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) +int null_perf_irq(struct pt_regs *regs) +{ + return 0; +} + +int (*perf_irq)(struct pt_regs *regs) = null_perf_irq; + +EXPORT_SYMBOL(null_perf_irq); +EXPORT_SYMBOL(perf_irq); +#endif + /* * High-level timer interrupt service routines. This function * is set as irqaction->handler and is invoked through do_IRQ. @@ -422,6 +434,22 @@ irqreturn_t timer_interrupt(int irq, voi { unsigned long j; unsigned int count; +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) + int r2 = cpu_has_mips_r2; + + /* + * Suckage alert: + * Before R2 of the architecture there was no way to see if a + * performance counter interrupt was pending, so we have to run the + * performance counter interrupt handler anyway. + */ + if (!r2 || (read_c0_cause() & (1 << 26))) + if (perf_irq(regs)) + return IRQ_HANDLED; + + if (r2 && !(read_c0_cause() & (1 << 30))) + return IRQ_HANDLED; +#endif count = mips_hpt_read(); mips_timer_ack(); @@ -507,38 +535,14 @@ irqreturn_t timer_interrupt(int irq, voi return IRQ_HANDLED; } -int null_perf_irq(struct pt_regs *regs) -{ - return 0; -} - -int (*perf_irq)(struct pt_regs *regs) = null_perf_irq; - -EXPORT_SYMBOL(null_perf_irq); -EXPORT_SYMBOL(perf_irq); - asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) { - int r2 = cpu_has_mips_r2; - irq_enter(); kstat_this_cpu.irqs[irq]++; - /* - * Suckage alert: - * Before R2 of the architecture there was no way to see if a - * performance counter interrupt was pending, so we have to run the - * performance counter interrupt handler anyway. - */ - if (!r2 || (read_c0_cause() & (1 << 26))) - if (perf_irq(regs)) - goto out; - /* we keep interrupt disabled all the time */ - if (!r2 || (read_c0_cause() & (1 << 30))) - timer_interrupt(irq, NULL, regs); + timer_interrupt(irq, NULL, regs); -out: irq_exit(); } diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 93f3bf2..f9471de 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -58,12 +58,11 @@ static char display_string[] = " static unsigned int display_count = 0; #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) -static unsigned int timer_tick_count=0; static int mips_cpu_timer_irq; static inline void scroll_display_message(void) { - if ((timer_tick_count++ % HZ) == 0) { + if ((jiffies % HZ) == 0) { mips_display_message(&display_string[display_count++]); if (display_count == MAX_DISPLAY_COUNT) display_count = 0; @@ -75,13 +74,8 @@ static void mips_timer_dispatch (struct do_IRQ (mips_cpu_timer_irq, regs); } -extern int null_perf_irq(struct pt_regs *regs); - -extern int (*perf_irq)(struct pt_regs *regs); - irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - int r2 = cpu_has_mips_r2; int cpu = smp_processor_id(); if (cpu == 0) { @@ -90,13 +84,7 @@ irqreturn_t mips_timer_interrupt(int irq * accounting resets count/compare registers to trigger next * timer int. */ - if (!r2 || (read_c0_cause() & (1 << 26))) - if (perf_irq(regs)) - goto out; - - /* we keep interrupt disabled all the time */ - if (!r2 || (read_c0_cause() & (1 << 30))) - timer_interrupt(irq, NULL, regs); + timer_interrupt(irq, NULL, regs); scroll_display_message(); } else { @@ -114,7 +102,6 @@ irqreturn_t mips_timer_interrupt(int irq local_timer_interrupt (irq, dev_id, regs); } -out: return IRQ_HANDLED; }