Skip to content

Commit 6a5dc6c

Browse files
rmurphy-armwilldeacon
authored andcommitted
perf/arm-ni: Consolidate CPU affinity handling
Since overflow interrupts from the individual PMUs are infrequent and unlikely to coincide, and we make no attempt to balance them across CPUs anyway, there's really not much point tracking a separate CPU affinity per PMU. Move the CPU affinity and hotplug migration up to the NI instance level. Tested-by: Shouping Wang <[email protected]> Signed-off-by: Robin Murphy <[email protected]> Link: https://lore.kernel.org/r/00b622872006c2f0c89485e343b1cb8caaa79c47.1752256072.git.robin.murphy@arm.com Signed-off-by: Will Deacon <[email protected]>
1 parent 0259de6 commit 6a5dc6c

File tree

1 file changed

+34
-40
lines changed

1 file changed

+34
-40
lines changed

drivers/perf/arm-ni.c

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ struct arm_ni_cd {
104104
u16 id;
105105
int num_units;
106106
int irq;
107-
int cpu;
108-
struct hlist_node cpuhp_node;
109107
struct pmu pmu;
110108
struct arm_ni_unit *units;
111109
struct perf_event *evcnt[NI_NUM_COUNTERS];
@@ -117,13 +115,18 @@ struct arm_ni {
117115
void __iomem *base;
118116
enum ni_part part;
119117
int id;
118+
int cpu;
120119
int num_cds;
120+
struct hlist_node cpuhp_node;
121121
struct arm_ni_cd cds[] __counted_by(num_cds);
122122
};
123123

124124
#define cd_to_ni(cd) container_of((cd), struct arm_ni, cds[(cd)->id])
125125
#define pmu_to_cd(p) container_of((p), struct arm_ni_cd, pmu)
126126

127+
#define ni_for_each_cd(n, c) \
128+
for (struct arm_ni_cd *c = n->cds; c < n->cds + n->num_cds; c++) if (c->pmu_base)
129+
127130
#define cd_for_each_unit(cd, u) \
128131
for (struct arm_ni_unit *u = cd->units; u < cd->units + cd->num_units; u++)
129132

@@ -218,9 +221,9 @@ static const struct attribute_group arm_ni_format_attrs_group = {
218221
static ssize_t arm_ni_cpumask_show(struct device *dev,
219222
struct device_attribute *attr, char *buf)
220223
{
221-
struct arm_ni_cd *cd = pmu_to_cd(dev_get_drvdata(dev));
224+
struct arm_ni *ni = cd_to_ni(pmu_to_cd(dev_get_drvdata(dev)));
222225

223-
return cpumap_print_to_pagebuf(true, buf, cpumask_of(cd->cpu));
226+
return cpumap_print_to_pagebuf(true, buf, cpumask_of(ni->cpu));
224227
}
225228

226229
static struct device_attribute arm_ni_cpumask_attr =
@@ -314,7 +317,7 @@ static int arm_ni_event_init(struct perf_event *event)
314317
if (is_sampling_event(event))
315318
return -EINVAL;
316319

317-
event->cpu = cd->cpu;
320+
event->cpu = cd_to_ni(cd)->cpu;
318321
if (NI_EVENT_TYPE(event) == NI_PMU)
319322
return arm_ni_validate_group(event);
320323

@@ -543,8 +546,7 @@ static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_s
543546
if (err)
544547
return err;
545548

546-
cd->cpu = cpumask_local_spread(0, dev_to_node(ni->dev));
547-
irq_set_affinity(cd->irq, cpumask_of(cd->cpu));
549+
irq_set_affinity(cd->irq, cpumask_of(ni->cpu));
548550

549551
cd->pmu = (struct pmu) {
550552
.module = THIS_MODULE,
@@ -566,32 +568,19 @@ static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_s
566568
if (!name)
567569
return -ENOMEM;
568570

569-
err = cpuhp_state_add_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
570-
if (err)
571-
return err;
572-
573-
err = perf_pmu_register(&cd->pmu, name, -1);
574-
if (err)
575-
cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
576-
577-
return err;
571+
return perf_pmu_register(&cd->pmu, name, -1);
578572
}
579573

580574
static void arm_ni_remove(struct platform_device *pdev)
581575
{
582576
struct arm_ni *ni = platform_get_drvdata(pdev);
583577

584-
for (int i = 0; i < ni->num_cds; i++) {
585-
struct arm_ni_cd *cd = ni->cds + i;
586-
587-
if (!cd->pmu_base)
588-
continue;
589-
578+
ni_for_each_cd(ni, cd) {
590579
writel_relaxed(0, cd->pmu_base + NI_PMCR);
591580
writel_relaxed(U32_MAX, cd->pmu_base + NI_PMINTENCLR);
592581
perf_pmu_unregister(&cd->pmu);
593-
cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
594582
}
583+
cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &ni->cpuhp_node);
595584
}
596585

597586
static void arm_ni_probe_domain(void __iomem *base, struct arm_ni_node *node)
@@ -611,7 +600,7 @@ static int arm_ni_probe(struct platform_device *pdev)
611600
struct resource *res;
612601
void __iomem *base;
613602
static atomic_t id;
614-
int num_cds;
603+
int ret, num_cds;
615604
u32 reg, part;
616605

617606
/*
@@ -662,17 +651,20 @@ static int arm_ni_probe(struct platform_device *pdev)
662651
ni->num_cds = num_cds;
663652
ni->part = part;
664653
ni->id = atomic_fetch_inc(&id);
654+
ni->cpu = cpumask_local_spread(0, dev_to_node(ni->dev));
665655
platform_set_drvdata(pdev, ni);
666656

657+
ret = cpuhp_state_add_instance_nocalls(arm_ni_hp_state, &ni->cpuhp_node);
658+
if (ret)
659+
return ret;
660+
667661
for (int v = 0; v < cfg.num_components; v++) {
668662
reg = readl_relaxed(cfg.base + NI_CHILD_PTR(v));
669663
arm_ni_probe_domain(base + reg, &vd);
670664
for (int p = 0; p < vd.num_components; p++) {
671665
reg = readl_relaxed(vd.base + NI_CHILD_PTR(p));
672666
arm_ni_probe_domain(base + reg, &pd);
673667
for (int c = 0; c < pd.num_components; c++) {
674-
int ret;
675-
676668
reg = readl_relaxed(pd.base + NI_CHILD_PTR(c));
677669
arm_ni_probe_domain(base + reg, &cd);
678670
ret = arm_ni_init_cd(ni, &cd, res->start);
@@ -715,42 +707,44 @@ static struct platform_driver arm_ni_driver = {
715707
.remove = arm_ni_remove,
716708
};
717709

718-
static void arm_ni_pmu_migrate(struct arm_ni_cd *cd, unsigned int cpu)
710+
static void arm_ni_pmu_migrate(struct arm_ni *ni, unsigned int cpu)
719711
{
720-
perf_pmu_migrate_context(&cd->pmu, cd->cpu, cpu);
721-
irq_set_affinity(cd->irq, cpumask_of(cpu));
722-
cd->cpu = cpu;
712+
ni_for_each_cd(ni, cd) {
713+
perf_pmu_migrate_context(&cd->pmu, ni->cpu, cpu);
714+
irq_set_affinity(cd->irq, cpumask_of(cpu));
715+
}
716+
ni->cpu = cpu;
723717
}
724718

725719
static int arm_ni_pmu_online_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
726720
{
727-
struct arm_ni_cd *cd;
721+
struct arm_ni *ni;
728722
int node;
729723

730-
cd = hlist_entry_safe(cpuhp_node, struct arm_ni_cd, cpuhp_node);
731-
node = dev_to_node(cd_to_ni(cd)->dev);
732-
if (cpu_to_node(cd->cpu) != node && cpu_to_node(cpu) == node)
733-
arm_ni_pmu_migrate(cd, cpu);
724+
ni = hlist_entry_safe(cpuhp_node, struct arm_ni, cpuhp_node);
725+
node = dev_to_node(ni->dev);
726+
if (cpu_to_node(ni->cpu) != node && cpu_to_node(cpu) == node)
727+
arm_ni_pmu_migrate(ni, cpu);
734728
return 0;
735729
}
736730

737731
static int arm_ni_pmu_offline_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
738732
{
739-
struct arm_ni_cd *cd;
733+
struct arm_ni *ni;
740734
unsigned int target;
741735
int node;
742736

743-
cd = hlist_entry_safe(cpuhp_node, struct arm_ni_cd, cpuhp_node);
744-
if (cpu != cd->cpu)
737+
ni = hlist_entry_safe(cpuhp_node, struct arm_ni, cpuhp_node);
738+
if (cpu != ni->cpu)
745739
return 0;
746740

747-
node = dev_to_node(cd_to_ni(cd)->dev);
741+
node = dev_to_node(ni->dev);
748742
target = cpumask_any_and_but(cpumask_of_node(node), cpu_online_mask, cpu);
749743
if (target >= nr_cpu_ids)
750744
target = cpumask_any_but(cpu_online_mask, cpu);
751745

752746
if (target < nr_cpu_ids)
753-
arm_ni_pmu_migrate(cd, target);
747+
arm_ni_pmu_migrate(ni, target);
754748
return 0;
755749
}
756750

0 commit comments

Comments
 (0)