[PATCH 17/25] perf: arm_pmu: Use a backend-specific pointer for percpu interrupt request

Marc Zyngier
2025-09-08T16:31:52Z

From: Will Deacon <will@kernel.org>

DT and ACPI significantly differ in the way the PMU probing is
conducted, resulting in different data being available at different
times.

Work around this by providing a per-cpu 'struct arm_pmu *' as
a parameter, instead of sampling it from a per-cpu variable.

Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/perf/arm_pmu.c | 10 +++++-----
drivers/perf/arm_pmu_acpi.c | 2 +-
drivers/perf/arm_pmu_platform.c | 4 ++--
include/linux/perf/arm_pmu.h | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index d1f738eb77f1e..044c9c6296997 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -628,20 +628,20 @@ static const struct pmu_irq_ops *armpmu_find_irq_ops(int this_cpu, int irq)
return ops;
}

-void armpmu_free_irq(int irq, int cpu)
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu)
{
if (per_cpu(cpu_irq, cpu) == 0)
return;
if (WARN_ON(irq != per_cpu(cpu_irq, cpu)))
return;

- per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, &cpu_armpmu);
+ per_cpu(cpu_irq_ops, cpu)->free_pmuirq(irq, cpu, armpmu);

per_cpu(cpu_irq, cpu) = 0;
per_cpu(cpu_irq_ops, cpu) = NULL;
}

-int armpmu_request_irq(int irq, int cpu)
+int armpmu_request_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu)
{
int err = 0;
const irq_handler_t handler = armpmu_dispatch_irq;
@@ -666,12 +666,12 @@ int armpmu_request_irq(int irq, int cpu)
IRQF_NO_THREAD;

err = request_nmi(irq, handler, irq_flags, "arm-pmu",
- per_cpu_ptr(&cpu_armpmu, cpu));
+ per_cpu_ptr(armpmu, cpu));

/* If cannot get an NMI, get a normal interrupt */
if (err) {
err = request_irq(irq, handler, irq_flags, "arm-pmu",
- per_cpu_ptr(&cpu_armpmu, cpu));
+ per_cpu_ptr(armpmu, cpu));
irq_ops = &pmuirq_ops;
} else {
has_nmi = true;
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c
index a5956fa728070..a28352e2bff0a 100644
--- a/drivers/perf/arm_pmu_acpi.c
+++ b/drivers/perf/arm_pmu_acpi.c
@@ -223,7 +223,7 @@ static int arm_pmu_acpi_parse_irqs(void)
* them with their PMUs.
*/
per_cpu(pmu_irqs, cpu) = irq;
- err = armpmu_request_irq(irq, cpu);
+ err = armpmu_request_irq(&probed_pmus, irq, cpu);
if (err)
goto out_err;
}
diff --git a/drivers/perf/arm_pmu_platform.c b/drivers/perf/arm_pmu_platform.c
index 0c7d5065e9074..d9b0e8f6debf2 100644
--- a/drivers/perf/arm_pmu_platform.c
+++ b/drivers/perf/arm_pmu_platform.c
@@ -169,7 +169,7 @@ static int armpmu_request_irqs(struct arm_pmu *armpmu)
if (!irq)
continue;

- err = armpmu_request_irq(irq, cpu);
+ err = armpmu_request_irq(&hw_events->percpu_pmu, irq, cpu);
if (err)
break;
}
@@ -185,7 +185,7 @@ static void armpmu_free_irqs(struct arm_pmu *armpmu)
for_each_cpu(cpu, &armpmu->supported_cpus) {
int irq = per_cpu(hw_events->irq, cpu);

- armpmu_free_irq(irq, cpu);
+ armpmu_free_irq(&hw_events->percpu_pmu, irq, cpu);
}
}

diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 7bf548678b288..395d03c282e8c 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -191,8 +191,8 @@ bool arm_pmu_irq_is_nmi(void);
struct arm_pmu *armpmu_alloc(void);
void armpmu_free(struct arm_pmu *pmu);
int armpmu_register(struct arm_pmu *pmu);
-int armpmu_request_irq(int irq, int cpu);
-void armpmu_free_irq(int irq, int cpu);
+int armpmu_request_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);
+void armpmu_free_irq(struct arm_pmu * __percpu *armpmu, int irq, int cpu);

#define ARMV8_PMU_PDEV_NAME "armv8-pmu"

--
2.39.2