Skip to content

Commit

Permalink
MIPS: Oprofile: Fixup the loose ends in the plumbing.
Browse files Browse the repository at this point in the history
    
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle authored and Unknown committed Jan 10, 2006
1 parent 0401572 commit ba339c0
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 7 deletions.
26 changes: 25 additions & 1 deletion arch/mips/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
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 */
timer_interrupt(irq, NULL, regs);
if (!r2 || (read_c0_cause() & (1 << 30)))
timer_interrupt(irq, NULL, regs);

out:
irq_exit();
}

Expand Down
20 changes: 17 additions & 3 deletions arch/mips/mips-boards/generic/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,29 @@ static void mips_timer_dispatch (struct pt_regs *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)
{
int r2 = cpu_has_mips_r2;
int cpu = smp_processor_id();

if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process accounting
* resets count/compare registers to trigger next timer int.
* CPU 0 handles the global timer interrupt job and process
* 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();
} else {
/* Everyone else needs to reset the timer int here as
Expand All @@ -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);
}

out:
return IRQ_HANDLED;
}

Expand Down
4 changes: 2 additions & 2 deletions arch/mips/oprofile/op_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

struct pt_regs;

extern void null_perf_irq(struct pt_regs *regs);
extern void (*perf_irq)(struct pt_regs *regs);
extern int null_perf_irq(struct pt_regs *regs);
extern int (*perf_irq)(struct pt_regs *regs);

/* Per-counter configuration as set via oprofilefs. */
struct op_counter_config {
Expand Down
6 changes: 5 additions & 1 deletion arch/mips/oprofile/op_model_mipsxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 control;
unsigned int counter;
int handled = 0;

switch (counters) {
#define HANDLE_COUNTER(n) \
Expand All @@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs)
(counter & M_COUNTER_OVERFLOW)) { \
oprofile_add_sample(regs, n); \
write_c0_perfcntr ## n(reg.counter[n]); \
handled = 1; \
}
HANDLE_COUNTER(3)
HANDLE_COUNTER(2)
HANDLE_COUNTER(1)
HANDLE_COUNTER(0)
}

return handled;
}

#define M_CONFIG1_PC (1 << 4)
Expand Down

0 comments on commit ba339c0

Please sign in to comment.