Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cda94408 authored by Catalin Marinas's avatar Catalin Marinas
Browse files

Merge branch 'for-next/perf' of...

Merge branch 'for-next/perf' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into for-next/core

* 'for-next/perf' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux:
  arm64: perf: add support for Cortex-A35
  arm64: perf: add support for Cortex-A73
  arm64: perf: Remove redundant entries from CPU-specific event maps
  arm64: perf: Connect additional events to pmu counters
  arm64: perf: Allow standard PMUv3 events to be extended by the CPU type
  perf: xgene: Remove unnecessary managed resources cleanup
  arm64: perf: Allow more than one cycle counter to be used
parents df5b95be e884f80c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -9,9 +9,11 @@ Required properties:
- compatible : should be one of
- compatible : should be one of
	"apm,potenza-pmu"
	"apm,potenza-pmu"
	"arm,armv8-pmuv3"
	"arm,armv8-pmuv3"
	"arm,cortex-a73-pmu"
	"arm,cortex-a72-pmu"
	"arm,cortex-a72-pmu"
	"arm,cortex-a57-pmu"
	"arm,cortex-a57-pmu"
	"arm,cortex-a53-pmu"
	"arm,cortex-a53-pmu"
	"arm,cortex-a35-pmu"
	"arm,cortex-a17-pmu"
	"arm,cortex-a17-pmu"
	"arm,cortex-a15-pmu"
	"arm,cortex-a15-pmu"
	"arm,cortex-a12-pmu"
	"arm,cortex-a12-pmu"
+85 −123
Original line number Original line Diff line number Diff line
@@ -202,55 +202,6 @@ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
};
};


/* ARM Cortex-A53 HW events mapping. */
static const unsigned armv8_a53_perf_map[PERF_COUNT_HW_MAX] = {
	PERF_MAP_ALL_UNSUPPORTED,
	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
};

/* ARM Cortex-A57 and Cortex-A72 events mapping. */
static const unsigned armv8_a57_perf_map[PERF_COUNT_HW_MAX] = {
	PERF_MAP_ALL_UNSUPPORTED,
	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
};

static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = {
	PERF_MAP_ALL_UNSUPPORTED,
	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
};

/* Broadcom Vulcan events mapping */
static const unsigned armv8_vulcan_perf_map[PERF_COUNT_HW_MAX] = {
	PERF_MAP_ALL_UNSUPPORTED,
	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_BR_RETIRED,
	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
};

static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
						[PERF_COUNT_HW_CACHE_OP_MAX]
						[PERF_COUNT_HW_CACHE_OP_MAX]
						[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
						[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
@@ -281,27 +232,10 @@ static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
	PERF_CACHE_MAP_ALL_UNSUPPORTED,
	PERF_CACHE_MAP_ALL_UNSUPPORTED,


	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREF_LINEFILL,
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREF_LINEFILL,


	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,

	[C(LL)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L2D_CACHE,
	[C(LL)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL,
	[C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L2D_CACHE,
	[C(LL)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL,

	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL,
	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,

	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
};
};


static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -314,18 +248,26 @@ static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,


	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,

	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,


	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
};


	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
static const unsigned armv8_a73_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
					      [PERF_COUNT_HW_CACHE_OP_MAX]
	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	PERF_CACHE_MAP_ALL_UNSUPPORTED,

	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,

	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,

	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
};
};


static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -340,8 +282,6 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS,
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS,
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS,
	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS,


	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
	[C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS,
	[C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS,
	[C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS,
	[C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS,


@@ -349,13 +289,6 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,

	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,

	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
};
};


static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -368,22 +301,11 @@ static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,


	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,

	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
	[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB,

	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,


	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,

	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
};
};
@@ -846,17 +768,14 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
	struct hw_perf_event *hwc = &event->hw;
	struct hw_perf_event *hwc = &event->hw;
	unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;
	unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;


	/* Always place a cycle counter into the cycle counter. */
	/* Always prefer to place a cycle counter into the cycle counter. */
	if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
	if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
		if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
		if (!test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
			return -EAGAIN;

			return ARMV8_IDX_CYCLE_COUNTER;
			return ARMV8_IDX_CYCLE_COUNTER;
	}
	}


	/*
	/*
	 * For anything other than a cycle counter, try and use
	 * Otherwise use events counters
	 * the events counters
	 */
	 */
	for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
	for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
		if (!test_and_set_bit(idx, cpuc->used_mask))
		if (!test_and_set_bit(idx, cpuc->used_mask))
@@ -924,7 +843,13 @@ static void armv8pmu_reset(void *info)
			    ARMV8_PMU_PMCR_LC);
			    ARMV8_PMU_PMCR_LC);
}
}


