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

Commit 9e9dddbe authored by Ashwin Chaugule's avatar Ashwin Chaugule Committed by Stephen Boyd
Browse files

Perf: Restore correct CPU's PMU counters after power collpase



Since the L1CC PMU's are per CPU, the variable to detect if a CPU
came out of powercollapse also needs to be a per CPU variable. This
ensures that we reset and restore the correct CPU's PMU counters.

Change-Id: I02273df2eff9f6d88d68f46a7752c107b290a8ef
Signed-off-by: default avatarAshwin Chaugule <ashwinc@codeaurora.org>
parent 0db01479
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ struct pmu_hw_events {
	 */
	unsigned long           *used_mask;

	u32			*from_idle;

	/*
	 * Hardware lock to serialize accesses to PMU registers. Needed for the
	 * read/modify/write sequences.
@@ -81,7 +83,6 @@ struct arm_pmu {
	struct mutex	reserve_mutex;
	u64		max_period;
	struct platform_device	*plat_device;
	u32		from_idle;
	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
	void		(*enable)(struct perf_event *event);
	void		(*disable)(struct perf_event *event);
+5 −2
Original line number Diff line number Diff line
@@ -469,7 +469,7 @@ static void armpmu_enable(struct pmu *pmu)
	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
	int idx;

	if (armpmu->from_idle) {
	if (*hw_events->from_idle) {
		for (idx = 0; idx <= cpu_pmu->num_events; ++idx) {
			struct perf_event *event = hw_events->events[idx];

@@ -480,9 +480,12 @@ static void armpmu_enable(struct pmu *pmu)
		}

		/* Reset bit so we don't needlessly re-enable counters.*/
		armpmu->from_idle = 0;
		*hw_events->from_idle = 0;
	}

	/* So we don't start the PMU before enabling counters after idle. */
	barrier();

	if (enabled)
		armpmu->start(armpmu);
}
+3 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
/* Set at runtime when we know what CPU type we are. */
static struct arm_pmu *cpu_pmu;

static DEFINE_PER_CPU(u32, from_idle);
static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
@@ -142,6 +143,7 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
		events->events = per_cpu(hw_events, cpu);
		events->used_mask = per_cpu(used_mask, cpu);
		events->from_idle = per_cpu(from_idle, cpu);
		raw_spin_lock_init(&events->pmu_lock);
	}

@@ -235,7 +237,7 @@ static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
			 * Flip this bit so armpmu_enable knows it needs
			 * to re-enable active counters.
			 */
			cpu_pmu->from_idle = 1;
			__get_cpu_var(from_idle) = 1;
			cpu_pmu->reset(NULL);
			perf_pmu_enable(&cpu_pmu->pmu);
		}