Skip to content

Commit 1a51688

Browse files
Junhao Hewilldeacon
authored andcommitted
drivers/perf: hisi: Add support for HiSilicon H60PA and PAv3 PMU driver
Compared to the original PA device, H60PA offers higher bandwidth. The H60PA is a new device and we use HID to differentiate them. The events supported by PAv3 and PAv2 are different. The PAv3 PMU removed some events which are supported by PAv2 PMU. The older PA PMU driver will probe v3 as v2. Therefore PA events displayed by "perf list" cannot work properly. We add the HISI0275 HID for PAv3 PMU to distinguish different. For each H60PA PMU, except for the overflow interrupt register, other functions of the H60PA PMU are the same as the original PA PMU module. It has 8-programable counters and each counter is free-running. Interrupt is supported to handle counter (64-bits) overflow. Signed-off-by: Junhao He <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Reviewed-by: Yicong Yang <[email protected]> Acked-by: Mark Rutland <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 7e51d05 commit 1a51688

File tree

2 files changed

+120
-15
lines changed

2 files changed

+120
-15
lines changed

drivers/perf/hisilicon/hisi_uncore_pa_pmu.c

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@
2222
#define PA_TT_CTRL 0x1c08
2323
#define PA_TGTID_CTRL 0x1c14
2424
#define PA_SRCID_CTRL 0x1c18
25+
26+
/* H32 PA interrupt registers */
2527
#define PA_INT_MASK 0x1c70
2628
#define PA_INT_STATUS 0x1c78
2729
#define PA_INT_CLEAR 0x1c7c
30+
31+
#define H60PA_INT_STATUS 0x1c70
32+
#define H60PA_INT_MASK 0x1c74
33+
2834
#define PA_EVENT_TYPE0 0x1c80
2935
#define PA_PMU_VERSION 0x1cf0
3036
#define PA_EVENT_CNT0_L 0x1d00
@@ -46,6 +52,12 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
4652
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
4753
HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
4854

55+
struct hisi_pa_pmu_int_regs {
56+
u32 mask_offset;
57+
u32 clear_offset;
58+
u32 status_offset;
59+
};
60+
4961
static void hisi_pa_pmu_enable_tracetag(struct perf_event *event)
5062
{
5163
struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
@@ -219,40 +231,40 @@ static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu,
219231
static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu,
220232
struct hw_perf_event *hwc)
221233
{
234+
struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
222235
u32 val;
223236

224237
/* Write 0 to enable interrupt */
225-
val = readl(pa_pmu->base + PA_INT_MASK);
238+
val = readl(pa_pmu->base + regs->mask_offset);
226239
val &= ~(1 << hwc->idx);
227-
writel(val, pa_pmu->base + PA_INT_MASK);
240+
writel(val, pa_pmu->base + regs->mask_offset);
228241
}
229242

230243
static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu,
231244
struct hw_perf_event *hwc)
232245
{
246+
struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
233247
u32 val;
234248

235249
/* Write 1 to mask interrupt */
236-
val = readl(pa_pmu->base + PA_INT_MASK);
250+
val = readl(pa_pmu->base + regs->mask_offset);
237251
val |= 1 << hwc->idx;
238-
writel(val, pa_pmu->base + PA_INT_MASK);
252+
writel(val, pa_pmu->base + regs->mask_offset);
239253
}
240254

241255
static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu)
242256
{
243-
return readl(pa_pmu->base + PA_INT_STATUS);
257+
struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
258+
259+
return readl(pa_pmu->base + regs->status_offset);
244260
}
245261

246262
static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx)
247263
{
248-
writel(1 << idx, pa_pmu->base + PA_INT_CLEAR);
249-
}
264+
struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
250265

251-
static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
252-
{ "HISI0273", },
253-
{}
254-
};
255-
MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
266+
writel(1 << idx, pa_pmu->base + regs->clear_offset);
267+
}
256268

257269
static int hisi_pa_pmu_init_data(struct platform_device *pdev,
258270
struct hisi_pmu *pa_pmu)
@@ -276,6 +288,10 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
276288
pa_pmu->ccl_id = -1;
277289
pa_pmu->sccl_id = -1;
278290