static int armv8_pmuv3_map_event(struct perf_event *event)
static int __armv8_pmuv3_map_event(struct perf_event *event,
				   const unsigned (*extra_event_map)
						  [PERF_COUNT_HW_MAX],
				   const unsigned (*extra_cache_map)
						  [PERF_COUNT_HW_CACHE_MAX]
						  [PERF_COUNT_HW_CACHE_OP_MAX]
						  [PERF_COUNT_HW_CACHE_RESULT_MAX])
{
{
	int hw_event_id;
	int hw_event_id;
	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
@@ -932,44 +857,47 @@ static int armv8_pmuv3_map_event(struct perf_event *event)
	hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map,
	hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map,
				       &armv8_pmuv3_perf_cache_map,
				       &armv8_pmuv3_perf_cache_map,
				       ARMV8_PMU_EVTYPE_EVENT);
				       ARMV8_PMU_EVTYPE_EVENT);
	if (hw_event_id < 0)

	/* Onl expose micro/arch events supported by this PMU */
	if ((hw_event_id > 0) && (hw_event_id < ARMV8_PMUV3_MAX_COMMON_EVENTS)
	    && test_bit(hw_event_id, armpmu->pmceid_bitmap)) {
		return hw_event_id;
		return hw_event_id;
	}


	/* disable micro/arch events not supported by this PMU */
	return armpmu_map_event(event, extra_event_map, extra_cache_map,
	if ((hw_event_id < ARMV8_PMUV3_MAX_COMMON_EVENTS) &&
				ARMV8_PMU_EVTYPE_EVENT);
		!test_bit(hw_event_id, armpmu->pmceid_bitmap)) {
			return -EOPNOTSUPP;
}
}


	return hw_event_id;
static int armv8_pmuv3_map_event(struct perf_event *event)
{
	return __armv8_pmuv3_map_event(event, NULL, NULL);
}
}


static int armv8_a53_map_event(struct perf_event *event)
static int armv8_a53_map_event(struct perf_event *event)
{
{
	return armpmu_map_event(event, &armv8_a53_perf_map,
	return __armv8_pmuv3_map_event(event, NULL, &armv8_a53_perf_cache_map);
				&armv8_a53_perf_cache_map,
				ARMV8_PMU_EVTYPE_EVENT);
}
}


static int armv8_a57_map_event(struct perf_event *event)
static int armv8_a57_map_event(struct perf_event *event)
{
{
	return armpmu_map_event(event, &armv8_a57_perf_map,
	return __armv8_pmuv3_map_event(event, NULL, &armv8_a57_perf_cache_map);
				&armv8_a57_perf_cache_map,
}
				ARMV8_PMU_EVTYPE_EVENT);

static int armv8_a73_map_event(struct perf_event *event)
{
	return __armv8_pmuv3_map_event(event, NULL, &armv8_a73_perf_cache_map);
}
}


static int armv8_thunder_map_event(struct perf_event *event)
static int armv8_thunder_map_event(struct perf_event *event)
{
{
	return armpmu_map_event(event, &armv8_thunder_perf_map,
	return __armv8_pmuv3_map_event(event, NULL,
				&armv8_thunder_perf_cache_map,
				       &armv8_thunder_perf_cache_map);
				ARMV8_PMU_EVTYPE_EVENT);
}
}


