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

Commit 9f766b5d authored by Prasad Sodagudi's avatar Prasad Sodagudi Committed by Visweswara Kumar
Browse files

perf: Add workaround for performance monitor irq burst



There is possibility of IRQ burst when back to back
performance monitor overflow interrupts raised.
Single interrupt line is used for all monitors on a CPU
and when multiple monitors are used simultaneously,
performance monitor overflow status register do no show
proper overflow status of each monitor. So add workaround
to disable all monitor overflow interrupts while handling
a monitor overflow interrupt.

Change-Id: I14a34b2258ddab19f8ed9a9e087129efd7b86ff4
Signed-off-by: default avatarPrasad Sodagudi <psodagud@codeaurora.org>
Signed-off-by: default avatarSrinivas Ramana <sramana@codeaurora.org>
parent bfa5d11f
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -678,6 +678,31 @@ static void armv8pmu_disable_event(struct perf_event *event)
	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}

static inline u32 armv8pmu_get_enabled_ints(void)
{
	u32 int_enset;
	int_enset = read_sysreg(pmintenset_el1);
	write_sysreg(0xffffffff, pmintenclr_el1);
	isb();
	return int_enset;
}

static inline u32 armv8pmu_update_enabled_ints(u32 value, int idx, int set)
{
	if(set)
		value |=  BIT(ARMV8_IDX_TO_COUNTER(idx));
	else
		value &= ~(BIT(ARMV8_IDX_TO_COUNTER(idx)));

	return value;
}

static inline void armv8pmu_set_enabled_ints(u32 mask)
{
	write_sysreg(mask, pmintenset_el1);
	isb();
}

static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
{
	u32 pmovsr;
@@ -686,6 +711,12 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
	struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
	struct pt_regs *regs;
	int idx;
	u32 enabled_ints;

	/*
	 * Get enabled the PMU interrupts and mask all PMU interrupts.
	 */
	enabled_ints = armv8pmu_get_enabled_ints();

	/*
	 * Get and reset the IRQ flags
@@ -695,8 +726,10 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
	/*
	 * Did an overflow occur?
	 */
	if (!armv8pmu_has_overflowed(pmovsr))
	if (!armv8pmu_has_overflowed(pmovsr)) {
		BUG_ON(1);
		return IRQ_NONE;
	}

	/*
	 * Handle the counter(s) overflow(s)
@@ -724,8 +757,14 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
		if (!armpmu_event_set_period(event))
			continue;

		if (perf_event_overflow(event, &data, regs))
		if (perf_event_overflow(event, &data, regs)) {
			cpu_pmu->disable(event);

			/*
			 * Update the list of interrupts that should be reenabled.
			 */
			enabled_ints = armv8pmu_update_enabled_ints(enabled_ints, idx, 0);
		}
	}

	/*
@@ -737,6 +776,11 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
	 */
	irq_work_run();

	/*
	 * Re-enable the PMU interrupts
	 */
	armv8pmu_set_enabled_ints(enabled_ints);

	return IRQ_HANDLED;
}