Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756867Ab1CIIoK (ORCPT ); Wed, 9 Mar 2011 03:44:10 -0500 Received: from mail-qw0-f46.google.com ([209.85.216.46]:54394 "EHLO mail-qw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756512Ab1CIIoI convert rfc822-to-8bit (ORCPT ); Wed, 9 Mar 2011 03:44:08 -0500 MIME-Version: 1.0 X-Originating-IP: [81.245.155.12] In-Reply-To: <1299608733-28514-1-git-send-email-sheetals@codeaurora.org> References: <1299608733-28514-1-git-send-email-sheetals@codeaurora.org> Date: Wed, 9 Mar 2011 09:44:06 +0100 Message-ID: Subject: Re: [PATCH v3 2/3] [ARM] perfevents: Add support for Scorpion performance monitors From: Jean Pihet To: Sheetal Sahasrabudhe Cc: linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, jamie.iles@picochip.com, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 32886 Lines: 776 HI Sheetal, Thanks for the update. I still have some nitpicking comments below. On Tue, Mar 8, 2011 at 7:25 PM, Sheetal Sahasrabudhe wrote: > This commit adds support for performance monitors provided by > Qualcomm Scorpion and ScorpionMP processor to perfevents. > > Signed-off-by: Sheetal Sahasrabudhe > Reviewed-by: Jean Pihet > Reviewed-by: Will Deacon > --- > ?arch/arm/include/asm/perf_event.h | ? ?2 + > ?arch/arm/kernel/perf_event.c ? ? ?| ? 11 + > ?arch/arm/kernel/perf_event_msm.c ?| ?665 +++++++++++++++++++++++++++++++++++++ > ?3 files changed, 678 insertions(+), 0 deletions(-) > ?create mode 100644 arch/arm/kernel/perf_event_msm.c > > diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h > index c4aa4e8..a549d82 100644 > --- a/arch/arm/include/asm/perf_event.h > +++ b/arch/arm/include/asm/perf_event.h > @@ -24,6 +24,8 @@ enum arm_perf_pmu_ids { > ? ? ? ?ARM_PERF_PMU_ID_V6MP, > ? ? ? ?ARM_PERF_PMU_ID_CA8, > ? ? ? ?ARM_PERF_PMU_ID_CA9, > + ? ? ? ARM_PERF_PMU_ID_SCORPION, > + ? ? ? ARM_PERF_PMU_ID_SCORPIONMP, > ? ? ? ?ARM_NUM_PMU_IDS, > ?}; > > diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c > index d150ad1..b76db9f 100644 > --- a/arch/arm/kernel/perf_event.c > +++ b/arch/arm/kernel/perf_event.c > @@ -608,6 +608,7 @@ static struct pmu pmu = { > ?#include "perf_event_xscale.c" > ?#include "perf_event_v6.c" > ?#include "perf_event_v7.c" > +#include "perf_event_msm.c" > > ?static int __init > ?init_hw_perf_events(void) > @@ -645,6 +646,16 @@ init_hw_perf_events(void) > ? ? ? ? ? ? ? ? ? ? ? ?armpmu = xscale2pmu_init(); > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ?} > + ? ? ? /* Qualcomm CPUs */ > + ? ? ? } else if (0x51 == implementor) { > + ? ? ? ? ? ? ? switch (part_number) { > + ? ? ? ? ? ? ? case 0x00F0: ? ?/* 8x50 & 7x30*/ > + ? ? ? ? ? ? ? ? ? ? ? armpmu = armv7_scorpion_pmu_init(); > + ? ? ? ? ? ? ? ? ? ? ? break; > + ? ? ? ? ? ? ? case 0x02D0: ? ?/* 8x60 */ > + ? ? ? ? ? ? ? ? ? ? ? armpmu = armv7_scorpionmp_pmu_init(); > + ? ? ? ? ? ? ? ? ? ? ? break; > + ? ? ? ? ? ? ? } > ? ? ? ?} > > ? ? ? ?if (armpmu) { > diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c > new file mode 100644 > index 0000000..326c2a9 > --- /dev/null > +++ b/arch/arm/kernel/perf_event_msm.c > @@ -0,0 +1,665 @@ > +/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. > +* > +* This program is free software; you can redistribute it and/or modify > +* it under the terms of the GNU General Public License version 2 and > +* only version 2 as published by the Free Software Foundation. > +* > +* This program is distributed in the hope that it will be useful, > +* but WITHOUT ANY WARRANTY; without even the implied warranty of > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ?See the > +* GNU General Public License for more details. > +*/ Multi-lines commenting style > + > +#include > +#include > +#include "../vfp/vfpinstr.h" > + > +#ifdef CONFIG_CPU_V7 > +enum scorpion_perf_common { > + ? ? ? SCORPION_EVT_START_IDX ? ? ? ? ? ? ? ? ?= 0x4c, > + ? ? ? SCORPION_ICACHE_EXPL_INV ? ? ? ? ? ? ? ?= 0x4c, > + ? ? ? SCORPION_ICACHE_MISS ? ? ? ? ? ? ? ? ? ?= 0x4d, > + ? ? ? SCORPION_ICACHE_ACCESS ? ? ? ? ? ? ? ? ?= 0x4e, > + ? ? ? SCORPION_ICACHE_CACHEREQ_L2 ? ? ? ? ? ? = 0x4f, > + ? ? ? SCORPION_ICACHE_NOCACHE_L2 ? ? ? ? ? ? ?= 0x50, > + ? ? ? SCORPION_HIQUP_NOPED ? ? ? ? ? ? ? ? ? ?= 0x51, > + ? ? ? SCORPION_DATA_ABORT ? ? ? ? ? ? ? ? ? ? = 0x52, > + ? ? ? SCORPION_IRQ ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x53, > + ? ? ? SCORPION_FIQ ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x54, > + ? ? ? SCORPION_ALL_EXCPT ? ? ? ? ? ? ? ? ? ? ?= 0x55, > + ? ? ? SCORPION_UNDEF ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x56, > + ? ? ? SCORPION_SVC ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x57, > + ? ? ? SCORPION_SMC ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x58, > + ? ? ? SCORPION_PREFETCH_ABORT ? ? ? ? ? ? ? ? = 0x59, > + ? ? ? SCORPION_INDEX_CHECK ? ? ? ? ? ? ? ? ? ?= 0x5a, > + ? ? ? SCORPION_NULL_CHECK ? ? ? ? ? ? ? ? ? ? = 0x5b, > + ? ? ? SCORPION_EXPL_ICIALLU ? ? ? ? ? ? ? ? ? = 0x5c, > + ? ? ? SCORPION_IMPL_ICIALLU ? ? ? ? ? ? ? ? ? = 0x5d, > + ? ? ? SCORPION_NONICIALLU_BTAC_INV ? ? ? ? ? ?= 0x5e, > + ? ? ? SCORPION_ICIMVAU_IMPL_ICIALLU ? ? ? ? ? = 0x5f, > + ? ? ? SCORPION_SPIPE_ONLY_CYCLES ? ? ? ? ? ? ?= 0x60, > + ? ? ? SCORPION_XPIPE_ONLY_CYCLES ? ? ? ? ? ? ?= 0x61, > + ? ? ? SCORPION_DUAL_CYCLES ? ? ? ? ? ? ? ? ? ?= 0x62, > + ? ? ? SCORPION_DISPATCH_ANY_CYCLES ? ? ? ? ? ?= 0x63, > + ? ? ? SCORPION_FIFO_FULLBLK_CMT ? ? ? ? ? ? ? = 0x64, > + ? ? ? SCORPION_FAIL_COND_INST ? ? ? ? ? ? ? ? = 0x65, > + ? ? ? SCORPION_PASS_COND_INST ? ? ? ? ? ? ? ? = 0x66, > + ? ? ? SCORPION_ALLOW_VU_CLK ? ? ? ? ? ? ? ? ? = 0x67, > + ? ? ? SCORPION_VU_IDLE ? ? ? ? ? ? ? ? ? ? ? ?= 0x68, > + ? ? ? SCORPION_ALLOW_L2_CLK ? ? ? ? ? ? ? ? ? = 0x69, > + ? ? ? SCORPION_L2_IDLE ? ? ? ? ? ? ? ? ? ? ? ?= 0x6a, > + ? ? ? SCORPION_DTLB_IMPL_INV_SCTLR_DACR ? ? ? = 0x6b, > + ? ? ? SCORPION_DTLB_EXPL_INV ? ? ? ? ? ? ? ? ?= 0x6c, > + ? ? ? SCORPION_DTLB_MISS ? ? ? ? ? ? ? ? ? ? ?= 0x6d, > + ? ? ? SCORPION_DTLB_ACCESS ? ? ? ? ? ? ? ? ? ?= 0x6e, > + ? ? ? SCORPION_ITLB_MISS ? ? ? ? ? ? ? ? ? ? ?= 0x6f, > + ? ? ? SCORPION_ITLB_IMPL_INV ? ? ? ? ? ? ? ? ?= 0x70, > + ? ? ? SCORPION_ITLB_EXPL_INV ? ? ? ? ? ? ? ? ?= 0x71, > + ? ? ? SCORPION_UTLB_D_MISS ? ? ? ? ? ? ? ? ? ?= 0x72, > + ? ? ? SCORPION_UTLB_D_ACCESS ? ? ? ? ? ? ? ? ?= 0x73, > + ? ? ? SCORPION_UTLB_I_MISS ? ? ? ? ? ? ? ? ? ?= 0x74, > + ? ? ? SCORPION_UTLB_I_ACCESS ? ? ? ? ? ? ? ? ?= 0x75, > + ? ? ? SCORPION_UTLB_INV_ASID ? ? ? ? ? ? ? ? ?= 0x76, > + ? ? ? SCORPION_UTLB_INV_MVA ? ? ? ? ? ? ? ? ? = 0x77, > + ? ? ? SCORPION_UTLB_INV_ALL ? ? ? ? ? ? ? ? ? = 0x78, > + ? ? ? SCORPION_S2_HOLD_RDQ_UNAVAIL ? ? ? ? ? ?= 0x79, > + ? ? ? SCORPION_S2_HOLD ? ? ? ? ? ? ? ? ? ? ? ?= 0x7a, > + ? ? ? SCORPION_S2_HOLD_DEV_OP ? ? ? ? ? ? ? ? = 0x7b, > + ? ? ? SCORPION_S2_HOLD_ORDER ? ? ? ? ? ? ? ? ?= 0x7c, > + ? ? ? SCORPION_S2_HOLD_BARRIER ? ? ? ? ? ? ? ?= 0x7d, > + ? ? ? SCORPION_VIU_DUAL_CYCLE ? ? ? ? ? ? ? ? = 0x7e, > + ? ? ? SCORPION_VIU_SINGLE_CYCLE ? ? ? ? ? ? ? = 0x7f, > + ? ? ? SCORPION_VX_PIPE_WAR_STALL_CYCLES ? ? ? = 0x80, > + ? ? ? SCORPION_VX_PIPE_WAW_STALL_CYCLES ? ? ? = 0x81, > + ? ? ? SCORPION_VX_PIPE_RAW_STALL_CYCLES ? ? ? = 0x82, > + ? ? ? SCORPION_VX_PIPE_LOAD_USE_STALL ? ? ? ? = 0x83, > + ? ? ? SCORPION_VS_PIPE_WAR_STALL_CYCLES ? ? ? = 0x84, > + ? ? ? SCORPION_VS_PIPE_WAW_STALL_CYCLES ? ? ? = 0x85, > + ? ? ? SCORPION_VS_PIPE_RAW_STALL_CYCLES ? ? ? = 0x86, > + ? ? ? SCORPION_EXCEPTIONS_INV_OPERATION ? ? ? = 0x87, > + ? ? ? SCORPION_EXCEPTIONS_DIV_BY_ZERO ? ? ? ? = 0x88, > + ? ? ? SCORPION_COND_INST_FAIL_VX_PIPE ? ? ? ? = 0x89, > + ? ? ? SCORPION_COND_INST_FAIL_VS_PIPE ? ? ? ? = 0x8a, > + ? ? ? SCORPION_EXCEPTIONS_OVERFLOW ? ? ? ? ? ?= 0x8b, > + ? ? ? SCORPION_EXCEPTIONS_UNDERFLOW ? ? ? ? ? = 0x8c, > + ? ? ? SCORPION_EXCEPTIONS_DENORM ? ? ? ? ? ? ?= 0x8d, > +}; > + > +enum scorpion_perf_smp { > + ? ? ? SCORPIONMP_NUM_BARRIERS ? ? ? ? ? ? ? ? = 0x8e, > + ? ? ? SCORPIONMP_BARRIER_CYCLES ? ? ? ? ? ? ? = 0x8f, > +}; > + > +enum scorpion_perf_up { > + ? ? ? SCORPION_BANK_AB_HIT ? ? ? ? ? ? ? ? ? ?= 0x8e, > + ? ? ? SCORPION_BANK_AB_ACCESS ? ? ? ? ? ? ? ? = 0x8f, > + ? ? ? SCORPION_BANK_CD_HIT ? ? ? ? ? ? ? ? ? ?= 0x90, > + ? ? ? SCORPION_BANK_CD_ACCESS ? ? ? ? ? ? ? ? = 0x91, > + ? ? ? SCORPION_BANK_AB_DSIDE_HIT ? ? ? ? ? ? ?= 0x92, > + ? ? ? SCORPION_BANK_AB_DSIDE_ACCESS ? ? ? ? ? = 0x93, > + ? ? ? SCORPION_BANK_CD_DSIDE_HIT ? ? ? ? ? ? ?= 0x94, > + ? ? ? SCORPION_BANK_CD_DSIDE_ACCESS ? ? ? ? ? = 0x95, > + ? ? ? SCORPION_BANK_AB_ISIDE_HIT ? ? ? ? ? ? ?= 0x96, > + ? ? ? SCORPION_BANK_AB_ISIDE_ACCESS ? ? ? ? ? = 0x97, > + ? ? ? SCORPION_BANK_CD_ISIDE_HIT ? ? ? ? ? ? ?= 0x98, > + ? ? ? SCORPION_BANK_CD_ISIDE_ACCESS ? ? ? ? ? = 0x99, > + ? ? ? SCORPION_ISIDE_RD_WAIT ? ? ? ? ? ? ? ? ?= 0x9a, > + ? ? ? SCORPION_DSIDE_RD_WAIT ? ? ? ? ? ? ? ? ?= 0x9b, > + ? ? ? SCORPION_BANK_BYPASS_WRITE ? ? ? ? ? ? ?= 0x9c, > + ? ? ? SCORPION_BANK_AB_NON_CASTOUT ? ? ? ? ? ?= 0x9d, > + ? ? ? SCORPION_BANK_AB_L2_CASTOUT ? ? ? ? ? ? = 0x9e, > + ? ? ? SCORPION_BANK_CD_NON_CASTOUT ? ? ? ? ? ?= 0x9f, > + ? ? ? SCORPION_BANK_CD_L2_CASTOUT ? ? ? ? ? ? = 0xa0, > +}; > + > +static const unsigned armv7_scorpion_perf_map[PERF_COUNT_HW_MAX] = { > + ? ? ? [PERF_COUNT_HW_CPU_CYCLES] ? ? ? ? ?= ARMV7_PERFCTR_CPU_CYCLES, > + ? ? ? [PERF_COUNT_HW_INSTRUCTIONS] ? ? ? ?= ARMV7_PERFCTR_INSTR_EXECUTED, > + ? ? ? [PERF_COUNT_HW_CACHE_REFERENCES] ? ?= HW_OP_UNSUPPORTED, > + ? ? ? [PERF_COUNT_HW_CACHE_MISSES] ? ? ? ?= HW_OP_UNSUPPORTED, > + ? ? ? [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, > + ? ? ? [PERF_COUNT_HW_BRANCH_MISSES] ? ? ? = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, > + ? ? ? [PERF_COUNT_HW_BUS_CYCLES] ? ? ? ? ?= ARMV7_PERFCTR_CLOCK_CYCLES, > +}; > + > +static const unsigned armv7_scorpion_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [PERF_COUNT_HW_CACHE_OP_MAX] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [PERF_COUNT_HW_CACHE_RESULT_MAX] = { > + ? ? ? [C(L1D)] = { > + ? ? ? ? ? ? ? /* > + ? ? ? ? ? ? ? ?* The performance counters don't differentiate between read > + ? ? ? ? ? ? ? ?* and write accesses/misses so this isn't strictly correct, > + ? ? ? ? ? ? ? ?* but it's the best we can do. Writes and reads get > + ? ? ? ? ? ? ? ?* combined. > + ? ? ? ? ? ? ? ?*/ > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= ARMV7_PERFCTR_DCACHE_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= ARMV7_PERFCTR_DCACHE_REFILL, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= ARMV7_PERFCTR_DCACHE_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= ARMV7_PERFCTR_DCACHE_REFILL, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > + ? ? ? [C(L1I)] = { > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= SCORPION_ICACHE_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_ICACHE_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= SCORPION_ICACHE_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_ICACHE_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > + ? ? ? [C(LL)] = { > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > + ? ? ? [C(DTLB)] = { > + ? ? ? ? ? ? ? /* > + ? ? ? ? ? ? ? ?* Only ITLB misses and DTLB refills are supported. > + ? ? ? ? ? ? ? ?* If users want the DTLB refills misses a raw counter > + ? ? ? ? ? ? ? ?* must be used. > + ? ? ? ? ? ? ? ?*/ > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= SCORPION_DTLB_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_DTLB_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= SCORPION_DTLB_ACCESS, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_DTLB_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > + ? ? ? [C(ITLB)] = { > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_ITLB_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= SCORPION_ITLB_MISS, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > + ? ? ? [C(BPU)] = { > + ? ? ? ? ? ? ? [C(OP_READ)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ARMV7_PERFCTR_PC_BRANCH_MIS_USED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ARMV7_PERFCTR_PC_BRANCH_MIS_USED, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_WRITE)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ARMV7_PERFCTR_PC_BRANCH_MIS_USED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = ARMV7_PERFCTR_PC_BRANCH_MIS_USED, > + ? ? ? ? ? ? ? }, > + ? ? ? ? ? ? ? [C(OP_PREFETCH)] = { > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_ACCESS)] ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? ? ? ? ? [C(RESULT_MISS)] ? ? ? ?= CACHE_OP_UNSUPPORTED, > + ? ? ? ? ? ? ? }, > + ? ? ? }, > +}; > + > +struct scorpion_evt { > + ? ? ? /* > + ? ? ? * The scorpion_evt_type field corresponds to the actual Scorpion > + ? ? ? * event codes. These map many-to-one to the armv7 defined codes > + ? ? ? */ > + ? ? ? u32 scorpion_evt_type; > + > + ? ? ? /* > + ? ? ? * The group_setval field corresponds to the value that the group > + ? ? ? * register needs to be set to. This value is deduced from the row > + ? ? ? * and column that the event belongs to in the event table > + ? ? ? */ > + ? ? ? u32 group_setval; > + > + ? ? ? /* > + ? ? ? * The groupcode corresponds to the group that the event belongs to. > + ? ? ? * Scorpion has 5 groups of events LPM0, LPM1, LPM2, L2LPM and VLPM > + ? ? ? * going from 0 to 4 in terms of the codes used > + ? ? ? */ > + ? ? ? u8 groupcode; > + > + ? ? ? /* > + ? ? ? * The armv7_evt_type field corresponds to the armv7 defined event > + ? ? ? * code that the Scorpion events map to > + ? ? ? */ > + ? ? ? u32 armv7_evt_type; > +}; > + > +static const struct scorpion_evt scorpion_event[] = { > + ? ? ? {SCORPION_ICACHE_EXPL_INV, ? ? ? ? ? ? ?0x80000500, 0, 0x4d}, > + ? ? ? {SCORPION_ICACHE_MISS, ? ? ? ? ? ? ? ? ?0x80050000, 0, 0x4e}, > + ? ? ? {SCORPION_ICACHE_ACCESS, ? ? ? ? ? ? ? ?0x85000000, 0, 0x4f}, > + ? ? ? {SCORPION_ICACHE_CACHEREQ_L2, ? ? ? ? ? 0x86000000, 0, 0x4f}, > + ? ? ? {SCORPION_ICACHE_NOCACHE_L2, ? ? ? ? ? ?0x87000000, 0, 0x4f}, > + ? ? ? {SCORPION_HIQUP_NOPED, ? ? ? ? ? ? ? ? ?0x80080000, 0, 0x4e}, > + ? ? ? {SCORPION_DATA_ABORT, ? ? ? ? ? ? ? ? ? 0x8000000a, 0, 0x4c}, > + ? ? ? {SCORPION_IRQ, ? ? ? ? ? ? ? ? ? ? ? ? ?0x80000a00, 0, 0x4d}, > + ? ? ? {SCORPION_FIQ, ? ? ? ? ? ? ? ? ? ? ? ? ?0x800a0000, 0, 0x4e}, > + ? ? ? {SCORPION_ALL_EXCPT, ? ? ? ? ? ? ? ? ? ?0x8a000000, 0, 0x4f}, > + ? ? ? {SCORPION_UNDEF, ? ? ? ? ? ? ? ? ? ? ? ?0x8000000b, 0, 0x4c}, > + ? ? ? {SCORPION_SVC, ? ? ? ? ? ? ? ? ? ? ? ? ?0x80000b00, 0, 0x4d}, > + ? ? ? {SCORPION_SMC, ? ? ? ? ? ? ? ? ? ? ? ? ?0x800b0000, 0, 0x4e}, > + ? ? ? {SCORPION_PREFETCH_ABORT, ? ? ? ? ? ? ? 0x8b000000, 0, 0x4f}, > + ? ? ? {SCORPION_INDEX_CHECK, ? ? ? ? ? ? ? ? ?0x8000000c, 0, 0x4c}, > + ? ? ? {SCORPION_NULL_CHECK, ? ? ? ? ? ? ? ? ? 0x80000c00, 0, 0x4d}, > + ? ? ? {SCORPION_EXPL_ICIALLU, ? ? ? ? ? ? ? ? 0x8000000d, 0, 0x4c}, > + ? ? ? {SCORPION_IMPL_ICIALLU, ? ? ? ? ? ? ? ? 0x80000d00, 0, 0x4d}, > + ? ? ? {SCORPION_NONICIALLU_BTAC_INV, ? ? ? ? ?0x800d0000, 0, 0x4e}, > + ? ? ? {SCORPION_ICIMVAU_IMPL_ICIALLU, ? ? ? ? 0x8d000000, 0, 0x4f}, > + > + ? ? ? {SCORPION_SPIPE_ONLY_CYCLES, ? ? ? ? ? ?0x80000600, 1, 0x51}, > + ? ? ? {SCORPION_XPIPE_ONLY_CYCLES, ? ? ? ? ? ?0x80060000, 1, 0x52}, > + ? ? ? {SCORPION_DUAL_CYCLES, ? ? ? ? ? ? ? ? ?0x86000000, 1, 0x53}, > + ? ? ? {SCORPION_DISPATCH_ANY_CYCLES, ? ? ? ? ?0x89000000, 1, 0x53}, > + ? ? ? {SCORPION_FIFO_FULLBLK_CMT, ? ? ? ? ? ? 0x8000000d, 1, 0x50}, > + ? ? ? {SCORPION_FAIL_COND_INST, ? ? ? ? ? ? ? 0x800d0000, 1, 0x52}, > + ? ? ? {SCORPION_PASS_COND_INST, ? ? ? ? ? ? ? 0x8d000000, 1, 0x53}, > + ? ? ? {SCORPION_ALLOW_VU_CLK, ? ? ? ? ? ? ? ? 0x8000000e, 1, 0x50}, > + ? ? ? {SCORPION_VU_IDLE, ? ? ? ? ? ? ? ? ? ? ?0x80000e00, 1, 0x51}, > + ? ? ? {SCORPION_ALLOW_L2_CLK, ? ? ? ? ? ? ? ? 0x800e0000, 1, 0x52}, > + ? ? ? {SCORPION_L2_IDLE, ? ? ? ? ? ? ? ? ? ? ?0x8e000000, 1, 0x53}, > + > + ? ? ? {SCORPION_DTLB_IMPL_INV_SCTLR_DACR, ? ? 0x80000001, 2, 0x54}, > + ? ? ? {SCORPION_DTLB_EXPL_INV, ? ? ? ? ? ? ? ?0x80000100, 2, 0x55}, > + ? ? ? {SCORPION_DTLB_MISS, ? ? ? ? ? ? ? ? ? ?0x80010000, 2, 0x56}, > + ? ? ? {SCORPION_DTLB_ACCESS, ? ? ? ? ? ? ? ? ?0x81000000, 2, 0x57}, > + ? ? ? {SCORPION_ITLB_MISS, ? ? ? ? ? ? ? ? ? ?0x80000200, 2, 0x55}, > + ? ? ? {SCORPION_ITLB_IMPL_INV, ? ? ? ? ? ? ? ?0x80020000, 2, 0x56}, > + ? ? ? {SCORPION_ITLB_EXPL_INV, ? ? ? ? ? ? ? ?0x82000000, 2, 0x57}, > + ? ? ? {SCORPION_UTLB_D_MISS, ? ? ? ? ? ? ? ? ?0x80000003, 2, 0x54}, > + ? ? ? {SCORPION_UTLB_D_ACCESS, ? ? ? ? ? ? ? ?0x80000300, 2, 0x55}, > + ? ? ? {SCORPION_UTLB_I_MISS, ? ? ? ? ? ? ? ? ?0x80030000, 2, 0x56}, > + ? ? ? {SCORPION_UTLB_I_ACCESS, ? ? ? ? ? ? ? ?0x83000000, 2, 0x57}, > + ? ? ? {SCORPION_UTLB_INV_ASID, ? ? ? ? ? ? ? ?0x80000400, 2, 0x55}, > + ? ? ? {SCORPION_UTLB_INV_MVA, ? ? ? ? ? ? ? ? 0x80040000, 2, 0x56}, > + ? ? ? {SCORPION_UTLB_INV_ALL, ? ? ? ? ? ? ? ? 0x84000000, 2, 0x57}, > + ? ? ? {SCORPION_S2_HOLD_RDQ_UNAVAIL, ? ? ? ? ?0x80000800, 2, 0x55}, > + ? ? ? {SCORPION_S2_HOLD, ? ? ? ? ? ? ? ? ? ? ?0x88000000, 2, 0x57}, > + ? ? ? {SCORPION_S2_HOLD_DEV_OP, ? ? ? ? ? ? ? 0x80000900, 2, 0x55}, > + ? ? ? {SCORPION_S2_HOLD_ORDER, ? ? ? ? ? ? ? ?0x80090000, 2, 0x56}, > + ? ? ? {SCORPION_S2_HOLD_BARRIER, ? ? ? ? ? ? ?0x89000000, 2, 0x57}, > + > + ? ? ? {SCORPION_VIU_DUAL_CYCLE, ? ? ? ? ? ? ? 0x80000001, 4, 0x5c}, > + ? ? ? {SCORPION_VIU_SINGLE_CYCLE, ? ? ? ? ? ? 0x80000100, 4, 0x5d}, > + ? ? ? {SCORPION_VX_PIPE_WAR_STALL_CYCLES, ? ? 0x80000005, 4, 0x5c}, > + ? ? ? {SCORPION_VX_PIPE_WAW_STALL_CYCLES, ? ? 0x80000500, 4, 0x5d}, > + ? ? ? {SCORPION_VX_PIPE_RAW_STALL_CYCLES, ? ? 0x80050000, 4, 0x5e}, > + ? ? ? {SCORPION_VX_PIPE_LOAD_USE_STALL, ? ? ? 0x80000007, 4, 0x5c}, > + ? ? ? {SCORPION_VS_PIPE_WAR_STALL_CYCLES, ? ? 0x80000008, 4, 0x5c}, > + ? ? ? {SCORPION_VS_PIPE_WAW_STALL_CYCLES, ? ? 0x80000800, 4, 0x5d}, > + ? ? ? {SCORPION_VS_PIPE_RAW_STALL_CYCLES, ? ? 0x80080000, 4, 0x5e}, > + ? ? ? {SCORPION_EXCEPTIONS_INV_OPERATION, ? ? 0x8000000b, 4, 0x5c}, > + ? ? ? {SCORPION_EXCEPTIONS_DIV_BY_ZERO, ? ? ? 0x80000b00, 4, 0x5d}, > + ? ? ? {SCORPION_COND_INST_FAIL_VX_PIPE, ? ? ? 0x800b0000, 4, 0x5e}, > + ? ? ? {SCORPION_COND_INST_FAIL_VS_PIPE, ? ? ? 0x8b000000, 4, 0x5f}, > + ? ? ? {SCORPION_EXCEPTIONS_OVERFLOW, ? ? ? ? ?0x8000000c, 4, 0x5c}, > + ? ? ? {SCORPION_EXCEPTIONS_UNDERFLOW, ? ? ? ? 0x80000c00, 4, 0x5d}, > + ? ? ? {SCORPION_EXCEPTIONS_DENORM, ? ? ? ? ? ?0x8c000000, 4, 0x5f}, > + > +#ifdef CONFIG_ARCH_MSM_SCORPIONMP > + ? ? ? {SCORPIONMP_NUM_BARRIERS, ? ? ? ? ? ? ? 0x80000e00, 3, 0x59}, > + ? ? ? {SCORPIONMP_BARRIER_CYCLES, ? ? ? ? ? ? 0x800e0000, 3, 0x5a}, > +#else > + ? ? ? {SCORPION_BANK_AB_HIT, ? ? ? ? ? ? ? ? ?0x80000001, 3, 0x58}, > + ? ? ? {SCORPION_BANK_AB_ACCESS, ? ? ? ? ? ? ? 0x80000100, 3, 0x59}, > + ? ? ? {SCORPION_BANK_CD_HIT, ? ? ? ? ? ? ? ? ?0x80010000, 3, 0x5a}, > + ? ? ? {SCORPION_BANK_CD_ACCESS, ? ? ? ? ? ? ? 0x81000000, 3, 0x5b}, > + ? ? ? {SCORPION_BANK_AB_DSIDE_HIT, ? ? ? ? ? ?0x80000002, 3, 0x58}, > + ? ? ? {SCORPION_BANK_AB_DSIDE_ACCESS, ? ? ? ? 0x80000200, 3, 0x59}, > + ? ? ? {SCORPION_BANK_CD_DSIDE_HIT, ? ? ? ? ? ?0x80020000, 3, 0x5a}, > + ? ? ? {SCORPION_BANK_CD_DSIDE_ACCESS, ? ? ? ? 0x82000000, 3, 0x5b}, > + ? ? ? {SCORPION_BANK_AB_ISIDE_HIT, ? ? ? ? ? ?0x80000003, 3, 0x58}, > + ? ? ? {SCORPION_BANK_AB_ISIDE_ACCESS, ? ? ? ? 0x80000300, 3, 0x59}, > + ? ? ? {SCORPION_BANK_CD_ISIDE_HIT, ? ? ? ? ? ?0x80030000, 3, 0x5a}, > + ? ? ? {SCORPION_BANK_CD_ISIDE_ACCESS, ? ? ? ? 0x83000000, 3, 0x5b}, > + ? ? ? {SCORPION_ISIDE_RD_WAIT, ? ? ? ? ? ? ? ?0x80000009, 3, 0x58}, > + ? ? ? {SCORPION_DSIDE_RD_WAIT, ? ? ? ? ? ? ? ?0x80090000, 3, 0x5a}, > + ? ? ? {SCORPION_BANK_BYPASS_WRITE, ? ? ? ? ? ?0x8000000a, 3, 0x58}, > + ? ? ? {SCORPION_BANK_AB_NON_CASTOUT, ? ? ? ? ?0x8000000c, 3, 0x58}, > + ? ? ? {SCORPION_BANK_AB_L2_CASTOUT, ? ? ? ? ? 0x80000c00, 3, 0x59}, > + ? ? ? {SCORPION_BANK_CD_NON_CASTOUT, ? ? ? ? ?0x800c0000, 3, 0x5a}, > + ? ? ? {SCORPION_BANK_CD_L2_CASTOUT, ? ? ? ? ? 0x8c000000, 3, 0x5b}, > +#endif > +}; > + > +static unsigned int get_scorpion_evtinfo(unsigned int scorpion_evt_type, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct scorpion_evt *evtinfo) > +{ > + ? ? ? u32 idx; Needs an extra blank line here. > + ? ? ? if (scorpion_evt_type < SCORPION_EVT_START_IDX || scorpion_evt_type >= > + ? ? ? ? ? ? ? (ARRAY_SIZE(scorpion_event) + SCORPION_EVT_START_IDX)) > + ? ? ? ? ? ? ? return -EINVAL; > + ? ? ? idx = scorpion_evt_type - SCORPION_EVT_START_IDX; > + ? ? ? if (scorpion_event[idx].scorpion_evt_type == scorpion_evt_type) { > + ? ? ? ? ? ? ? evtinfo->group_setval = scorpion_event[idx].group_setval; > + ? ? ? ? ? ? ? evtinfo->groupcode = scorpion_event[idx].groupcode; > + ? ? ? ? ? ? ? evtinfo->armv7_evt_type = scorpion_event[idx].armv7_evt_type; > + ? ? ? ? ? ? ? return scorpion_event[idx].armv7_evt_type; > + ? ? ? } > + ? ? ? return -EINVAL; > +} > + > +static u32 scorpion_read_lpm0(void) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val)); > + ? ? ? return val; > +} > + > +static void scorpion_write_lpm0(u32 val) > +{ > + ? ? ? asm volatile("mcr p15, 0, %0, c15, c0, 0" : : "r" (val)); > +} > + > +static u32 scorpion_read_lpm1(void) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); > + ? ? ? return val; > +} > + > +static void scorpion_write_lpm1(u32 val) > +{ > + ? ? ? asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val)); > +} > + > +static u32 scorpion_read_lpm2(void) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val)); > + ? ? ? return val; > +} > + > +static void scorpion_write_lpm2(u32 val) > +{ > + ? ? ? asm volatile("mcr p15, 2, %0, c15, c0, 0" : : "r" (val)); > +} > + > +static u32 scorpion_read_l2lpm(void) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val)); > + ? ? ? return val; > +} > + > +static void scorpion_write_l2lpm(u32 val) > +{ > + ? ? ? asm volatile("mcr p15, 3, %0, c15, c2, 0" : : "r" (val)); > +} > + > +static u32 scorpion_read_vlpm(void) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val)); > + ? ? ? return val; > +} > + > +static void scorpion_write_vlpm(u32 val) > +{ > + ? ? ? asm volatile("mcr p10, 7, %0, c11, c0, 0" : : "r" (val)); > +} > + > +/*The Scorpion processor supports performance monitoring for Venum unit. > + * In order to access the performance monitor registers corresponding to > + * VFP, CPACR and FPEXC registers need to be set up beforehand. > + * Also, they need to be recovered once the access is done. > + * This is the reason for having pre and post functions > + */ Multi-lines commenting style > + > +static DEFINE_PER_CPU(u32, venum_orig_val); > +static DEFINE_PER_CPU(u32, fp_orig_val); > + > +static void scorpion_pre_vlpm(void) > +{ > + ? ? ? u32 venum_new_val; > + ? ? ? u32 fp_new_val; Needs an extra blank line here. > + ? ? ? /* CPACR Enable CP10 access*/ > + ? ? ? venum_orig_val = get_copro_access(); > + ? ? ? venum_new_val = venum_orig_val | CPACC_SVC(10); > + ? ? ? set_copro_access(venum_new_val); > + ? ? ? /* Enable FPEXC */ > + ? ? ? fp_orig_val = fmrx(FPEXC); > + ? ? ? fp_new_val = fp_orig_val | FPEXC_EN; > + ? ? ? fmxr(FPEXC, fp_new_val); > +} > + > +static void scorpion_post_vlpm(void) > +{ > + ? ? ? /* Restore FPEXC*/ > + ? ? ? fmxr(FPEXC, fp_orig_val); > + ? ? ? isb(); > + ? ? ? /* Restore CPACR*/ > + ? ? ? set_copro_access(venum_orig_val); > +} > + > +struct scorpion_access_funcs { > + ? ? ? u32 (*read) (void); > + ? ? ? void (*write) (u32); > + ? ? ? void (*pre) (void); > + ? ? ? void (*post) (void); > +}; > + > +/* The scorpion_functions array is used to set up the event register codes > + * based on the group to which an event belongs to. > + * Having the following array modularizes the code for doing that. > + */ Multi-lines commenting style > +struct scorpion_access_funcs scorpion_functions[] = { > + ? ? ? {scorpion_read_lpm0, scorpion_write_lpm0, NULL, NULL}, > + ? ? ? {scorpion_read_lpm1, scorpion_write_lpm1, NULL, NULL}, > + ? ? ? {scorpion_read_lpm2, scorpion_write_lpm2, NULL, NULL}, > + ? ? ? {scorpion_read_l2lpm, scorpion_write_l2lpm, NULL, NULL}, > + ? ? ? {scorpion_read_vlpm, scorpion_write_vlpm, scorpion_pre_vlpm, > + ? ? ? ? ? ? ? scorpion_post_vlpm}, > +}; > + > +static inline u32 scorpion_get_columnmask(u32 evt_code) > +{ > + ? ? ? const u32 columnmasks[] = {0xffffff00, 0xffff00ff, 0xff00ffff, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x80ffffff}; > + ? ? ? return columnmasks[evt_code & 0x3]; > +} > + > +static void scorpion_evt_setup(u32 gr, u32 setval, u32 evt_code) > +{ > + ? ? ? u32 val; Needs an extra blank line here. > + ? ? ? if (scorpion_functions[gr].pre) > + ? ? ? ? ? ? ? scorpion_functions[gr].pre(); > + ? ? ? val = scorpion_get_columnmask(evt_code) & scorpion_functions[gr].read(); > + ? ? ? val = val | setval; > + ? ? ? scorpion_functions[gr].write(val); > + ? ? ? if (scorpion_functions[gr].post) > + ? ? ? ? ? ? ? scorpion_functions[gr].post(); > +} > + > +static void scorpion_clear_pmuregs(void) > +{ > + ? ? ? unsigned long flags; Needs an extra blank line here. > + ? ? ? scorpion_write_lpm0(0); > + ? ? ? scorpion_write_lpm1(0); > + ? ? ? scorpion_write_lpm2(0); > + ? ? ? scorpion_write_l2lpm(0); > + ? ? ? raw_spin_lock_irqsave(&pmu_lock, flags); > + ? ? ? scorpion_pre_vlpm(); > + ? ? ? scorpion_write_vlpm(0); > + ? ? ? scorpion_post_vlpm(); > + ? ? ? raw_spin_unlock_irqrestore(&pmu_lock, flags); > +} > + > +static void scorpion_clearpmu(u32 grp, u32 val, u32 evt_code) > +{ > + ? ? ? u32 orig_pmuval, new_pmuval; Needs an extra blank line here. > + ? ? ? if (scorpion_functions[grp].pre) > + ? ? ? ? ? ? ? scorpion_functions[grp].pre(); > + ? ? ? orig_pmuval = scorpion_functions[grp].read(); > + ? ? ? val = val & ~scorpion_get_columnmask(evt_code); > + ? ? ? new_pmuval = orig_pmuval & ~val; > + ? ? ? scorpion_functions[grp].write(new_pmuval); > + ? ? ? if (scorpion_functions[grp].post) > + ? ? ? ? ? ? ? scorpion_functions[grp].post(); > +} > + > +static void scorpion_pmu_disable_event(struct hw_perf_event *hwc, int idx) > +{ > + ? ? ? unsigned long flags; > + ? ? ? u32 val = 0; > + ? ? ? u32 gr; > + ? ? ? unsigned long event; > + ? ? ? struct scorpion_evt evtinfo; > + > + ? ? ? /* Disable counter and interrupt */ > + ? ? ? raw_spin_lock_irqsave(&pmu_lock, flags); > + > + ? ? ? /* Disable counter */ > + ? ? ? armv7_pmnc_disable_counter(idx); > + > + ? ? ? /* > + ? ? ? * Clear lpm code (if destined for PMNx counters) > + ? ? ? * We don't need to set the event if it's a cycle count > + ? ? ? */ > + ? ? ? if (idx != ARMV7_CYCLE_COUNTER) { > + ? ? ? ? ? ? ? val = hwc->config_base; > + ? ? ? ? ? ? ? val &= ARMV7_EVTSEL_MASK; > + ? ? ? ? ? ? ? if (val > 0x40) { > + ? ? ? ? ? ? ? ? ? ? ? event = get_scorpion_evtinfo(val, &evtinfo); > + ? ? ? ? ? ? ? ? ? ? ? if (event == -EINVAL) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto scorpion_dis_out; > + ? ? ? ? ? ? ? ? ? ? ? val = evtinfo.group_setval; > + ? ? ? ? ? ? ? ? ? ? ? gr = evtinfo.groupcode; > + ? ? ? ? ? ? ? ? ? ? ? scorpion_clearpmu(gr, val, evtinfo.armv7_evt_type); > + ? ? ? ? ? ? ? } > + ? ? ? } > + ? ? ? /* Disable interrupt for this counter */ > + ? ? ? armv7_pmnc_disable_intens(idx); > + > +scorpion_dis_out: > + ? ? ? raw_spin_unlock_irqrestore(&pmu_lock, flags); > +} > + > +static void scorpion_pmu_enable_event(struct hw_perf_event *hwc, int idx) > +{ > + ? ? ? unsigned long flags; > + ? ? ? u32 val = 0; > + ? ? ? u32 gr; > + ? ? ? unsigned long event; > + ? ? ? struct scorpion_evt evtinfo; > + > + ? ? ? /* > + ? ? ? * Enable counter and interrupt, and set the counter to count > + ? ? ? * the event that we're interested in. > + ? ? ? */ > + ? ? ? raw_spin_lock_irqsave(&pmu_lock, flags); > + > + ? ? ? /* Disable counter */ > + ? ? ? armv7_pmnc_disable_counter(idx); > + > + ? ? ? /* > + ? ? ? * Set event (if destined for PMNx counters) > + ? ? ? * We don't need to set the event if it's a cycle count > + ? ? ? */ > + ? ? ? if (idx != ARMV7_CYCLE_COUNTER) { > + ? ? ? ? ? ? ? val = hwc->config_base; > + ? ? ? ? ? ? ? val &= ARMV7_EVTSEL_MASK; > + ? ? ? ? ? ? ? if (val < 0x40) { > + ? ? ? ? ? ? ? ? ? ? ? armv7_pmnc_write_evtsel(idx, hwc->config_base); > + ? ? ? ? ? ? ? } else { > + ? ? ? ? ? ? ? ? ? ? ? event = get_scorpion_evtinfo(val, &evtinfo); > + > + ? ? ? ? ? ? ? ? ? ? ? if (event == -EINVAL) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto scorpion_out; > + ? ? ? ? ? ? ? ? ? ? ? /* > + ? ? ? ? ? ? ? ? ? ? ? * Set event (if destined for PMNx counters) > + ? ? ? ? ? ? ? ? ? ? ? * We don't need to set the event if it's a cycle count > + ? ? ? ? ? ? ? ? ? ? ? */ > + ? ? ? ? ? ? ? ? ? ? ? armv7_pmnc_write_evtsel(idx, event); > + ? ? ? ? ? ? ? ? ? ? ? val = 0x0; > + ? ? ? ? ? ? ? ? ? ? ? asm volatile("mcr p15, 0, %0, c9, c15, 0" : : > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "r" (val)); > + ? ? ? ? ? ? ? ? ? ? ? val = evtinfo.group_setval; > + ? ? ? ? ? ? ? ? ? ? ? gr = evtinfo.groupcode; > + ? ? ? ? ? ? ? ? ? ? ? scorpion_evt_setup(gr, val, evtinfo.armv7_evt_type); > + ? ? ? ? ? ? ? } > + ? ? ? } > + > + ? ? ? /* Enable interrupt for this counter */ > + ? ? ? armv7_pmnc_enable_intens(idx); > + > + ? ? ? /* Enable counter */ > + ? ? ? armv7_pmnc_enable_counter(idx); > + > +scorpion_out: > + ? ? ? raw_spin_unlock_irqrestore(&pmu_lock, flags); > +} > + > +static struct arm_pmu scorpion_pmu = { > + ? ? ? .handle_irq ? ? ? ? ? ? = armv7pmu_handle_irq, > + ? ? ? .enable ? ? ? ? ? ? ? ? = scorpion_pmu_enable_event, > + ? ? ? .disable ? ? ? ? ? ? ? ?= scorpion_pmu_disable_event, > + ? ? ? .read_counter ? ? ? ? ? = armv7pmu_read_counter, > + ? ? ? .write_counter ? ? ? ? ?= armv7pmu_write_counter, > + ? ? ? .raw_event_mask ? ? ? ? = 0xFF, > + ? ? ? .get_event_idx ? ? ? ? ?= armv7pmu_get_event_idx, > + ? ? ? .start ? ? ? ? ? ? ? ? ?= armv7pmu_start, > + ? ? ? .stop ? ? ? ? ? ? ? ? ? = armv7pmu_stop, > + ? ? ? .max_period ? ? ? ? ? ? = (1LLU << 32) - 1, > +}; > + > +static const struct arm_pmu *__init armv7_scorpion_pmu_init(void) > +{ > + ? ? ? scorpion_pmu.id ? ? ? ? = ARM_PERF_PMU_ID_SCORPION; > + ? ? ? scorpion_pmu.name ? ? ? = "ARMv7 Scorpion"; > + ? ? ? scorpion_pmu.cache_map ?= &armv7_scorpion_perf_cache_map; > + ? ? ? scorpion_pmu.event_map ?= &armv7_scorpion_perf_map; > + ? ? ? scorpion_pmu.num_events = armv7_reset_read_pmnc(); > + ? ? ? scorpion_clear_pmuregs(); > + ? ? ? return &scorpion_pmu; > +} > + > +static const struct arm_pmu *__init armv7_scorpionmp_pmu_init(void) > +{ > + ? ? ? scorpion_pmu.id ? ? ? ? = ARM_PERF_PMU_ID_SCORPIONMP; > + ? ? ? scorpion_pmu.name ? ? ? = "ARMv7 Scorpion-MP"; > + ? ? ? scorpion_pmu.cache_map ?= &armv7_scorpion_perf_cache_map; > + ? ? ? scorpion_pmu.event_map ?= &armv7_scorpion_perf_map; > + ? ? ? scorpion_pmu.num_events = armv7_reset_read_pmnc(); > + ? ? ? scorpion_clear_pmuregs(); > + ? ? ? return &scorpion_pmu; > +} > +#else > +static const struct arm_pmu *__init scorpion_pmu_init(void) > +{ > + ? ? ? return NULL; > +} > +static const struct arm_pmu *__init scorpionmp_pmu_init(void) > +{ > + ? ? ? return NULL; > +} > +#endif /* CONFIG_CPU_V7 */ > -- > 1.7.4.1 > Thanks! Jean > -- > Sent by an employee of the Qualcomm Innovation Center, Inc. > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/