static int armv8_vulcan_map_event(struct perf_event *event)
static int armv8_vulcan_map_event(struct perf_event *event)
{
{
	return armpmu_map_event(event, &armv8_vulcan_perf_map,
	return __armv8_pmuv3_map_event(event, NULL,
				&armv8_vulcan_perf_cache_map,
				       &armv8_vulcan_perf_cache_map);
				ARMV8_PMU_EVTYPE_EVENT);
}
}


struct armv8pmu_probe_info {
struct armv8pmu_probe_info {
@@ -1062,6 +990,22 @@ static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu)
	return 0;
	return 0;
}
}


static int armv8_a35_pmu_init(struct arm_pmu *cpu_pmu)
{
	int ret = armv8_pmu_init(cpu_pmu);
	if (ret)
		return ret;

	cpu_pmu->name			= "armv8_cortex_a35";
	cpu_pmu->map_event		= armv8_a53_map_event;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
		&armv8_pmuv3_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv8_pmuv3_format_attr_group;

	return 0;
}

static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
{
{
	int ret = armv8_pmu_init(cpu_pmu);
	int ret = armv8_pmu_init(cpu_pmu);
@@ -1110,6 +1054,22 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
	return 0;
	return 0;
}
}


static int armv8_a73_pmu_init(struct arm_pmu *cpu_pmu)
{
	int ret = armv8_pmu_init(cpu_pmu);
	if (ret)
		return ret;

	cpu_pmu->name			= "armv8_cortex_a73";
	cpu_pmu->map_event		= armv8_a73_map_event;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
		&armv8_pmuv3_events_attr_group;
	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
		&armv8_pmuv3_format_attr_group;

	return 0;
}

