提交 ba339c03 编写于 作者: R Ralf Baechle 提交者:

MIPS: Oprofile: Fixup the loose ends in the plumbing.

Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
上级 0401572a
...@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED; 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) asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
{ {
int r2 = cpu_has_mips_r2;
irq_enter(); irq_enter();
kstat_this_cpu.irqs[irq]++; 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 */ /* we keep interrupt disabled all the time */
timer_interrupt(irq, NULL, regs); if (!r2 || (read_c0_cause() & (1 << 30)))
timer_interrupt(irq, NULL, regs);
out:
irq_exit(); irq_exit();
} }
......
...@@ -75,16 +75,29 @@ static void mips_timer_dispatch (struct pt_regs *regs) ...@@ -75,16 +75,29 @@ static void mips_timer_dispatch (struct pt_regs *regs)
do_IRQ (mips_cpu_timer_irq, regs); 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) 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(); int cpu = smp_processor_id();
if (cpu == 0) { if (cpu == 0) {
/* /*
* CPU 0 handles the global timer interrupt job and process accounting * CPU 0 handles the global timer interrupt job and process
* resets count/compare registers to trigger next timer int. * accounting resets count/compare registers to trigger next
* timer int.
*/ */
timer_interrupt(irq, dev_id, regs); 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);
scroll_display_message(); scroll_display_message();
} else { } else {
/* Everyone else needs to reset the timer int here as /* Everyone else needs to reset the timer int here as
...@@ -101,6 +114,7 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -101,6 +114,7 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
local_timer_interrupt (irq, dev_id, regs); local_timer_interrupt (irq, dev_id, regs);
} }
out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
struct pt_regs; struct pt_regs;
extern void null_perf_irq(struct pt_regs *regs); extern int null_perf_irq(struct pt_regs *regs);
extern void (*perf_irq)(struct pt_regs *regs); extern int (*perf_irq)(struct pt_regs *regs);
/* Per-counter configuration as set via oprofilefs. */ /* Per-counter configuration as set via oprofilefs. */
struct op_counter_config { struct op_counter_config {
......
...@@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args) ...@@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args)
} }
} }
static void mipsxx_perfcount_handler(struct pt_regs *regs) static int mipsxx_perfcount_handler(struct pt_regs *regs)
{ {
unsigned int counters = op_model_mipsxx.num_counters; unsigned int counters = op_model_mipsxx.num_counters;
unsigned int control; unsigned int control;
unsigned int counter; unsigned int counter;
int handled = 0;
switch (counters) { switch (counters) {
#define HANDLE_COUNTER(n) \ #define HANDLE_COUNTER(n) \
...@@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs) ...@@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs)
(counter & M_COUNTER_OVERFLOW)) { \ (counter & M_COUNTER_OVERFLOW)) { \
oprofile_add_sample(regs, n); \ oprofile_add_sample(regs, n); \
write_c0_perfcntr ## n(reg.counter[n]); \ write_c0_perfcntr ## n(reg.counter[n]); \
handled = 1; \
} }
HANDLE_COUNTER(3) HANDLE_COUNTER(3)
HANDLE_COUNTER(2) HANDLE_COUNTER(2)
HANDLE_COUNTER(1) HANDLE_COUNTER(1)
HANDLE_COUNTER(0) HANDLE_COUNTER(0)
} }
return handled;
} }
#define M_CONFIG1_PC (1 << 4) #define M_CONFIG1_PC (1 << 4)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册