MIPS: Add hook to get C0 performance counter interrupt
The hardware perf event driver and oprofile interpret the global cp0_perfcount_irq differently: in the hardware perf event driver it is an offset from MIPS_CPU_IRQ_BASE and in oprofile it is the actual IRQ number. This still works most of the time since MIPS_CPU_IRQ_BASE is usually 0, but is clearly wrong. Since the performance counter interrupt may vary from platform to platform like the C0 timer interrupt, add the optional get_c0_perfcount_int hook which returns the IRQ number of the performance counter. The hook should return < 0 if the performance counter interrupt is shared with the timer. If the hook is not present, the CPU vector reported in C0_IntCtl (cp0_perfcount_irq) is used. Signed-off-by: Andrew Bresticker <abrestic@chromium.org> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com> Tested-by: Qais Yousef <qais.yousef@imgtec.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Andrew Bresticker <abrestic@chromium.org> Cc: Jeffrey Deans <jeffrey.deans@imgtec.com> Cc: Markos Chandras <markos.chandras@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Qais Yousef <qais.yousef@imgtec.com> Cc: Jonas Gorski <jogo@openwrt.org> Cc: John Crispin <blogic@openwrt.org> Cc: David Daney <ddaney.cavm@gmail.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7805/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:

committed by
Ralf Baechle

parent
079a460176
commit
a669efc4a3
@@ -11,6 +11,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
#include "op_impl.h"
|
||||
|
||||
@@ -35,6 +36,7 @@
|
||||
#define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13)
|
||||
|
||||
static int (*save_perf_irq)(void);
|
||||
static int perfcount_irq;
|
||||
|
||||
/*
|
||||
* XLR has only one set of counters per core. Designate the
|
||||
@@ -431,8 +433,16 @@ static int __init mipsxx_init(void)
|
||||
save_perf_irq = perf_irq;
|
||||
perf_irq = mipsxx_perfcount_handler;
|
||||
|
||||
if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
|
||||
return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
|
||||
if (get_c0_perfcount_int)
|
||||
perfcount_irq = get_c0_perfcount_int();
|
||||
else if ((cp0_perfcount_irq >= 0) &&
|
||||
(cp0_compare_irq != cp0_perfcount_irq))
|
||||
perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
|
||||
else
|
||||
perfcount_irq = -1;
|
||||
|
||||
if (perfcount_irq >= 0)
|
||||
return request_irq(perfcount_irq, mipsxx_perfcount_int,
|
||||
0, "Perfcounter", save_perf_irq);
|
||||
|
||||
return 0;
|
||||
@@ -442,8 +452,8 @@ static void mipsxx_exit(void)
|
||||
{
|
||||
int counters = op_model_mipsxx_ops.num_counters;
|
||||
|
||||
if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq))
|
||||
free_irq(cp0_perfcount_irq, save_perf_irq);
|
||||
if (perfcount_irq >= 0)
|
||||
free_irq(perfcount_irq, save_perf_irq);
|
||||
|
||||
counters = counters_per_cpu_to_total(counters);
|
||||
on_each_cpu(reset_counters, (void *)(long)counters, 1);
|
||||
|
Reference in New Issue
Block a user