Skip to content

Commit 2e5d34d

Browse files
committed
Merge branch 'for-next/perf' into for-next/core
PMU driver cleanups for managing IRQ affinity and exposing event attributes via sysfs. * for-next/perf: (36 commits) drivers/perf: fix the missed ida_simple_remove() in ddr_perf_probe() perf/arm-cmn: Fix invalid pointer when access dtc object sharing the same IRQ number arm64: perf: Simplify EVENT ATTR macro in perf_event.c drivers/perf: Simplify EVENT ATTR macro in fsl_imx8_ddr_perf.c drivers/perf: Simplify EVENT ATTR macro in xgene_pmu.c drivers/perf: Simplify EVENT ATTR macro in qcom_l3_pmu.c drivers/perf: Simplify EVENT ATTR macro in qcom_l2_pmu.c drivers/perf: Simplify EVENT ATTR macro in SMMU PMU driver perf: Add EVENT_ATTR_ID to simplify event attributes perf/smmuv3: Don't trample existing events with global filter perf/hisi: Constify static attribute_group structs perf: qcom: Remove redundant dev_err call in qcom_l3_cache_pmu_probe() drivers/perf: hisi: Fix data source control arm64: perf: Add more support on caps under sysfs perf: qcom_l2_pmu: move to use request_irq by IRQF_NO_AUTOEN flag arm_pmu: move to use request_irq by IRQF_NO_AUTOEN flag perf: arm_spe: use DEVICE_ATTR_RO macro perf: xgene_pmu: use DEVICE_ATTR_RO macro perf: qcom: use DEVICE_ATTR_RO macro perf: arm_pmu: use DEVICE_ATTR_RO macro ...
2 parents fdceddb + d96b1b8 commit 2e5d34d

26 files changed

Lines changed: 156 additions & 170 deletions

arch/arm/kernel/perf_event_v7.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -773,10 +773,10 @@ static inline void armv7pmu_write_counter(struct perf_event *event, u64 value)
773773
pr_err("CPU%u writing wrong counter %d\n",
774774
smp_processor_id(), idx);
775775
} else if (idx == ARMV7_IDX_CYCLE_COUNTER) {
776-
asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
776+
asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" ((u32)value));
777777
} else {
778778
armv7_pmnc_select_counter(idx);
779-
asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
779+
asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" ((u32)value));
780780
}
781781
}
782782

arch/arm64/include/asm/perf_event.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@
239239
/* PMMIR_EL1.SLOTS mask */
240240
#define ARMV8_PMU_SLOTS_MASK 0xff
241241

242+
#define ARMV8_PMU_BUS_SLOTS_SHIFT 8
243+
#define ARMV8_PMU_BUS_SLOTS_MASK 0xff
244+
#define ARMV8_PMU_BUS_WIDTH_SHIFT 16
245+
#define ARMV8_PMU_BUS_WIDTH_MASK 0xf
246+
242247
#ifdef CONFIG_PERF_EVENTS
243248
struct pt_regs;
244249
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);

arch/arm64/kernel/perf_event.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,7 @@ armv8pmu_events_sysfs_show(struct device *dev,
165165
}
166166

167167
#define ARMV8_EVENT_ATTR(name, config) \
168-
(&((struct perf_pmu_events_attr) { \
169-
.attr = __ATTR(name, 0444, armv8pmu_events_sysfs_show, NULL), \
170-
.id = config, \
171-
}).attr.attr)
168+
PMU_EVENT_ATTR_ID(name, armv8pmu_events_sysfs_show, config)
172169

173170
static struct attribute *armv8_pmuv3_event_attrs[] = {
174171
ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR),
@@ -312,13 +309,46 @@ static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
312309
struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
313310
u32 slots = cpu_pmu->reg_pmmir & ARMV8_PMU_SLOTS_MASK;
314311

315-
return snprintf(page, PAGE_SIZE, "0x%08x\n", slots);
312+
return sysfs_emit(page, "0x%08x\n", slots);
316313
}
317314

318315
static DEVICE_ATTR_RO(slots);
319316

