MIPS: Oprofile: Fixup the loose ends in the plumbing.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
0401572a9b
commit
ba339c03e2
|
@ -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]++;
|
||||||
|
|
||||||
/* we keep interrupt disabled all the time */
|
/*
|
||||||
timer_interrupt(irq, NULL, regs);
|
* 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);
|
||||||
|
|
||||||
|
out:
|
||||||
irq_exit();
|
irq_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
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 @@
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
(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)
|
||||||
|
|
Loading…
Reference in a new issue