291+
pa_pmu->dev_info = device_get_match_data(&pdev->dev);
292+
if (!pa_pmu->dev_info)
293+
return -ENODEV;
294+
279295
pa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
280296
if (IS_ERR(pa_pmu->base)) {
281297
dev_err(&pdev->dev, "ioremap failed for pa_pmu resource.\n");
@@ -314,6 +330,32 @@ static const struct attribute_group hisi_pa_pmu_v2_events_group = {
314330
.attrs = hisi_pa_pmu_v2_events_attr,
315331
};
316332

333+
static struct attribute *hisi_pa_pmu_v3_events_attr[] = {
334+
HISI_PMU_EVENT_ATTR(tx_req, 0x0),
335+
HISI_PMU_EVENT_ATTR(tx_dat, 0x1),
336+
HISI_PMU_EVENT_ATTR(tx_snp, 0x2),
337+
HISI_PMU_EVENT_ATTR(rx_req, 0x7),
338+
HISI_PMU_EVENT_ATTR(rx_dat, 0x8),
339+
HISI_PMU_EVENT_ATTR(rx_snp, 0x9),
340+
NULL
341+
};
342+
343+
static const struct attribute_group hisi_pa_pmu_v3_events_group = {
344+
.name = "events",
345+
.attrs = hisi_pa_pmu_v3_events_attr,
346+
};
347+
348+
static struct attribute *hisi_h60pa_pmu_events_attr[] = {
349+
HISI_PMU_EVENT_ATTR(rx_flit, 0x50),
350+
HISI_PMU_EVENT_ATTR(tx_flit, 0x65),
351+
NULL
352+
};
353+
354+
static const struct attribute_group hisi_h60pa_pmu_events_group = {
355+
.name = "events",
356+
.attrs = hisi_h60pa_pmu_events_attr,
357+
};
358+
317359
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
318360

319361
static struct attribute *hisi_pa_pmu_cpumask_attrs[] = {
@@ -337,6 +379,12 @@ static const struct attribute_group hisi_pa_pmu_identifier_group = {
337379
.attrs = hisi_pa_pmu_identifier_attrs,
338380
};
339381

382+
static struct hisi_pa_pmu_int_regs hisi_pa_pmu_regs = {
383+
.mask_offset = PA_INT_MASK,
384+
.clear_offset = PA_INT_CLEAR,
385+
.status_offset = PA_INT_STATUS,
386+
};
387+
340388
static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
341389
&hisi_pa_pmu_v2_format_group,
342390
&hisi_pa_pmu_v2_events_group,
@@ -345,6 +393,46 @@ static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
345393
NULL
346394
};
347395

396+
static const struct hisi_pmu_dev_info hisi_h32pa_v2 = {
397+
.name = "pa",
398+
.attr_groups = hisi_pa_pmu_v2_attr_groups,
399+
.private = &hisi_pa_pmu_regs,
400+
};
401+
402+
static const struct attribute_group *hisi_pa_pmu_v3_attr_groups[] = {
403+
&hisi_pa_pmu_v2_format_group,
404+
&hisi_pa_pmu_v3_events_group,
405+
&hisi_pa_pmu_cpumask_attr_group,
406+
&hisi_pa_pmu_identifier_group,
407+
NULL
408+
};
409+
410+
static const struct hisi_pmu_dev_info hisi_h32pa_v3 = {
411+
.name = "pa",
412+
.attr_groups = hisi_pa_pmu_v3_attr_groups,
413+
.private = &hisi_pa_pmu_regs,
414+
};
415+
416+
static struct hisi_pa_pmu_int_regs hisi_h60pa_pmu_regs = {
417+
.mask_offset = H60PA_INT_MASK,
418+
.clear_offset = H60PA_INT_STATUS, /* Clear on write */
419+
.status_offset = H60PA_INT_STATUS,
420+
};
421+
422+
static const struct attribute_group *hisi_h60pa_pmu_attr_groups[] = {
423+
&hisi_pa_pmu_v2_format_group,
424+
&hisi_h60pa_pmu_events_group,
425+
&hisi_pa_pmu_cpumask_attr_group,
426+
&hisi_pa_pmu_identifier_group,
427+
NULL
428+
};
429+
430+
static const struct hisi_pmu_dev_info hisi_h60pa = {
431+
.name = "h60pa",
432+
.attr_groups = hisi_h60pa_pmu_attr_groups,
433+
.private = &hisi_h60pa_pmu_regs,
434+
};
435+
348436
static const struct hisi_uncore_ops hisi_uncore_pa_ops = {
349437
.write_evtype = hisi_pa_pmu_write_evtype,
350438
.get_event_idx = hisi_uncore_pmu_get_event_idx,
@@ -375,7 +463,7 @@ static int hisi_pa_pmu_dev_probe(struct platform_device *pdev,
375463
if (ret)
376464
return ret;
377465

378-
pa_pmu->pmu_events.attr_groups = hisi_pa_pmu_v2_attr_groups;
466+
pa_pmu->pmu_events.attr_groups = pa_pmu->dev_info->attr_groups;
379467
pa_pmu->num_counters = PA_NR_COUNTERS;
380468
pa_pmu->ops = &hisi_uncore_pa_ops;
381469
pa_pmu->check_event = 0xB0;
@@ -400,8 +488,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
400488
if (ret)
401489
return ret;
402490

403-
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u",
404-
pa_pmu->sicl_id, pa_pmu->index_id);
491+
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_%s%u",
492+
pa_pmu->sicl_id, pa_pmu->dev_info->name,
493+
pa_pmu->index_id);
405494
if (!name)
406495
return -ENOMEM;
407496

@@ -435,6 +524,14 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev)
435524
return 0;
436525
}
437526

527+
static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
528+
{ "HISI0273", (kernel_ulong_t)&hisi_h32pa_v2 },
529+
{ "HISI0275", (kernel_ulong_t)&hisi_h32pa_v3 },
530+
{ "HISI0274", (kernel_ulong_t)&hisi_h60pa },
531+
{}
532+
};
533+
MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
534+
438535
static struct platform_driver hisi_pa_pmu_driver = {
439536
.driver = {
440537
.name = "hisi_pa_pmu",

drivers/perf/hisilicon/hisi_uncore_pmu.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ struct hisi_uncore_ops {
6262
void (*disable_filter)(struct perf_event *event);
6363
};
6464

65+
/* Describes the HISI PMU chip features information */
66+
struct hisi_pmu_dev_info {
67+
const char *name;
68+
const struct attribute_group **attr_groups;
69+
void *private;
70+
};
71+
6572
struct hisi_pmu_hwevents {
6673
struct perf_event *hw_events[HISI_MAX_COUNTERS];
6774
DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
@@ -72,6 +79,7 @@ struct hisi_pmu_hwevents {
7279
struct hisi_pmu {
7380
struct pmu pmu;
7481
const struct hisi_uncore_ops *ops;
82+
const struct hisi_pmu_dev_info *dev_info;
7583
struct hisi_pmu_hwevents pmu_events;
7684
/* associated_cpus: All CPUs associated with the PMU */
7785
cpumask_t associated_cpus;

0 commit comments

Comments
 (0)