317+
static ssize_t bus_slots_show(struct device *dev, struct device_attribute *attr,
318+
char *page)
319+
{
320+
struct pmu *pmu = dev_get_drvdata(dev);
321+
struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
322+
u32 bus_slots = (cpu_pmu->reg_pmmir >> ARMV8_PMU_BUS_SLOTS_SHIFT)
323+
& ARMV8_PMU_BUS_SLOTS_MASK;
324+
325+
return sysfs_emit(page, "0x%08x\n", bus_slots);
326+
}
327+
328+
static DEVICE_ATTR_RO(bus_slots);
329+
330+
static ssize_t bus_width_show(struct device *dev, struct device_attribute *attr,
331+
char *page)
332+
{
333+
struct pmu *pmu = dev_get_drvdata(dev);
334+
struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
335+
u32 bus_width = (cpu_pmu->reg_pmmir >> ARMV8_PMU_BUS_WIDTH_SHIFT)
336+
& ARMV8_PMU_BUS_WIDTH_MASK;
337+
u32 val = 0;
338+
339+
/* Encoded as Log2(number of bytes), plus one */
340+
if (bus_width > 2 && bus_width < 13)
341+
val = 1 << (bus_width - 1);
342+
343+
return sysfs_emit(page, "0x%08x\n", val);
344+
}
345+
346+
static DEVICE_ATTR_RO(bus_width);
347+
320348
static struct attribute *armv8_pmuv3_caps_attrs[] = {
321349
&dev_attr_slots.attr,
350+
&dev_attr_bus_slots.attr,
351+
&dev_attr_bus_width.attr,
322352
NULL,
323353
};
324354

drivers/perf/arm-cci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
#define CCI_PMU_CNTR_SIZE(model) ((model)->cntr_size)
3939
#define CCI_PMU_CNTR_BASE(model, idx) ((idx) * CCI_PMU_CNTR_SIZE(model))
40-
#define CCI_PMU_CNTR_MASK ((1ULL << 32) -1)
40+
#define CCI_PMU_CNTR_MASK ((1ULL << 32) - 1)
4141
#define CCI_PMU_CNTR_LAST(cci_pmu) (cci_pmu->num_cntrs - 1)
4242

4343
#define CCI_PMU_MAX_HW_CNTRS(model) \
@@ -806,7 +806,7 @@ static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *ev
806806
return cci_pmu->model->get_event_idx(cci_pmu, hw, cci_event);
807807

808808
/* Generic code to find an unused idx from the mask */
809-
for(idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++)
809+
for (idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++)
810810
if (!test_and_set_bit(idx, hw->used_mask))
811811
return idx;
812812

drivers/perf/arm-ccn.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@ static int arm_ccn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
12111211
perf_pmu_migrate_context(&dt->pmu, cpu, target);
12121212
dt->cpu = target;
12131213
if (ccn->irq)
1214-
WARN_ON(irq_set_affinity_hint(ccn->irq, cpumask_of(dt->cpu)));
1214+
WARN_ON(irq_set_affinity(ccn->irq, cpumask_of(dt->cpu)));
12151215
return 0;
12161216
}
12171217

@@ -1291,7 +1291,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
12911291

12921292
/* Also make sure that the overflow interrupt is handled by this CPU */
12931293
if (ccn->irq) {
1294-
err = irq_set_affinity_hint(ccn->irq, cpumask_of(ccn->dt.cpu));
1294+
err = irq_set_affinity(ccn->irq, cpumask_of(ccn->dt.cpu));
12951295
if (err) {
12961296
dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
12971297
goto error_set_affinity;
@@ -1325,8 +1325,6 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
13251325

13261326
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE,
13271327
&ccn->dt.node);
1328-
if (ccn->irq)
1329-
irq_set_affinity_hint(ccn->irq, NULL);
13301328
for (i = 0; i < ccn->num_xps; i++)
13311329
writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
13321330
writel(0, ccn->dt.base + CCN_DT_PMCR);

drivers/perf/arm-cmn.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0)
3232
#define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16)
3333

