Skip to content

Commit 0e2663d

Browse files
mrutland-armwildea01
authored andcommitted
drivers/perf: arm_pmu: split cpu-local irq request/free
Currently we have functions to request/free all IRQs for a given PMU. While this works today, this won't work for ACPI, where we don't know the full set of IRQs up front, and need to request them separately. To enable supporting ACPI, this patch splits out the cpu-local request/free into new functions, allowing us to request/free individual IRQs. As this makes it possible/necessary to request a PPI once per cpu, an additional check is added to detect mismatched PPIs. This shouldn't matter for the DT / platform case, as we check this when parsing. Signed-off-by: Mark Rutland <[email protected]> Tested-by: Jeremy Linton <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 3cf6111 commit 0e2663d

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

drivers/perf/arm_pmu.c

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -527,65 +527,81 @@ int perf_num_counters(void)
527527
}
528528
EXPORT_SYMBOL_GPL(perf_num_counters);
529529

530-
static void armpmu_free_irqs(struct arm_pmu *armpmu)
530+
static void armpmu_free_irq(struct arm_pmu *armpmu, int cpu)
531531
{
532-
int cpu;
533532
struct pmu_hw_events __percpu *hw_events = armpmu->hw_events;
533+
int irq = per_cpu(hw_events->irq, cpu);
534534

535-
for_each_cpu(cpu, &armpmu->supported_cpus) {
536-
int irq = per_cpu(hw_events->irq, cpu);
537-
if (!irq)
538-
continue;
535+
if (!cpumask_test_and_clear_cpu(cpu, &armpmu->active_irqs))
536+
return;
539537

540-
if (irq_is_percpu(irq)) {
541-
free_percpu_irq(irq, &hw_events->percpu_pmu);
542-
break;
543-
}
538+
if (irq_is_percpu(irq)) {
539+
free_percpu_irq(irq, &hw_events->percpu_pmu);
540+
cpumask_clear(&armpmu->active_irqs);
541+
return;
542+
}
544543

545-
if (!cpumask_test_and_clear_cpu(cpu, &armpmu->active_irqs))
546-
continue;
544+
free_irq(irq, per_cpu_ptr(&hw_events->percpu_pmu, cpu));
545+
}
547546

548-
free_irq(irq, per_cpu_ptr(&hw_events->percpu_pmu, cpu));
549-
}
547+
static void armpmu_free_irqs(struct arm_pmu *armpmu)
548+
{
549+
int cpu;
550+
551+
for_each_cpu(cpu, &armpmu->supported_cpus)
552+
armpmu_free_irq(armpmu, cpu);
550553
}
551554

552-
static int armpmu_request_irqs(struct arm_pmu *armpmu)
555+
static int armpmu_request_irq(struct arm_pmu *armpmu, int cpu)
553556
{
554-
int cpu, err;
557+
int err = 0;
555558
struct pmu_hw_events __percpu *hw_events = armpmu->hw_events;
556559
const irq_handler_t handler = armpmu_dispatch_irq;
560+
int irq = per_cpu(hw_events->irq, cpu);
561+
if (!irq)
562+
return 0;
557563

558-
for_each_cpu(cpu, &armpmu->supported_cpus) {
559-
int irq = per_cpu(hw_events->irq, cpu);
560-
if (!irq)
561-
continue;
564+
if (irq_is_percpu(irq) && cpumask_empty(&armpmu->active_irqs)) {
565+
err = request_percpu_irq(irq, handler, "arm-pmu",
566+
&hw_events->percpu_pmu);
567+
} else if (irq_is_percpu(irq)) {
568+
int other_cpu = cpumask_first(&armpmu->active_irqs);
569+
int other_irq = per_cpu(hw_events->irq, other_cpu);
562570

563-
if (irq_is_percpu(irq)) {
564-
err = request_percpu_irq(irq, handler, "arm-pmu",
565-
&hw_events->percpu_pmu);
566-
if (err) {
567-
pr_err("unable to request IRQ%d for ARM PMU counters\n",
568-
irq);
569-
}
570-
571-
return err;
571+
if (irq != other_irq) {
572+
pr_warn("mismatched PPIs detected.\n");
573+
err = -EINVAL;
572574
}
573-
575+
} else {
574576
err = request_irq(irq, handler,
575577
IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu",
576578
per_cpu_ptr(&hw_events->percpu_pmu, cpu));
577-
if (err) {
578-
pr_err("unable to request IRQ%d for ARM PMU counters\n",
579-
irq);
580-
return err;
581-
}
579+
}
582580

583-
cpumask_set_cpu(cpu, &armpmu->active_irqs);
581+
if (err) {
582+
pr_err("unable to request IRQ%d for ARM PMU counters\n",
583+
irq);
584+
return err;
584585
}
585586

587+
cpumask_set_cpu(cpu, &armpmu->active_irqs);
588+
586589
return 0;
587590
}
588591

592+
static int armpmu_request_irqs(struct arm_pmu *armpmu)
593+
{
594+
int cpu, err;
595+
596+
for_each_cpu(cpu, &armpmu->supported_cpus) {
597+
err = armpmu_request_irq(armpmu, cpu);
598+
if (err)
599+
break;
600+
}
601+
602+
return err;
603+
}
604+
589605
static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu)
590606
{
591607
struct pmu_hw_events __percpu *hw_events = pmu->hw_events;

0 commit comments

Comments
 (0)