static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
{
{
	int ret = armv8_pmu_init(cpu_pmu);
	int ret = armv8_pmu_init(cpu_pmu);
@@ -1144,9 +1104,11 @@ static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu)


static const struct of_device_id armv8_pmu_of_device_ids[] = {
static const struct of_device_id armv8_pmu_of_device_ids[] = {
	{.compatible = "arm,armv8-pmuv3",	.data = armv8_pmuv3_init},
	{.compatible = "arm,armv8-pmuv3",	.data = armv8_pmuv3_init},
	{.compatible = "arm,cortex-a35-pmu",	.data = armv8_a35_pmu_init},
	{.compatible = "arm,cortex-a53-pmu",	.data = armv8_a53_pmu_init},
	{.compatible = "arm,cortex-a53-pmu",	.data = armv8_a53_pmu_init},
	{.compatible = "arm,cortex-a57-pmu",	.data = armv8_a57_pmu_init},
	{.compatible = "arm,cortex-a57-pmu",	.data = armv8_a57_pmu_init},
	{.compatible = "arm,cortex-a72-pmu",	.data = armv8_a72_pmu_init},
	{.compatible = "arm,cortex-a72-pmu",	.data = armv8_a72_pmu_init},
	{.compatible = "arm,cortex-a73-pmu",	.data = armv8_a73_pmu_init},
	{.compatible = "cavium,thunder-pmu",	.data = armv8_thunder_pmu_init},
	{.compatible = "cavium,thunder-pmu",	.data = armv8_thunder_pmu_init},
	{.compatible = "brcm,vulcan-pmu",	.data = armv8_vulcan_pmu_init},
	{.compatible = "brcm,vulcan-pmu",	.data = armv8_vulcan_pmu_init},
	{},
	{},
+6 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,9 @@ armpmu_map_cache_event(const unsigned (*cache_map)
	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
		return -EINVAL;
		return -EINVAL;


	if (!cache_map)
		return -ENOENT;

	ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
	ret = (int)(*cache_map)[cache_type][cache_op][cache_result];


	if (ret == CACHE_OP_UNSUPPORTED)
	if (ret == CACHE_OP_UNSUPPORTED)
@@ -63,6 +66,9 @@ armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
	if (config >= PERF_COUNT_HW_MAX)
	if (config >= PERF_COUNT_HW_MAX)
		return -EINVAL;
		return -EINVAL;


	if (!event_map)
		return -ENOENT;

	mapping = (*event_map)[config];
	mapping = (*event_map)[config];
	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
}
}
+22 −52
Original line number Original line Diff line number Diff line
@@ -1147,7 +1147,6 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
{
{
	struct device *dev = xgene_pmu->dev;
	struct device *dev = xgene_pmu->dev;
	struct xgene_pmu_dev *pmu;
	struct xgene_pmu_dev *pmu;
	int rc;


	pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
	pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
	if (!pmu)
	if (!pmu)
@@ -1159,7 +1158,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
	switch (pmu->inf->type) {
	switch (pmu->inf->type) {
	case PMU_TYPE_L3C:
	case PMU_TYPE_L3C:
		if (!(xgene_pmu->l3c_active_mask & pmu->inf->enable_mask))
		if (!(xgene_pmu->l3c_active_mask & pmu->inf->enable_mask))
			goto dev_err;
			return -ENODEV;
		if (xgene_pmu->version == PCP_PMU_V3)
		if (xgene_pmu->version == PCP_PMU_V3)
			pmu->attr_groups = l3c_pmu_v3_attr_groups;
			pmu->attr_groups = l3c_pmu_v3_attr_groups;
		else
		else
@@ -1177,7 +1176,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
		break;
		break;
	case PMU_TYPE_MCB:
	case PMU_TYPE_MCB:
		if (!(xgene_pmu->mcb_active_mask & pmu->inf->enable_mask))
		if (!(xgene_pmu->mcb_active_mask & pmu->inf->enable_mask))
			goto dev_err;
			return -ENODEV;
		if (xgene_pmu->version == PCP_PMU_V3)
		if (xgene_pmu->version == PCP_PMU_V3)
			pmu->attr_groups = mcb_pmu_v3_attr_groups;
			pmu->attr_groups = mcb_pmu_v3_attr_groups;
		else
		else
@@ -1185,7 +1184,7 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
		break;
		break;
	case PMU_TYPE_MC:
	case PMU_TYPE_MC:
		if (!(xgene_pmu->mc_active_mask & pmu->inf->enable_mask))
		if (!(xgene_pmu->mc_active_mask & pmu->inf->enable_mask))
			goto dev_err;
			return -ENODEV;
		if (xgene_pmu->version == PCP_PMU_V3)
		if (xgene_pmu->version == PCP_PMU_V3)
			pmu->attr_groups = mc_pmu_v3_attr_groups;
			pmu->attr_groups = mc_pmu_v3_attr_groups;
		else
		else
@@ -1195,19 +1194,14 @@ xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
		return -EINVAL;
		return -EINVAL;
	}
	}


	rc = xgene_init_perf(pmu, ctx->name);
	if (xgene_init_perf(pmu, ctx->name)) {
	if (rc) {
		dev_err(dev, "%s PMU: Failed to init perf driver\n", ctx->name);
		dev_err(dev, "%s PMU: Failed to init perf driver\n", ctx->name);
		goto dev_err;
		return -ENODEV;
	}
	}


	dev_info(dev, "%s PMU registered\n", ctx->name);
	dev_info(dev, "%s PMU registered\n", ctx->name);


	return rc;
	return 0;

dev_err:
	devm_kfree(dev, pmu);
	return -ENODEV;
}
}


static void _xgene_pmu_isr(int irq, struct xgene_pmu_dev *pmu_dev)
static void _xgene_pmu_isr(int irq, struct xgene_pmu_dev *pmu_dev)
@@ -1515,13 +1509,13 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
	acpi_dev_free_resource_list(&resource_list);
	acpi_dev_free_resource_list(&resource_list);
	if (rc < 0) {
	if (rc < 0) {
		dev_err(dev, "PMU type %d: No resource address found\n", type);
		dev_err(dev, "PMU type %d: No resource address found\n", type);
		goto err;
		return NULL;
	}
	}


	dev_csr = devm_ioremap_resource(dev, &res);
	dev_csr = devm_ioremap_resource(dev, &res);
	if (IS_ERR(dev_csr)) {
	if (IS_ERR(dev_csr)) {
		dev_err(dev, "PMU type %d: Fail to map resource\n", type);
		dev_err(dev, "PMU type %d: Fail to map resource\n", type);
		goto err;
		return NULL;
	}
	}


	/* A PMU device node without enable-bit-index is always enabled */
	/* A PMU device node without enable-bit-index is always enabled */
@@ -1535,7 +1529,7 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
	ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
	ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
	if (!ctx->name) {
	if (!ctx->name) {
		dev_err(dev, "PMU type %d: Fail to get device name\n", type);
		dev_err(dev, "PMU type %d: Fail to get device name\n", type);
		goto err;
		return NULL;
	}
	}
	inf = &ctx->inf;
	inf = &ctx->inf;
	inf->type = type;
	inf->type = type;
@@ -1543,9 +1537,6 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
	inf->enable_mask = 1 << enable_bit;
	inf->enable_mask = 1 << enable_bit;


	return ctx;
	return ctx;
err:
	devm_kfree(dev, ctx);
	return NULL;
}
}


