diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-12-09 07:29:38 -0500 |
---|---|---|
committer | <ralf@denk.linux-mips.net> | 2006-01-10 08:39:07 -0500 |
commit | ba339c03e2e8ede8ccd37ed6c4e564e3b1545495 (patch) | |
tree | 1a7bbfd15a9c46d5300d2d5a1890d748b81dbce2 /arch/mips | |
parent | 0401572a9b9b2f368176b6e53f53004fd048a566 (diff) |
MIPS: Oprofile: Fixup the loose ends in the plumbing.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/time.c | 26 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/time.c | 20 | ||||
-rw-r--r-- | arch/mips/oprofile/op_impl.h | 4 | ||||
-rw-r--r-- | arch/mips/oprofile/op_model_mipsxx.c | 6 |
4 files changed, 49 insertions, 7 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 07e125c027b2..7050b4ffffcd 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
507 | return IRQ_HANDLED; | 507 | return IRQ_HANDLED; |
508 | } | 508 | } |
509 | 509 | ||
510 | int null_perf_irq(struct pt_regs *regs) | ||
511 | { | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | int (*perf_irq)(struct pt_regs *regs) = null_perf_irq; | ||
516 | |||
517 | EXPORT_SYMBOL(null_perf_irq); | ||
518 | EXPORT_SYMBOL(perf_irq); | ||
519 | |||
510 | asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) | 520 | asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) |
511 | { | 521 | { |
522 | int r2 = cpu_has_mips_r2; | ||
523 | |||
512 | irq_enter(); | 524 | irq_enter(); |
513 | kstat_this_cpu.irqs[irq]++; | 525 | kstat_this_cpu.irqs[irq]++; |
514 | 526 | ||
527 | /* | ||
528 | * Suckage alert: | ||
529 | * Before R2 of the architecture there was no way to see if a | ||
530 | * performance counter interrupt was pending, so we have to run the | ||
531 | * performance counter interrupt handler anyway. | ||
532 | */ | ||
533 | if (!r2 || (read_c0_cause() & (1 << 26))) | ||
534 | if (perf_irq(regs)) | ||
535 | goto out; | ||
536 | |||
515 | /* we keep interrupt disabled all the time */ | 537 | /* we keep interrupt disabled all the time */ |
516 | timer_interrupt(irq, NULL, regs); | 538 | if (!r2 || (read_c0_cause() & (1 << 30))) |
539 | timer_interrupt(irq, NULL, regs); | ||
517 | 540 | ||
541 | out: | ||
518 | irq_exit(); | 542 | irq_exit(); |
519 | } | 543 | } |
520 | 544 | ||
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 2830f656fe2f..93f3bf2c2b22 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c | |||
@@ -75,16 +75,29 @@ static void mips_timer_dispatch (struct pt_regs *regs) | |||
75 | do_IRQ (mips_cpu_timer_irq, regs); | 75 | do_IRQ (mips_cpu_timer_irq, regs); |
76 | } | 76 | } |
77 | 77 | ||
78 | extern int null_perf_irq(struct pt_regs *regs); | ||
79 | |||
80 | extern int (*perf_irq)(struct pt_regs *regs); | ||
81 | |||
78 | irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 82 | irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
79 | { | 83 | { |
84 | int r2 = cpu_has_mips_r2; | ||
80 | int cpu = smp_processor_id(); | 85 | int cpu = smp_processor_id(); |
81 | 86 | ||
82 | if (cpu == 0) { | 87 | if (cpu == 0) { |
83 | /* | 88 | /* |
84 | * CPU 0 handles the global timer interrupt job and process accounting | 89 | * CPU 0 handles the global timer interrupt job and process |
85 | * resets count/compare registers to trigger next timer int. | 90 | * accounting resets count/compare registers to trigger next |
91 | * timer int. | ||
86 | */ | 92 | */ |
87 | timer_interrupt(irq, dev_id, regs); | 93 | if (!r2 || (read_c0_cause() & (1 << 26))) |
94 | if (perf_irq(regs)) | ||
95 | goto out; | ||
96 | |||
97 | /* we keep interrupt disabled all the time */ | ||
98 | if (!r2 || (read_c0_cause() & (1 << 30))) | ||
99 | timer_interrupt(irq, NULL, regs); | ||
100 | |||
88 | scroll_display_message(); | 101 | scroll_display_message(); |
89 | } else { | 102 | } else { |
90 | /* Everyone else needs to reset the timer int here as | 103 | /* 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 | local_timer_interrupt (irq, dev_id, regs); | 114 | local_timer_interrupt (irq, dev_id, regs); |
102 | } | 115 | } |
103 | 116 | ||
117 | out: | ||
104 | return IRQ_HANDLED; | 118 | return IRQ_HANDLED; |
105 | } | 119 | } |
106 | 120 | ||
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h index f0121557047d..5cfce7d87a4d 100644 --- a/arch/mips/oprofile/op_impl.h +++ b/arch/mips/oprofile/op_impl.h | |||
@@ -12,8 +12,8 @@ | |||
12 | 12 | ||
13 | struct pt_regs; | 13 | struct pt_regs; |
14 | 14 | ||
15 | extern void null_perf_irq(struct pt_regs *regs); | 15 | extern int null_perf_irq(struct pt_regs *regs); |
16 | extern void (*perf_irq)(struct pt_regs *regs); | 16 | extern int (*perf_irq)(struct pt_regs *regs); |
17 | 17 | ||
18 | /* Per-counter configuration as set via oprofilefs. */ | 18 | /* Per-counter configuration as set via oprofilefs. */ |
19 | struct op_counter_config { | 19 | struct op_counter_config { |
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index d36b64dfcb2f..a4a4aa99ab03 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c | |||
@@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args) | |||
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
117 | static void mipsxx_perfcount_handler(struct pt_regs *regs) | 117 | static int mipsxx_perfcount_handler(struct pt_regs *regs) |
118 | { | 118 | { |
119 | unsigned int counters = op_model_mipsxx.num_counters; | 119 | unsigned int counters = op_model_mipsxx.num_counters; |
120 | unsigned int control; | 120 | unsigned int control; |
121 | unsigned int counter; | 121 | unsigned int counter; |
122 | int handled = 0; | ||
122 | 123 | ||
123 | switch (counters) { | 124 | switch (counters) { |
124 | #define HANDLE_COUNTER(n) \ | 125 | #define HANDLE_COUNTER(n) \ |
@@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs) | |||
129 | (counter & M_COUNTER_OVERFLOW)) { \ | 130 | (counter & M_COUNTER_OVERFLOW)) { \ |
130 | oprofile_add_sample(regs, n); \ | 131 | oprofile_add_sample(regs, n); \ |
131 | write_c0_perfcntr ## n(reg.counter[n]); \ | 132 | write_c0_perfcntr ## n(reg.counter[n]); \ |
133 | handled = 1; \ | ||
132 | } | 134 | } |
133 | HANDLE_COUNTER(3) | 135 | HANDLE_COUNTER(3) |
134 | HANDLE_COUNTER(2) | 136 | HANDLE_COUNTER(2) |
135 | HANDLE_COUNTER(1) | 137 | HANDLE_COUNTER(1) |
136 | HANDLE_COUNTER(0) | 138 | HANDLE_COUNTER(0) |
137 | } | 139 | } |
140 | |||
141 | return handled; | ||
138 | } | 142 | } |
139 | 143 | ||
140 | #define M_CONFIG1_PC (1 << 4) | 144 | #define M_CONFIG1_PC (1 << 4) |