34-
#define CMN_CHILD_NODE_ADDR GENMASK(27,0)
34+
#define CMN_CHILD_NODE_ADDR GENMASK(27, 0)
3535
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
3636

3737
#define CMN_ADDR_NODE_PTR GENMASK(27, 14)
@@ -1162,7 +1162,7 @@ static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
11621162

11631163
perf_pmu_migrate_context(&cmn->pmu, cpu, target);
11641164
for (i = 0; i < cmn->num_dtcs; i++)
1165-
irq_set_affinity_hint(cmn->dtc[i].irq, cpumask_of(target));
1165+
irq_set_affinity(cmn->dtc[i].irq, cpumask_of(target));
11661166
cmn->cpu = target;
11671167
return 0;
11681168
}
@@ -1212,7 +1212,7 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
12121212
irq = cmn->dtc[i].irq;
12131213
for (j = i; j--; ) {
12141214
if (cmn->dtc[j].irq == irq) {
1215-
cmn->dtc[j].irq_friend = j - i;
1215+
cmn->dtc[j].irq_friend = i - j;
12161216
goto next;
12171217
}
12181218
}
@@ -1222,7 +1222,7 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
12221222
if (err)
12231223
return err;
12241224

1225-
err = irq_set_affinity_hint(irq, cpumask_of(cmn->cpu));
1225+
err = irq_set_affinity(irq, cpumask_of(cmn->cpu));
12261226
if (err)
12271227
return err;
12281228
next:
@@ -1568,16 +1568,11 @@ static int arm_cmn_probe(struct platform_device *pdev)
15681568
static int arm_cmn_remove(struct platform_device *pdev)
15691569
{
15701570
struct arm_cmn *cmn = platform_get_drvdata(pdev);
1571-
int i;
15721571

15731572
writel_relaxed(0, cmn->dtc[0].base + CMN_DT_DTC_CTL);
15741573

15751574
perf_pmu_unregister(&cmn->pmu);
15761575
cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node);
1577-
1578-
for (i = 0; i < cmn->num_dtcs; i++)
1579-
irq_set_affinity_hint(cmn->dtc[i].irq, NULL);
1580-
15811576
return 0;
15821577
}
15831578

drivers/perf/arm_dmc620_pmu.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ static struct dmc620_pmu_irq *__dmc620_pmu_get_irq(int irq_num)
421421
if (ret)
422422
goto out_free_aff;
423423

424-
ret = irq_set_affinity_hint(irq_num, cpumask_of(irq->cpu));
424+
ret = irq_set_affinity(irq_num, cpumask_of(irq->cpu));
425425
if (ret)
426426
goto out_free_irq;
427427

@@ -475,7 +475,6 @@ static void dmc620_pmu_put_irq(struct dmc620_pmu *dmc620_pmu)
475475
list_del(&irq->irqs_node);
476476
mutex_unlock(&dmc620_pmu_irqs_lock);
477477

478-
WARN_ON(irq_set_affinity_hint(irq->irq_num, NULL));
479478
free_irq(irq->irq_num, irq);
480479
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &irq->node);
481480
kfree(irq);
@@ -622,7 +621,7 @@ static int dmc620_pmu_cpu_teardown(unsigned int cpu,
622621
perf_pmu_migrate_context(&dmc620_pmu->pmu, irq->cpu, target);
623622
mutex_unlock(&dmc620_pmu_irqs_lock);
624623

625-
WARN_ON(irq_set_affinity_hint(irq->irq_num, cpumask_of(target)));
624+
WARN_ON(irq_set_affinity(irq->irq_num, cpumask_of(target)));
626625
irq->cpu = target;
627626

628627
return 0;

drivers/perf/arm_dsu_pmu.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
687687
static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu)
688688
{
689689
cpumask_set_cpu(cpu, &dsu_pmu->active_cpu);
690-
if (irq_set_affinity_hint(dsu_pmu->irq, &dsu_pmu->active_cpu))
690+
if (irq_set_affinity(dsu_pmu->irq, &dsu_pmu->active_cpu))
691691
pr_warn("Failed to set irq affinity to %d\n", cpu);
692692
}
693693