static const struct acpi_device_id xgene_pmu_acpi_type_match[] = {
static const struct acpi_device_id xgene_pmu_acpi_type_match[] = {
@@ -1663,20 +1654,20 @@ xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
	void __iomem *dev_csr;
	void __iomem *dev_csr;
	struct resource res;
	struct resource res;
	int enable_bit;
	int enable_bit;
	int rc;


	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
	if (!ctx)
		return NULL;
		return NULL;
	rc = of_address_to_resource(np, 0, &res);

	if (rc < 0) {
	if (of_address_to_resource(np, 0, &res) < 0) {
		dev_err(dev, "PMU type %d: No resource address found\n", type);
		dev_err(dev, "PMU type %d: No resource address found\n", type);
		goto err;
		return NULL;
	}
	}

	dev_csr = devm_ioremap_resource(dev, &res);
	dev_csr = devm_ioremap_resource(dev, &res);
	if (IS_ERR(dev_csr)) {
	if (IS_ERR(dev_csr)) {
		dev_err(dev, "PMU type %d: Fail to map resource\n", type);
		dev_err(dev, "PMU type %d: Fail to map resource\n", type);
		goto err;
		return NULL;
	}
	}


	/* A PMU device node without enable-bit-index is always enabled */
	/* A PMU device node without enable-bit-index is always enabled */
@@ -1686,17 +1677,15 @@ xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
	ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
	ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
	if (!ctx->name) {
	if (!ctx->name) {
		dev_err(dev, "PMU type %d: Fail to get device name\n", type);
		dev_err(dev, "PMU type %d: Fail to get device name\n", type);
		goto err;
		return NULL;
	}
	}

	inf = &ctx->inf;
	inf = &ctx->inf;
	inf->type = type;
	inf->type = type;
	inf->csr = dev_csr;
	inf->csr = dev_csr;
	inf->enable_mask = 1 << enable_bit;
	inf->enable_mask = 1 << enable_bit;


	return ctx;
	return ctx;
err:
	devm_kfree(dev, ctx);
	return NULL;
}
}


