diff options
author | Shaokun Zhang <zhangshaokun@hisilicon.com> | 2021-03-08 14:50:30 +0800 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2021-03-25 13:03:45 +0000 |
commit | baff06c315a146a6943b4fcabb4fe4fa36167413 (patch) | |
tree | 2680c2de63fd28296342adcf089897fdc0574e6f /drivers/perf/hisilicon/hisi_uncore_pmu.c | |
parent | 4e4cb8ca48bd68c00df67c10ff867016abb7391f (diff) | |
download | linux-baff06c315a146a6943b4fcabb4fe4fa36167413.tar.bz2 |
drivers/perf: hisi: Refactor code for more uncore PMUs
On HiSilicon uncore PMU drivers, interrupt handling function and interrupt
registration function are very similar in differents PMU modules. Let's
refactor the frame.
Two new callbacks are added for the HW accessors:
* hisi_uncore_ops::get_int_status returns a bitmap of events which
have overflowed and raised an interrupt
* hisi_uncore_ops::clear_int_status clears the overflow status for a
specific event
These callback functions are used by a common IRQ handler,
hisi_uncore_pmu_isr().
One more function hisi_uncore_pmu_init_irq() is added to replace each
PMU initialization IRQ interface and simplify the code.
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: John Garry <john.garry@huawei.com>
Co-developed-by: Qi Liu <liuqi115@huawei.com>
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Link: https://lore.kernel.org/r/1615186237-22263-3-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'drivers/perf/hisilicon/hisi_uncore_pmu.c')
-rw-r--r-- | drivers/perf/hisilicon/hisi_uncore_pmu.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c index 44b7553a3e42..c9d8e2ec499a 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c @@ -128,6 +128,60 @@ static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx) clear_bit(idx, hisi_pmu->pmu_events.used_mask); } +static irqreturn_t hisi_uncore_pmu_isr(int irq, void *data) +{ + struct hisi_pmu *hisi_pmu = data; + struct perf_event *event; + unsigned long overflown; + int idx; + + overflown = hisi_pmu->ops->get_int_status(hisi_pmu); + if (!overflown) + return IRQ_NONE; + + /* + * Find the counter index which overflowed if the bit was set + * and handle it. + */ + for_each_set_bit(idx, &overflown, hisi_pmu->num_counters) { + /* Write 1 to clear the IRQ status flag */ + hisi_pmu->ops->clear_int_status(hisi_pmu, idx); + /* Get the corresponding event struct */ + event = hisi_pmu->pmu_events.hw_events[idx]; + if (!event) + continue; + + hisi_uncore_pmu_event_update(event); + hisi_uncore_pmu_set_event_period(event); + } + + return IRQ_HANDLED; +} + +int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, + struct platform_device *pdev) +{ + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(&pdev->dev, irq, hisi_uncore_pmu_isr, + IRQF_NOBALANCING | IRQF_NO_THREAD, + dev_name(&pdev->dev), hisi_pmu); + if (ret < 0) { + dev_err(&pdev->dev, + "Fail to request IRQ: %d ret: %d.\n", irq, ret); + return ret; + } + + hisi_pmu->irq = irq; + + return 0; +} +EXPORT_SYMBOL_GPL(hisi_uncore_pmu_init_irq); + int hisi_uncore_pmu_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; |