aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/time.c
diff options
context:
space:
mode:
authorChris Dearman <chris@mips.com>2007-05-24 17:24:20 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-06-14 13:25:15 -0400
commitffe9ee4709cf513fb80e9b7e04d214dd8b76a10d (patch)
tree07453e5644806b9c755159e5a4c1fe11dacfcab0 /arch/mips/kernel/time.c
parentb72c05262298cc2ac92edb657f5ea3a97ad5ea3d (diff)
[MIPS] Separate performance counter interrupts
Support for performance counter overflow interrupt that is on a separate interrupt from the timer. Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/time.c')
-rw-r--r--arch/mips/kernel/time.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 751b4a18b133..7def1ff3da94 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -199,6 +199,30 @@ int (*perf_irq)(void) = null_perf_irq;
199EXPORT_SYMBOL(null_perf_irq); 199EXPORT_SYMBOL(null_perf_irq);
200EXPORT_SYMBOL(perf_irq); 200EXPORT_SYMBOL(perf_irq);
201 201
202/*
203 * Performance counter IRQ or -1 if shared with timer
204 */
205int mipsxx_perfcount_irq;
206EXPORT_SYMBOL(mipsxx_perfcount_irq);
207
208/*
209 * Possibly handle a performance counter interrupt.
210 * Return true if the timer interrupt should not be checked
211 */
212static inline int handle_perf_irq (int r2)
213{
214 /*
215 * The performance counter overflow interrupt may be shared with the
216 * timer interrupt (mipsxx_perfcount_irq < 0). If it is and a
217 * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
218 * and we can't reliably determine if a counter interrupt has also
219 * happened (!r2) then don't check for a timer interrupt.
220 */
221 return (mipsxx_perfcount_irq < 0) &&
222 perf_irq() == IRQ_HANDLED &&
223 !r2;
224}
225
202asmlinkage void ll_timer_interrupt(int irq) 226asmlinkage void ll_timer_interrupt(int irq)
203{ 227{
204 int r2 = cpu_has_mips_r2; 228 int r2 = cpu_has_mips_r2;
@@ -206,19 +230,13 @@ asmlinkage void ll_timer_interrupt(int irq)
206 irq_enter(); 230 irq_enter();
207 kstat_this_cpu.irqs[irq]++; 231 kstat_this_cpu.irqs[irq]++;
208 232
209 /* 233 if (handle_perf_irq(r2))
210 * Suckage alert: 234 goto out;
211 * Before R2 of the architecture there was no way to see if a
212 * performance counter interrupt was pending, so we have to run the
213 * performance counter interrupt handler anyway.
214 */
215 if (!r2 || (read_c0_cause() & (1 << 26)))
216 if (perf_irq())
217 goto out;
218 235
219 /* we keep interrupt disabled all the time */ 236 if (r2 && ((read_c0_cause() & (1 << 30)) == 0))
220 if (!r2 || (read_c0_cause() & (1 << 30))) 237 goto out;
221 timer_interrupt(irq, NULL); 238
239 timer_interrupt(irq, NULL);
222 240
223out: 241out:
224 irq_exit(); 242 irq_exit();
@@ -258,7 +276,7 @@ unsigned int mips_hpt_frequency;
258 276
259static struct irqaction timer_irqaction = { 277static struct irqaction timer_irqaction = {
260 .handler = timer_interrupt, 278 .handler = timer_interrupt,
261 .flags = IRQF_DISABLED, 279 .flags = IRQF_DISABLED | IRQF_PERCPU,
262 .name = "timer", 280 .name = "timer",
263}; 281};
264 282