static int fdt_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
static int fdt_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
@@ -1868,22 +1857,20 @@ static int xgene_pmu_probe(struct platform_device *pdev)
	xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res);
	xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(xgene_pmu->pcppmu_csr)) {
	if (IS_ERR(xgene_pmu->pcppmu_csr)) {
		dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n");
		dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n");
		rc = PTR_ERR(xgene_pmu->pcppmu_csr);
		return PTR_ERR(xgene_pmu->pcppmu_csr);
		goto err;
	}
	}


	irq = platform_get_irq(pdev, 0);
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
	if (irq < 0) {
		dev_err(&pdev->dev, "No IRQ resource\n");
		dev_err(&pdev->dev, "No IRQ resource\n");
		rc = -EINVAL;
		return -EINVAL;
		goto err;
	}
	}
	rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr,
	rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr,
				IRQF_NOBALANCING | IRQF_NO_THREAD,
				IRQF_NOBALANCING | IRQF_NO_THREAD,
				dev_name(&pdev->dev), xgene_pmu);
				dev_name(&pdev->dev), xgene_pmu);
	if (rc) {
	if (rc) {
		dev_err(&pdev->dev, "Could not request IRQ %d\n", irq);
		dev_err(&pdev->dev, "Could not request IRQ %d\n", irq);
		goto err;
		return rc;
	}
	}


	raw_spin_lock_init(&xgene_pmu->lock);
	raw_spin_lock_init(&xgene_pmu->lock);
@@ -1903,42 +1890,29 @@ static int xgene_pmu_probe(struct platform_device *pdev)
	rc = irq_set_affinity(irq, &xgene_pmu->cpu);
	rc = irq_set_affinity(irq, &xgene_pmu->cpu);
	if (rc) {
	if (rc) {
		dev_err(&pdev->dev, "Failed to set interrupt affinity!\n");
		dev_err(&pdev->dev, "Failed to set interrupt affinity!\n");
		goto err;
		return rc;
	}
	}


	/* Walk through the tree for all PMU perf devices */
	/* Walk through the tree for all PMU perf devices */
	rc = xgene_pmu_probe_pmu_dev(xgene_pmu, pdev);
	rc = xgene_pmu_probe_pmu_dev(xgene_pmu, pdev);
	if (rc) {
	if (rc) {
		dev_err(&pdev->dev, "No PMU perf devices found!\n");
		dev_err(&pdev->dev, "No PMU perf devices found!\n");
		goto err;
		return rc;
	}
	}


	/* Enable interrupt */
	/* Enable interrupt */
	xgene_pmu->ops->unmask_int(xgene_pmu);
	xgene_pmu->ops->unmask_int(xgene_pmu);


	return 0;
	return 0;

err:
	if (xgene_pmu->pcppmu_csr)
		devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
	devm_kfree(&pdev->dev, xgene_pmu);

	return rc;
}
}


static void
static void
xgene_pmu_dev_cleanup(struct xgene_pmu *xgene_pmu, struct list_head *pmus)
xgene_pmu_dev_cleanup(struct xgene_pmu *xgene_pmu, struct list_head *pmus)
{
{
	struct xgene_pmu_dev_ctx *ctx;
	struct xgene_pmu_dev_ctx *ctx;
	struct device *dev = xgene_pmu->dev;
	struct xgene_pmu_dev *pmu_dev;


	list_for_each_entry(ctx, pmus, next) {
	list_for_each_entry(ctx, pmus, next) {
		pmu_dev = ctx->pmu_dev;
		perf_pmu_unregister(&ctx->pmu_dev->pmu);
		if (pmu_dev->inf->csr)
			devm_iounmap(dev, pmu_dev->inf->csr);
		devm_kfree(dev, ctx);
		devm_kfree(dev, pmu_dev);
	}
	}
}
}


@@ -1951,10 +1925,6 @@ static int xgene_pmu_remove(struct platform_device *pdev)
	xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcbpmus);
	xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcbpmus);
	xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcpmus);
	xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcpmus);


	if (xgene_pmu->pcppmu_csr)
		devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
	devm_kfree(&pdev->dev, xgene_pmu);

	return 0;
	return 0;
}
}