@@ -769,7 +769,6 @@ static int dsu_pmu_device_probe(struct platform_device *pdev)
769769
if (rc) {
770770
cpuhp_state_remove_instance(dsu_pmu_cpuhp_state,
771771
&dsu_pmu->cpuhp_node);
772-
irq_set_affinity_hint(dsu_pmu->irq, NULL);
773772
}
774773

775774
return rc;
@@ -781,7 +780,6 @@ static int dsu_pmu_device_remove(struct platform_device *pdev)
781780

782781
perf_pmu_unregister(&dsu_pmu->pmu);
783782
cpuhp_state_remove_instance(dsu_pmu_cpuhp_state, &dsu_pmu->cpuhp_node);
784-
irq_set_affinity_hint(dsu_pmu->irq, NULL);
785783

786784
return 0;
787785
}
@@ -840,10 +838,8 @@ static int dsu_pmu_cpu_teardown(unsigned int cpu, struct hlist_node *node)
840838

841839
dst = dsu_pmu_get_online_cpu_any_but(dsu_pmu, cpu);
842840
/* If there are no active CPUs in the DSU, leave IRQ disabled */
843-
if (dst >= nr_cpu_ids) {
844-
irq_set_affinity_hint(dsu_pmu->irq, NULL);
841+
if (dst >= nr_cpu_ids)
845842
return 0;
846-
}
847843

848844
perf_pmu_migrate_context(&dsu_pmu->pmu, cpu, dst);
849845
dsu_pmu_set_active_cpu(dst, dsu_pmu);

drivers/perf/arm_pmu.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -563,14 +563,14 @@ static int armpmu_filter_match(struct perf_event *event)
563563
return ret;
564564
}
565565

566-
static ssize_t armpmu_cpumask_show(struct device *dev,
567-
struct device_attribute *attr, char *buf)
566+
static ssize_t cpus_show(struct device *dev,
567+
struct device_attribute *attr, char *buf)
568568
{
569569
struct arm_pmu *armpmu = to_arm_pmu(dev_get_drvdata(dev));
570570
return cpumap_print_to_pagebuf(true, buf, &armpmu->supported_cpus);
571571
}
572572

573-
static DEVICE_ATTR(cpus, S_IRUGO, armpmu_cpumask_show, NULL);
573+
static DEVICE_ATTR_RO(cpus);
574574

575575
static struct attribute *armpmu_common_attrs[] = {
576576
&dev_attr_cpus.attr,
@@ -644,11 +644,9 @@ int armpmu_request_irq(int irq, int cpu)
644644
}
645645

646646
irq_flags = IRQF_PERCPU |
647-
IRQF_NOBALANCING |
647+
IRQF_NOBALANCING | IRQF_NO_AUTOEN |
648648
IRQF_NO_THREAD;
649649

650-
irq_set_status_flags(irq, IRQ_NOAUTOEN);
651-
652650
err = request_nmi(irq, handler, irq_flags, "arm-pmu",
653651
per_cpu_ptr(&cpu_armpmu, cpu));
654652

