When perf is used in system mode, i.e. specifying a set of CPUs to count (perf -a -C cpu), event->cpu is set to the CPU number on which events should be counted. The current BMIPS500 variation of mipsxx_pmu_enable_event only over sets the counter to count the current CPU, so system mode does not work. Fix this by removing this BMIPS5000 specific path and integrating it with the generic one. Since BMIPS5000 uses specific extensions to the perf control register, different fields must be set up to count the relevant CPU. Signed-off-by: Matt Redfearn <matt.redfearn@xxxxxxxx> Tested-by: Florian Fainelli <f.fainelli@xxxxxxxxx> --- Changes in v4: Fix compiler error from BRCM_PERFCTRL_VPEID flagged by Florian. Changes in v2: New patch to fix BMIPS5000 system mode perf. arch/mips/include/asm/mipsregs.h | 1 + arch/mips/kernel/perf_event_mipsxx.c | 17 ++++++----------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index a4baaaa02bc..6b0b06d2683 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -735,6 +735,7 @@ #define MIPS_PERFCTRL_MT_EN_TC (_ULCAST_(2) << 20) /* PerfCnt control register MT extensions used by BMIPS5000 */ +#define BRCM_PERFCTRL_VPEID(v) (_ULCAST_(1) << (12 + (v))) #define BRCM_PERFCTRL_TC (_ULCAST_(1) << 30) /* PerfCnt control register MT extensions used by Netlogic XLR */ diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 5b8811643e6..77d7167e303 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -364,16 +364,7 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) /* Make sure interrupt enabled. */ MIPS_PERFCTRL_IE; -#ifdef CONFIG_CPU_BMIPS5000 - { - /* enable the counter for the calling thread */ - unsigned int vpe_id; - - vpe_id = smp_processor_id() & MIPS_CPUID_TO_COUNTER_MASK; - cpuc->saved_ctrl[idx] |= BIT(12 + vpe_id) | BRCM_PERFCTRL_TC; - } -#else -#ifdef CONFIG_MIPS_MT_SMP +#if defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_CPU_BMIPS5000) if (range > V) { /* The counter is processor wide. Set it up to count all TCs. */ pr_debug("Enabling perf counter for all TCs\n"); @@ -390,12 +381,16 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) */ cpu = (event->cpu >= 0) ? event->cpu : smp_processor_id(); +#if defined(CONFIG_CPU_BMIPS5000) + ctrl = BRCM_PERFCTRL_VPEID(cpu & MIPS_CPUID_TO_COUNTER_MASK); + ctrl |= BRCM_PERFCTRL_TC; +#else ctrl = M_PERFCTL_VPEID(cpu_vpe_id(&cpu_data[cpu])); ctrl |= M_TC_EN_VPE; +#endif cpuc->saved_ctrl[idx] |= ctrl; pr_debug("Enabling perf counter for CPU%d\n", cpu); } -#endif /* CONFIG_CPU_BMIPS5000 */ /* * We do not actually let the counter run. Leave it until start(). */ -- 2.7.4