@@ -670,7 +668,7 @@ int armpmu_request_irq(int irq, int cpu)
670668
&cpu_armpmu);
671669
irq_ops = &percpu_pmuirq_ops;
672670
} else {
673-
has_nmi= true;
671+
has_nmi = true;
674672
irq_ops = &percpu_pmunmi_ops;
675673
}
676674
} else {
@@ -869,10 +867,8 @@ static struct arm_pmu *__armpmu_alloc(gfp_t flags)
869867
int cpu;
870868

871869
pmu = kzalloc(sizeof(*pmu), flags);
872-
if (!pmu) {
873-
pr_info("failed to allocate PMU device!\n");
870+
if (!pmu)
874871
goto out;
875-
}
876872

877873
pmu->hw_events = alloc_percpu_gfp(struct pmu_hw_events, flags);
878874
if (!pmu->hw_events) {

drivers/perf/arm_smmuv3_pmu.c

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -277,25 +277,27 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
277277
struct perf_event *event, int idx)
278278
{
279279
u32 span, sid;
280-
unsigned int num_ctrs = smmu_pmu->num_counters;
280+
unsigned int cur_idx, num_ctrs = smmu_pmu->num_counters;
281281
bool filter_en = !!get_filter_enable(event);
282282

283283
span = filter_en ? get_filter_span(event) :
284284
SMMU_PMCG_DEFAULT_FILTER_SPAN;
285285
sid = filter_en ? get_filter_stream_id(event) :
286286
SMMU_PMCG_DEFAULT_FILTER_SID;
287287

288-
/* Support individual filter settings */
289-
if (!smmu_pmu->global_filter) {
288+
cur_idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
289+
/*
290+
* Per-counter filtering, or scheduling the first globally-filtered
291+
* event into an empty PMU so idx == 0 and it works out equivalent.
292+
*/
293+
if (!smmu_pmu->global_filter || cur_idx == num_ctrs) {
290294
smmu_pmu_set_event_filter(event, idx, span, sid);
291295
return 0;
292296
}
293297

294-
/* Requested settings same as current global settings*/
295-
idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
296-
if (idx == num_ctrs ||
297-
smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) {
298-
smmu_pmu_set_event_filter(event, 0, span, sid);
298+
/* Otherwise, must match whatever's currently scheduled */
299+
if (smmu_pmu_check_global_filter(smmu_pmu->events[cur_idx], event)) {
300+
smmu_pmu_set_evtyper(smmu_pmu, idx, get_event(event));
299301
return 0;
300302
}
301303

@@ -509,11 +511,8 @@ static ssize_t smmu_pmu_event_show(struct device *dev,
509511
return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
510512
}
511513

512-
#define SMMU_EVENT_ATTR(name, config) \
513-
(&((struct perf_pmu_events_attr) { \
514-
.attr = __ATTR(name, 0444, smmu_pmu_event_show, NULL), \
515-
.id = config, \
516-
}).attr.attr)
514+
#define SMMU_EVENT_ATTR(name, config) \
515+
PMU_EVENT_ATTR_ID(name, smmu_pmu_event_show, config)
517516

518517
static struct attribute *smmu_pmu_events[] = {
519518
SMMU_EVENT_ATTR(cycles, 0),
@@ -628,7 +627,7 @@ static int smmu_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
628627

629628
perf_pmu_migrate_context(&smmu_pmu->pmu, cpu, target);
630629
smmu_pmu->on_cpu = target;
631-
WARN_ON(irq_set_affinity_hint(smmu_pmu->irq, cpumask_of(target)));
630+
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(target)));
632631

633632
return 0;
634633
}
@@ -839,15 +838,14 @@ static int smmu_pmu_probe(struct platform_device *pdev)
839838

840839
/* Pick one CPU to be the preferred one to use */
841840
smmu_pmu->on_cpu = raw_smp_processor_id();
842-
WARN_ON(irq_set_affinity_hint(smmu_pmu->irq,
843-
cpumask_of(smmu_pmu->on_cpu)));
841+
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
844842

845843
err = cpuhp_state_add_instance_nocalls(cpuhp_state_num,
846844
&smmu_pmu->node);
847845
if (err) {
848846
dev_err(dev, "Error %d registering hotplug, PMU @%pa\n",
849847
err, &res_0->start);
850-
goto out_clear_affinity;
848+
return err;
851849
}
852850

853851
err = perf_pmu_register(&smmu_pmu->pmu, name, -1);
@@ -866,8 +864,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
866864

867865
out_unregister:
868866
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
869-
out_clear_affinity:
870-
irq_set_affinity_hint(smmu_pmu->irq, NULL);
871867
return err;
872868
}
873869

@@ -877,7 +873,6 @@ static int smmu_pmu_remove(struct platform_device *pdev)
877873

878874
perf_pmu_unregister(&smmu_pmu->pmu);
879875
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
880-
irq_set_affinity_hint(smmu_pmu->irq, NULL);
881876

882877
return 0;
883878
}

0 commit comments

Comments
 (0)