Add support for hisilicon uncore pmu drivers

This commit is contained in:
hongrongxuan 2023-10-31 21:17:36 +08:00
parent 75042fb2d5
commit 639cc4585b
57 changed files with 11828 additions and 1 deletions

View File

@ -32,7 +32,7 @@
Name: kernel
Version: 4.19.90
Release: %{hulkrelease}.0230
Release: %{hulkrelease}.0231
Summary: Linux Kernel
License: GPLv2
URL: http://www.kernel.org/
@ -832,6 +832,63 @@ fi
%changelog
* Wed Nov 1 2023 hongrongxuan <hongrongxuan@huawei.com> - 4.19.90-2311.1.0.0231
- perf/smmuv3: Add MODULE_ALIAS for module auto loading
- perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
- perf/smmuv3: Enable HiSilicon Erratum 162001800 quirk
- Revert "perf/smmuv3_pmu: Enable HiSilicon Erratum 162001800 quirk"
- drivers/perf: hisi: add NULL check for name
- drivers/perf: hisi: Remove redundant initialized of pmu->name
- drivers/perf: hisi: Extract initialization of "cpa_pmu->pmu"
- drivers/perf: hisi: Simplify the parameters of hisi_pmu_init()
- drivers/perf: hisi: Advertise the PERF_PMU_CAP_NO_EXCLUDE capability
- perf: hisi: Extract hisi_pmu_init
- perf: hisi: Add configs for PMU isolation
- perf: hisi: Fix read sccl_id and ccl_id error in TSV200
- drivers/perf: fixed kabi broken for SLLC and PA PMU
- drivers/perf: fixed the issue that the kabi value changed
- drivers/perf: hisi: Don't migrate perf to the CPU going to teardown
- drivers/perf: hisi: Add TLP filter support
- docs: perf: Fix PMU instance name of hisi-pcie-pmu
- docs: fix 'make htmldocs' warning in perf
- docs: perf: Address some html build warnings
- docs: perf: Add description for HiSilicon PCIe PMU driver
- docs: perf: Add new description on HiSilicon uncore PMU v2
- docs: perf: move to the admin-guide
- drivers/perf: hisi: Fix some event id for hisi-pcie-pmu
- drivers/perf: hisi: Add Support for CPA PMU
- driver/perf: hisi: fix kabi broken for struct hisi_pmu
- drivers/perf: hisi: Associate PMUs in SICL with CPUs online
- drivers/perf: hisi: Add driver for HiSilicon PCIe PMU
- PCI: Add pci_dev_id() helper
- perf: hisi: Fix unexpected modifications in hisi_uncore_l3c_pmu.c
- perf: hisi: Add support for HiSilicon SoC LPDDRC PMU
- perf: hisi: Add support for HiSilicon SoC L3T PMU
- perf: hisi: Fix read sccl_id and ccl_id error in some platform
- perf: hisi: Make irq shared
- drivers/perf: hisi: Fix data source control
- perf/hisi: Use irq_set_affinity()
- drivers/perf: hisi: Add support for HiSilicon PA PMU driver
- drivers/perf: hisi: Add support for HiSilicon SLLC PMU driver
- drivers/perf: hisi: Update DDRC PMU for programmable counter
- drivers/perf: hisi: Add new functions for HHA PMU
- drivers/perf: hisi: Add new functions for L3C PMU
- drivers/perf: hisi: Add PMU version for uncore PMU drivers.
- drivers/perf: hisi: Refactor code for more uncore PMUs
- drivers/perf: hisi: Remove unnecessary check of counter index
- drivers/perf: hisi: Add identifier sysfs file
- perf: hisi: use devm_platform_ioremap_resource() to simplify code
- drivers: provide devm_platform_ioremap_resource()
- For drivers that do not support context exclusion let's advertise the PERF_PMU_CAP_NO_EXCLUDE capability. This ensures that perf will prevent us from handling events where any exclusion flags are set. Let's also remove the now unnecessary check for exclusion flags.
- drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling
- docs: perf: convert to ReST
- Revert "perf: hisi: remove duplicated code"
- Revert "drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling"
- Revert "perf: hisi: Add support for HiSilicon SoC PMU driver dt probe"
- Revert "perf: hisi: Add support for HiSilicon SoC LPDDRC PMU driver"
- Revert "perf: hisi: Add support for HiSilicon SoC L3T PMU driver"
- Revert "perf: hisi: Fix compile error if defined MODULE"
* Wed Nov 1 2023 Luo Shengwei <luoshengwei@huawei.com> - 4.19.90-2311.1.0.0230
- !2609 Fix CVE-2023-5717
- !2588 [openEuler-1.0-LTS] Add Phytium Display Engine support.

View File

@ -0,0 +1,37 @@
From 6f28c899df9750b13fdc86b9b3bb80d46aa89c8d Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 14:58:04 +0800
Subject: [PATCH 01/55] Revert "perf: hisi: Fix compile error if defined
MODULE"
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
--------------------------------------------------------------
This reverts commit f00917fa81207962a5455e1084c90aff36b3a6ae.
This bugfix fixed in higher verison in L3t pmu driver, inclusion it later.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
index ca395252ccc3..8f8b211788e0 100644
--- a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
@@ -241,7 +241,7 @@ static int hisi_lpddrc_pmu_init_irq(struct hisi_pmu *lpddrc_pmu,
static const struct of_device_id lpddrc_of_match[] = {
{ .compatible = "hisilicon,lpddrc-pmu", },
{},
-};
+}
MODULE_DEVICE_TABLE(of, lpddrc_of_match);
static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev,
--
2.27.0

View File

@ -0,0 +1,480 @@
From 7cd21a232cb93ea0598386c028c88e1931946887 Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 15:03:16 +0800
Subject: [PATCH 02/55] Revert "perf: hisi: Add support for HiSilicon SoC L3T
PMU driver"
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
------------------------------------------------------------
This reverts commit 72ed85332d7704ab91afe3f14ab95b39fca17e97.
Now, revert it, then we will inclusion the newer version of L3T PMU
driver.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/hisilicon/Makefile
---
drivers/perf/hisilicon/Makefile | 7 +-
drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c | 432 -------------------
2 files changed, 1 insertion(+), 438 deletions(-)
delete mode 100644 drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 63942ae6b167..3651f18260e5 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,6 +1 @@
-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o \
- hisi_uncore_l3c_pmu.o \
- hisi_uncore_hha_pmu.o \
- hisi_uncore_ddrc_pmu.o \
- hisi_uncore_lpddrc_pmu.o \
- hisi_uncore_l3t_pmu.o
+obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_lpddrc_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
deleted file mode 100644
index bd4e600e0c32..000000000000
--- a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
+++ /dev/null
@@ -1,432 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HiSilicon SoC L3T uncore Hardware event counters support
- *
- * Copyright (C) 2021 Hisilicon Limited
- * Author: Fang Lijun <fanglijun3@huawei.com>
- * Anurup M <anurup.m@huawei.com>
- * Shaokun Zhang <zhangshaokun@hisilicon.com>
- *
- * This code is based on the uncore PMUs like arm-cci and arm-ccn.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/acpi.h>
-#include <linux/bug.h>
-#include <linux/cpuhotplug.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/smp.h>
-
-#include "hisi_uncore_pmu.h"
-
-/* L3T register definition */
-#define L3T_PERF_CTRL 0x0408
-#define L3T_INT_MASK 0x0800
-#define L3T_INT_STATUS 0x0808
-#define L3T_INT_CLEAR 0x080c
-#define L3T_EVENT_CTRL 0x1c00
-#define L3T_EVENT_TYPE0 0x1d00
-/*
- * Each counter is 48-bits and [48:63] are reserved
- * which are Read-As-Zero and Writes-Ignored.
- */
-#define L3T_CNTR0_LOWER 0x1e00
-
-/* L3T has 8-counters */
-#define L3T_NR_COUNTERS 0x8
-
-#define L3T_PERF_CTRL_EN 0x20000
-#define L3T_EVTYPE_NONE 0xff
-
-/*
- * Select the counter register offset using the counter index
- */
-static u32 hisi_l3t_pmu_get_counter_offset(u32 cntr_idx)
-{
- return (L3T_CNTR0_LOWER + (cntr_idx * 8));
-}
-
-static u64 hisi_l3t_pmu_read_counter(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc)
-{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(l3t_pmu, idx)) {
- dev_err(l3t_pmu->dev, "Unsupported event index:%d!\n", idx);
- return 0;
- }
-
- /* Read 64-bits and the upper 16 bits are RAZ */
- return readq(l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(idx));
-}
-
-static void hisi_l3t_pmu_write_counter(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc, u64 val)
-{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(l3t_pmu, idx)) {
- dev_err(l3t_pmu->dev, "Unsupported event index:%d!\n", idx);
- return;
- }
-
- /* Write 64-bits and the upper 16 bits are WI */
- writeq(val, l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(idx));
-}
-
-static void hisi_l3t_pmu_write_evtype(struct hisi_pmu *l3t_pmu, int idx,
- u32 type)
-{
- u32 reg, reg_idx, shift, val;
-
- /*
- * Select the appropriate event select register(L3T_EVENT_TYPE0/1).
- * There are 2 event select registers for the 8 hardware counters.
- * Event code is 8-bits and for the former 4 hardware counters,
- * L3T_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
- * L3T_EVENT_TYPE1 is chosen.
- */
- reg = L3T_EVENT_TYPE0 + (idx / 4) * 4;
- reg_idx = idx % 4;
- shift = 8 * reg_idx;
-
- /* Write event code to L3T_EVENT_TYPEx Register */
- val = readl(l3t_pmu->base + reg);
- val &= ~(L3T_EVTYPE_NONE << shift);
- val |= (type << shift);
- writel(val, l3t_pmu->base + reg);
-}
-
-static void hisi_l3t_pmu_start_counters(struct hisi_pmu *l3t_pmu)
-{
- u32 val;
-
- /*
- * Set perf_enable bit in L3T_PERF_CTRL register to start counting
- * for all enabled counters.
- */
- val = readl(l3t_pmu->base + L3T_PERF_CTRL);
- val |= L3T_PERF_CTRL_EN;
- writel(val, l3t_pmu->base + L3T_PERF_CTRL);
-}
-
-static void hisi_l3t_pmu_stop_counters(struct hisi_pmu *l3t_pmu)
-{
- u32 val;
-
- /*
- * Clear perf_enable bit in L3T_PERF_CTRL register to stop counting
- * for all enabled counters.
- */
- val = readl(l3t_pmu->base + L3T_PERF_CTRL);
- val &= ~(L3T_PERF_CTRL_EN);
- writel(val, l3t_pmu->base + L3T_PERF_CTRL);
-}
-
-static void hisi_l3t_pmu_enable_counter(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Enable counter index in L3T_EVENT_CTRL register */
- val = readl(l3t_pmu->base + L3T_EVENT_CTRL);
- val |= (1 << hwc->idx);
- writel(val, l3t_pmu->base + L3T_EVENT_CTRL);
-}
-
-static void hisi_l3t_pmu_disable_counter(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Clear counter index in L3T_EVENT_CTRL register */
- val = readl(l3t_pmu->base + L3T_EVENT_CTRL);
- val &= ~(1 << hwc->idx);
- writel(val, l3t_pmu->base + L3T_EVENT_CTRL);
-}
-
-static void hisi_l3t_pmu_enable_counter_int(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- val = readl(l3t_pmu->base + L3T_INT_MASK);
- /* Write 0 to enable interrupt */
- val &= ~(1 << hwc->idx);
- writel(val, l3t_pmu->base + L3T_INT_MASK);
-}
-
-static void hisi_l3t_pmu_disable_counter_int(struct hisi_pmu *l3t_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- val = readl(l3t_pmu->base + L3T_INT_MASK);
- /* Write 1 to mask interrupt */
- val |= (1 << hwc->idx);
- writel(val, l3t_pmu->base + L3T_INT_MASK);
-}
-
-static irqreturn_t hisi_l3t_pmu_isr(int irq, void *dev_id)
-{
- struct hisi_pmu *l3t_pmu = dev_id;
- struct perf_event *event;
- unsigned long overflown;
- int idx;
-
- /* Read L3T_INT_STATUS register */
- overflown = readl(l3t_pmu->base + L3T_INT_STATUS);
- 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, L3T_NR_COUNTERS) {
- /* Write 1 to clear the IRQ status flag */
- writel((1 << idx), l3t_pmu->base + L3T_INT_CLEAR);
-
- /* Get the corresponding event struct */
- event = l3t_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;
-}
-
-static int hisi_l3t_pmu_init_irq(struct hisi_pmu *l3t_pmu,
- struct platform_device *pdev)
-{
- int irq, ret;
-
- /* Read and init IRQ */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "L3T PMU get irq fail; irq:%d\n", irq);
- return irq;
- }
-
- ret = devm_request_irq(&pdev->dev, irq, hisi_l3t_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED,
- dev_name(&pdev->dev), l3t_pmu);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Fail to request IRQ:%d ret:%d\n", irq, ret);
- return ret;
- }
-
- l3t_pmu->irq = irq;
-
- return 0;
-}
-
-static const struct of_device_id l3t_of_match[] = {
- { .compatible = "hisilicon,l3t-pmu", },
- {},
-};
-MODULE_DEVICE_TABLE(of, l3t_of_match);
-
-static int hisi_l3t_pmu_init_data(struct platform_device *pdev,
- struct hisi_pmu *l3t_pmu)
-{
- struct resource *res;
-
- /*
- * Use the SCCL_ID and CCL_ID to identify the L3T PMU, while
- * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
- */
- if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
- &l3t_pmu->sccl_id)) {
- dev_err(&pdev->dev, "Can not read l3t sccl-id!\n");
- return -EINVAL;
- }
-
- if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
- &l3t_pmu->ccl_id)) {
- dev_err(&pdev->dev, "Can not read l3t ccl-id!\n");
- return -EINVAL;
- }
-
- if (device_property_read_u32(&pdev->dev, "hisilicon,index-id",
- &l3t_pmu->index_id)) {
- dev_err(&pdev->dev, "Can not read l3t index-id!\n");
- return -EINVAL;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- l3t_pmu->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(l3t_pmu->base)) {
- dev_err(&pdev->dev, "ioremap failed for l3t_pmu resource\n");
- return PTR_ERR(l3t_pmu->base);
- }
-
- return 0;
-}
-
-static struct attribute *hisi_l3t_pmu_format_attr[] = {
- HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
- NULL,
-};
-
-static const struct attribute_group hisi_l3t_pmu_format_group = {
- .name = "format",
- .attrs = hisi_l3t_pmu_format_attr,
-};
-
-static struct attribute *hisi_l3t_pmu_events_attr[] = {
- HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00),
- HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01),
- HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02),
- HISI_PMU_EVENT_ATTR(wr_hit_cpipe, 0x03),
- HISI_PMU_EVENT_ATTR(victim_num, 0x04),
- HISI_PMU_EVENT_ATTR(rd_spipe, 0x20),
- HISI_PMU_EVENT_ATTR(wr_spipe, 0x21),
- HISI_PMU_EVENT_ATTR(rd_hit_spipe, 0x22),
- HISI_PMU_EVENT_ATTR(wr_hit_spipe, 0x23),
- HISI_PMU_EVENT_ATTR(back_invalid, 0x29),
- HISI_PMU_EVENT_ATTR(retry_cpu, 0x40),
- HISI_PMU_EVENT_ATTR(retry_ring, 0x41),
- HISI_PMU_EVENT_ATTR(prefetch_drop, 0x42),
- NULL,
-};
-
-static const struct attribute_group hisi_l3t_pmu_events_group = {
- .name = "events",
- .attrs = hisi_l3t_pmu_events_attr,
-};
-
-static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
-
-static struct attribute *hisi_l3t_pmu_cpumask_attrs[] = {
- &dev_attr_cpumask.attr,
- NULL,
-};
-
-static const struct attribute_group hisi_l3t_pmu_cpumask_attr_group = {
- .attrs = hisi_l3t_pmu_cpumask_attrs,
-};
-
-static const struct attribute_group *hisi_l3t_pmu_attr_groups[] = {
- &hisi_l3t_pmu_format_group,
- &hisi_l3t_pmu_events_group,
- &hisi_l3t_pmu_cpumask_attr_group,
- NULL,
-};
-
-static const struct hisi_uncore_ops hisi_uncore_l3t_ops = {
- .write_evtype = hisi_l3t_pmu_write_evtype,
- .get_event_idx = hisi_uncore_pmu_get_event_idx,
- .start_counters = hisi_l3t_pmu_start_counters,
- .stop_counters = hisi_l3t_pmu_stop_counters,
- .enable_counter = hisi_l3t_pmu_enable_counter,
- .disable_counter = hisi_l3t_pmu_disable_counter,
- .enable_counter_int = hisi_l3t_pmu_enable_counter_int,
- .disable_counter_int = hisi_l3t_pmu_disable_counter_int,
- .write_counter = hisi_l3t_pmu_write_counter,
- .read_counter = hisi_l3t_pmu_read_counter,
-};
-
-static int hisi_l3t_pmu_dev_probe(struct platform_device *pdev,
- struct hisi_pmu *l3t_pmu)
-{
- int ret;
-
- ret = hisi_l3t_pmu_init_data(pdev, l3t_pmu);
- if (ret)
- return ret;
-
- ret = hisi_l3t_pmu_init_irq(l3t_pmu, pdev);
- if (ret)
- return ret;
-
- l3t_pmu->num_counters = L3T_NR_COUNTERS;
- l3t_pmu->counter_bits = 48;
- l3t_pmu->ops = &hisi_uncore_l3t_ops;
- l3t_pmu->dev = &pdev->dev;
- l3t_pmu->on_cpu = -1;
- l3t_pmu->check_event = 0x59;
-
- return 0;
-}
-
-static int hisi_l3t_pmu_probe(struct platform_device *pdev)
-{
- struct hisi_pmu *l3t_pmu;
- char *name;
- int ret;
-
- l3t_pmu = devm_kzalloc(&pdev->dev, sizeof(*l3t_pmu), GFP_KERNEL);
- if (!l3t_pmu)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, l3t_pmu);
-
- ret = hisi_l3t_pmu_dev_probe(pdev, l3t_pmu);
- if (ret)
- return ret;
-
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3t%u",
- l3t_pmu->sccl_id, l3t_pmu->index_id);
- HISI_INIT_PMU(&l3t_pmu->pmu, name, hisi_l3t_pmu_attr_groups);
-
- ret = perf_pmu_register(&l3t_pmu->pmu, name, -1);
- if (ret) {
- dev_err(l3t_pmu->dev, "L3T PMU register failed!\n");
- return ret;
- }
-
- /* Pick one core to use for cpumask attributes */
- cpumask_set_cpu(smp_processor_id(), &l3t_pmu->associated_cpus);
-
- l3t_pmu->on_cpu = cpumask_first(&l3t_pmu->associated_cpus);
- if (l3t_pmu->on_cpu >= nr_cpu_ids)
- return -EINVAL;
-
- return 0;
-}
-
-static int hisi_l3t_pmu_remove(struct platform_device *pdev)
-{
- struct hisi_pmu *l3t_pmu = platform_get_drvdata(pdev);
-
- perf_pmu_unregister(&l3t_pmu->pmu);
-
- return 0;
-}
-
-static struct platform_driver hisi_l3t_pmu_driver = {
- .driver = {
- .name = "hisi_l3t_pmu",
- .of_match_table = of_match_ptr(l3t_of_match),
- },
- .probe = hisi_l3t_pmu_probe,
- .remove = hisi_l3t_pmu_remove,
-};
-
-static int __init hisi_l3t_pmu_module_init(void)
-{
- return platform_driver_register(&hisi_l3t_pmu_driver);
-}
-module_init(hisi_l3t_pmu_module_init);
-
-static void __exit hisi_l3t_pmu_module_exit(void)
-{
- platform_driver_unregister(&hisi_l3t_pmu_driver);
-}
-module_exit(hisi_l3t_pmu_module_exit);
-
-MODULE_DESCRIPTION("HiSilicon SoC L3T uncore PMU driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("HUAWEI TECHNOLOGIES CO., LTD.");
-MODULE_AUTHOR("Fang Lijun <fanglijun3@huawei.com>");
--
2.27.0

View File

@ -0,0 +1,469 @@
From a42c8f603e8d0aa7d67023014604d919227581dd Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 15:04:16 +0800
Subject: [PATCH 03/55] Revert "perf: hisi: Add support for HiSilicon SoC
LPDDRC PMU driver"
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
-------------------------------------------------------------
This reverts commit be4e2dae37269ece33d54f906323b00208a569b0.
Now, revert it, then we will inclusion the newer version of LPDRRC PMU
driver.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/Makefile | 2 +-
.../perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 429 ------------------
2 files changed, 1 insertion(+), 430 deletions(-)
delete mode 100644 drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 3651f18260e5..2621d51ae87a 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_lpddrc_pmu.o
+obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
deleted file mode 100644
index 8f8b211788e0..000000000000
--- a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
+++ /dev/null
@@ -1,429 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HiSilicon SoC LPDDRC uncore Hardware event counters support
- *
- * Copyright (C) 2021 Hisilicon Limited
- * Author: Fang Lijun <fanglijun3@huawei.com>
- * Shaokun Zhang <zhangshaokun@hisilicon.com>
- * Anurup M <anurup.m@huawei.com>
- *
- * This code is based on the uncore PMUs like arm-cci and arm-ccn.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/acpi.h>
-#include <linux/bug.h>
-#include <linux/cpuhotplug.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/smp.h>
-
-#include "hisi_uncore_pmu.h"
-
-/* LPDDRC register definition */
-#define LPDDRC_PERF_CTRL 0x4930
-#define LPDDRC_FLUX_WR 0x4948
-#define LPDDRC_FLUX_RD 0x494c
-#define LPDDRC_FLUX_WCMD 0x4950
-#define LPDDRC_FLUX_RCMD 0x4954
-#define LPDDRC_PRE_CMD 0x4984
-#define LPDDRC_ACT_CMD 0x4988
-#define LPDDRC_RNK_CHG 0x4990
-#define LPDDRC_RW_CHG 0x4994
-#define LPDDRC_EVENT_CTRL 0x4d60
-#define LPDDRC_INT_MASK 0x6c8
-#define LPDDRC_INT_STATUS 0x6cc
-#define LPDDRC_INT_CLEAR 0x6d0
-
-/* LPDDRC has 8-counters */
-#define LPDDRC_NR_COUNTERS 0x8
-#define LPDDRC_PERF_CTRL_EN 0x1
-
-/*
- * For LPDDRC PMU, there are eight-events and every event has been mapped
- * to fixed-purpose counters which register offset is not consistent.
- * Therefore there is no write event type and we assume that event
- * code (0 to 7) is equal to counter index in PMU driver.
- */
-#define GET_LPDDRC_EVENTID(hwc) (hwc->config_base & 0x7)
-
-static const u32 lpddrc_reg_off[] = {
- LPDDRC_FLUX_WR, LPDDRC_FLUX_RD, LPDDRC_FLUX_WCMD, LPDDRC_FLUX_RCMD,
- LPDDRC_PRE_CMD, LPDDRC_ACT_CMD, LPDDRC_RNK_CHG, LPDDRC_RW_CHG
-};
-
-/*
- * Select the counter register offset using the counter index.
- * In LPDDRC there are no programmable counter, the count
- * is readed form the statistics counter register itself.
- */
-static u32 hisi_lpddrc_pmu_get_counter_offset(int cntr_idx)
-{
- return lpddrc_reg_off[cntr_idx];
-}
-
-static u64 hisi_lpddrc_pmu_read_counter(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc)
-{
- /* Use event code as counter index */
- u32 idx = GET_LPDDRC_EVENTID(hwc);
-
- if (!hisi_uncore_pmu_counter_valid(lpddrc_pmu, idx)) {
- dev_err(lpddrc_pmu->dev, "Unsupported event index:%d!\n", idx);
- return 0;
- }
-
- return readl(lpddrc_pmu->base + hisi_lpddrc_pmu_get_counter_offset(idx));
-}
-
-/*
- * For LPDDRC PMU, event counter should be reset when start counters,
- * reset the prev_count by software, because the counter register was RO.
- */
-static void hisi_lpddrc_pmu_write_counter(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc, u64 val)
-{
- local64_set(&hwc->prev_count, 0);
-}
-
-/*
- * For LPDDRC PMU, event has been mapped to fixed-purpose counter by hardware,
- * so there is no need to write event type.
- */
-static void hisi_lpddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
- u32 type)
-{
-}
-
-static void hisi_lpddrc_pmu_start_counters(struct hisi_pmu *lpddrc_pmu)
-{
- u32 val;
-
- /* Set perf_enable in LPDDRC_PERF_CTRL to start event counting */
- val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL);
- val |= LPDDRC_PERF_CTRL_EN;
- writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL);
-}
-
-static void hisi_lpddrc_pmu_stop_counters(struct hisi_pmu *lpddrc_pmu)
-{
- u32 val;
-
- /* Clear perf_enable in LPDDRC_PERF_CTRL to stop event counting */
- val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL);
- val &= ~LPDDRC_PERF_CTRL_EN;
- writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL);
-}
-
-static void hisi_lpddrc_pmu_enable_counter(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Set counter index(event code) in LPDDRC_EVENT_CTRL register */
- val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
- val |= (1 << GET_LPDDRC_EVENTID(hwc));
- writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
-}
-
-static void hisi_lpddrc_pmu_disable_counter(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Clear counter index(event code) in LPDDRC_EVENT_CTRL register */
- val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
- val &= ~(1 << GET_LPDDRC_EVENTID(hwc));
- writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
-}
-
-static int hisi_lpddrc_pmu_get_event_idx(struct perf_event *event)
-{
- struct hisi_pmu *lpddrc_pmu = to_hisi_pmu(event->pmu);
- unsigned long *used_mask = lpddrc_pmu->pmu_events.used_mask;
- struct hw_perf_event *hwc = &event->hw;
- /* For LPDDRC PMU, we use event code as counter index */
- int idx = GET_LPDDRC_EVENTID(hwc);
-
- if (test_bit(idx, used_mask))
- return -EAGAIN;
-
- set_bit(idx, used_mask);
-
- return idx;
-}
-
-static void hisi_lpddrc_pmu_enable_counter_int(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Write 0 to enable interrupt */
- val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK);
- val &= ~(1 << GET_LPDDRC_EVENTID(hwc));
- writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK);
-}
-
-static void hisi_lpddrc_pmu_disable_counter_int(struct hisi_pmu *lpddrc_pmu,
- struct hw_perf_event *hwc)
-{
- u32 val;
-
- /* Write 1 to mask interrupt */
- val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK);
- val |= (1 << GET_LPDDRC_EVENTID(hwc));
- writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK);
-}
-
-static irqreturn_t hisi_lpddrc_pmu_isr(int irq, void *dev_id)
-{
- struct hisi_pmu *lpddrc_pmu = dev_id;
- struct perf_event *event;
- unsigned long overflown;
- int idx;
-
- /* Read the LPDDRC_INT_STATUS register */
- overflown = readl(lpddrc_pmu->base + LPDDRC_INT_STATUS);
- 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, LPDDRC_NR_COUNTERS) {
- /* Write 1 to clear the IRQ status flag */
- writel((1 << idx), lpddrc_pmu->base + LPDDRC_INT_CLEAR);
-
- /* Get the corresponding event struct */
- event = lpddrc_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;
-}
-
-static int hisi_lpddrc_pmu_init_irq(struct hisi_pmu *lpddrc_pmu,
- struct platform_device *pdev)
-{
- int irq, ret;
-
- /* Read and init IRQ */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "LPDDRC PMU get irq fail; irq:%d\n", irq);
- return irq;
- }
-
- ret = devm_request_irq(&pdev->dev, irq, hisi_lpddrc_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED,
- dev_name(&pdev->dev), lpddrc_pmu);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Fail to request IRQ:%d ret:%d\n", irq, ret);
- return ret;
- }
-
- lpddrc_pmu->irq = irq;
-
- return 0;
-}
-
-static const struct of_device_id lpddrc_of_match[] = {
- { .compatible = "hisilicon,lpddrc-pmu", },
- {},
-}
-MODULE_DEVICE_TABLE(of, lpddrc_of_match);
-
-static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev,
- struct hisi_pmu *lpddrc_pmu)
-{
- struct resource *res;
-
- /*
- * Use the SCCL_ID and LPDDRC channel ID to identify the
- * LPDDRC PMU, while SCCL_ID is in MPIDR[aff2].
- */
- if (device_property_read_u32(&pdev->dev, "hisilicon,ch-id",
- &lpddrc_pmu->index_id)) {
- dev_err(&pdev->dev, "Can not read lpddrc channel-id!\n");
- return -EINVAL;
- }
-
- if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
- &lpddrc_pmu->sccl_id)) {
- dev_err(&pdev->dev, "Can not read lpddrc sccl-id!\n");
- return -EINVAL;
- }
- /* LPDDRC PMUs only share the same SCCL */
- lpddrc_pmu->ccl_id = -1;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- lpddrc_pmu->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(lpddrc_pmu->base)) {
- dev_err(&pdev->dev, "ioremap failed for lpddrc_pmu resource\n");
- return PTR_ERR(lpddrc_pmu->base);
- }
-
- return 0;
-}
-
-static struct attribute *hisi_lpddrc_pmu_format_attr[] = {
- HISI_PMU_FORMAT_ATTR(event, "config:0-4"),
- NULL,
-};
-
-static const struct attribute_group hisi_lpddrc_pmu_format_group = {
- .name = "format",
- .attrs = hisi_lpddrc_pmu_format_attr,
-};
-
-static struct attribute *hisi_lpddrc_pmu_events_attr[] = {
- HISI_PMU_EVENT_ATTR(flux_wr, 0x00),
- HISI_PMU_EVENT_ATTR(flux_rd, 0x01),
- HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02),
- HISI_PMU_EVENT_ATTR(flux_rcmd, 0x03),
- HISI_PMU_EVENT_ATTR(pre_cmd, 0x04),
- HISI_PMU_EVENT_ATTR(act_cmd, 0x05),
- HISI_PMU_EVENT_ATTR(rnk_chg, 0x06),
- HISI_PMU_EVENT_ATTR(rw_chg, 0x07),
- NULL,
-};
-
-static const struct attribute_group hisi_lpddrc_pmu_events_group = {
- .name = "events",
- .attrs = hisi_lpddrc_pmu_events_attr,
-};
-
-static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
-
-static struct attribute *hisi_lpddrc_pmu_cpumask_attrs[] = {
- &dev_attr_cpumask.attr,
- NULL,
-};
-
-static const struct attribute_group hisi_lpddrc_pmu_cpumask_attr_group = {
- .attrs = hisi_lpddrc_pmu_cpumask_attrs,
-};
-
-static const struct attribute_group *hisi_lpddrc_pmu_attr_groups[] = {
- &hisi_lpddrc_pmu_format_group,
- &hisi_lpddrc_pmu_events_group,
- &hisi_lpddrc_pmu_cpumask_attr_group,
- NULL,
-};
-
-static const struct hisi_uncore_ops hisi_uncore_lpddrc_ops = {
- .write_evtype = hisi_lpddrc_pmu_write_evtype,
- .get_event_idx = hisi_lpddrc_pmu_get_event_idx,
- .start_counters = hisi_lpddrc_pmu_start_counters,
- .stop_counters = hisi_lpddrc_pmu_stop_counters,
- .enable_counter = hisi_lpddrc_pmu_enable_counter,
- .disable_counter = hisi_lpddrc_pmu_disable_counter,
- .enable_counter_int = hisi_lpddrc_pmu_enable_counter_int,
- .disable_counter_int = hisi_lpddrc_pmu_disable_counter_int,
- .write_counter = hisi_lpddrc_pmu_write_counter,
- .read_counter = hisi_lpddrc_pmu_read_counter,
-};
-
-static int hisi_lpddrc_pmu_dev_probe(struct platform_device *pdev,
- struct hisi_pmu *lpddrc_pmu)
-{
- int ret;
-
- ret = hisi_lpddrc_pmu_init_data(pdev, lpddrc_pmu);
- if (ret)
- return ret;
-
- ret = hisi_lpddrc_pmu_init_irq(lpddrc_pmu, pdev);
- if (ret)
- return ret;
-
- lpddrc_pmu->num_counters = LPDDRC_NR_COUNTERS;
- lpddrc_pmu->counter_bits = 32;
- lpddrc_pmu->ops = &hisi_uncore_lpddrc_ops;
- lpddrc_pmu->dev = &pdev->dev;
- lpddrc_pmu->on_cpu = -1;
- lpddrc_pmu->check_event = 7;
-
- return 0;
-}
-
-static int hisi_lpddrc_pmu_probe(struct platform_device *pdev)
-{
- struct hisi_pmu *lpddrc_pmu;
- char *name;
- int ret;
-
- lpddrc_pmu = devm_kzalloc(&pdev->dev, sizeof(*lpddrc_pmu), GFP_KERNEL);
- if (!lpddrc_pmu)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, lpddrc_pmu);
-
- ret = hisi_lpddrc_pmu_dev_probe(pdev, lpddrc_pmu);
- if (ret)
- return ret;
-
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_lpddrc%u",
- lpddrc_pmu->sccl_id, lpddrc_pmu->index_id);
- HISI_INIT_PMU(&lpddrc_pmu->pmu, name, hisi_lpddrc_pmu_attr_groups);
- ret = perf_pmu_register(&lpddrc_pmu->pmu, name, -1);
- if (ret) {
- dev_err(lpddrc_pmu->dev, "LPDDRC PMU register failed!\n");
- return ret;
- }
-
- /* Pick one core to use for cpumask attributes */
- cpumask_set_cpu(smp_processor_id(), &lpddrc_pmu->associated_cpus);
-
- lpddrc_pmu->on_cpu = cpumask_first(&lpddrc_pmu->associated_cpus);
- if (lpddrc_pmu->on_cpu >= nr_cpu_ids)
- return -EINVAL;
-
- return 0;
-}
-
-static int hisi_lpddrc_pmu_remove(struct platform_device *pdev)
-{
- struct hisi_pmu *lpddrc_pmu = platform_get_drvdata(pdev);
-
- perf_pmu_unregister(&lpddrc_pmu->pmu);
-
- return 0;
-}
-
-static struct platform_driver hisi_lpddrc_pmu_driver = {
- .driver = {
- .name = "hisi_lpddrc_pmu",
- .of_match_table = lpddrc_of_match,
- },
- .probe = hisi_lpddrc_pmu_probe,
- .remove = hisi_lpddrc_pmu_remove,
-};
-
-static int __init hisi_lpddrc_pmu_module_init(void)
-{
- return platform_driver_register(&hisi_lpddrc_pmu_driver);
-}
-module_init(hisi_lpddrc_pmu_module_init);
-
-static void __exit hisi_lpddrc_pmu_module_exit(void)
-{
- platform_driver_unregister(&hisi_lpddrc_pmu_driver);
-}
-module_exit(hisi_lpddrc_pmu_module_exit);
-
-MODULE_DESCRIPTION("HiSilicon SoC LPDDRC uncore PMU driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Fang Lijun <fanglijun3@huawei.com>");
-MODULE_AUTHOR("HUAWEI TECHNOLOGIES CO., LTD.");
--
2.27.0

View File

@ -0,0 +1,142 @@
From 368cbff964ef136c493a3f06b88ff7e35454073d Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 15:21:52 +0800
Subject: [PATCH 04/55] Revert "perf: hisi: Add support for HiSilicon SoC PMU
driver dt probe"
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
-----------------------------------------------------------------
This reverts commit 31067ca7ca856eee32857bdc618e89d3b9a3261a.
In newer version of PMU drivers that we will inclusion them later,
the acpi_evaluate_integer was removed, so this problem is gone.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/Kconfig
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 -
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 23 ++++---------------
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 20 +++-------------
3 files changed, 7 insertions(+), 37 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 8d1c48bc9812..f2a144ba3724 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/smp.h>
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 52286739c8b9..540f664463a8 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/smp.h>
@@ -236,34 +235,20 @@ static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match);
-#ifdef CONFIG_ACPI
-static int hisi_hha_pmu_init_index(struct platform_device *pdev,
+static int hisi_hha_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *hha_pmu)
{
- acpi_status status;
unsigned long long id;
+ struct resource *res;
+ acpi_status status;
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
- "_UID", NULL, &id);
+ "_UID", NULL, &id);
if (ACPI_FAILURE(status))
return -EINVAL;
hha_pmu->index_id = id;
- return 0;
-}
-#endif
-
-static int hisi_hha_pmu_init_data(struct platform_device *pdev,
- struct hisi_pmu *hha_pmu)
-{
- struct resource *res;
-
-#ifdef CONFIG_ACPI
- if (hisi_hha_pmu_init_index(pdev, hha_pmu))
- dev_info(&pdev->dev, "Can not init index id by acpi!\n");
-#endif
-
/*
* Use SCCL_ID and UID to identify the HHA PMU, while
* SCCL_ID is in MPIDR[aff2].
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 0e766cea4a11..117edd114445 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/smp.h>
@@ -235,33 +234,20 @@ static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, hisi_l3c_pmu_acpi_match);
-#ifdef CONFIG_ACPI
-static int hisi_l3c_pmu_init_index(struct platform_device *pdev,
+static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *l3c_pmu)
{
unsigned long long id;
+ struct resource *res;
acpi_status status;
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
- "_UID", NULL, &id);
+ "_UID", NULL, &id);
if (ACPI_FAILURE(status))
return -EINVAL;
l3c_pmu->index_id = id;
- return 0;
-}
-#endif
-
-static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
- struct hisi_pmu *l3c_pmu)
-{
- struct resource *res;
-
-#ifdef CONFIG_ACPI
- if (hisi_l3c_pmu_init_index(pdev, l3c_pmu))
- dev_info(&pdev->dev, "Can not init index id by acpi!");
-#endif
/*
* Use the SCCL_ID and CCL_ID to identify the L3C PMU, while
* SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
--
2.27.0

View File

@ -0,0 +1,36 @@
From 05df62b6b7f9e92e9f25b8a0bcd5c99c4ae02165 Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 15:26:10 +0800
Subject: [PATCH 05/55] Revert "drivers/perf: Fix kernel panic when rmmod PMU
modules during perf sampling"
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
--------------------------------------------------------------
This reverts commit 525a3927062f89be41f1b23ae33ad0638c13bf8e.
revert it, and inclusion the upstream version later.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 129896662cf2..8445ee581e46 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -105,7 +105,6 @@ static inline void HISI_INIT_PMU(struct pmu *pmu, const char *name,
const struct attribute_group **attr_groups)
{
pmu->name = name;
- pmu->module = THIS_MODULE;
pmu->task_ctx_nr = perf_invalid_context;
pmu->event_init = hisi_uncore_pmu_event_init;
pmu->pmu_enable = hisi_uncore_pmu_enable;
--
2.27.0

View File

@ -0,0 +1,129 @@
From 41ea05f9ac69e7cbae775862e5c3e0dad2e1e4ca Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 15:26:31 +0800
Subject: [PATCH 06/55] Revert "perf: hisi: remove duplicated code"
driver inclusion
category: cleanup
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
----------------------------------------------------------
This reverts commit de1ea4e7f5209c7f84965c38bf37287c11db02dc.
revert it, and inclusion the newer version of commit c38992d67c15(perf: hisi: Extract hisi_pmu_init) later.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 15 ++++++++++++++-
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 15 ++++++++++++++-
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 14 +++++++++++++-
drivers/perf/hisilicon/hisi_uncore_pmu.h | 17 -----------------
4 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index f2a144ba3724..b3488ae1f2b8 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -384,7 +384,20 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_ddrc%u",
ddrc_pmu->sccl_id, ddrc_pmu->index_id);
- HISI_INIT_PMU(&ddrc_pmu->pmu, name, hisi_ddrc_pmu_attr_groups);
+ ddrc_pmu->pmu = (struct pmu) {
+ .name = name,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = hisi_ddrc_pmu_attr_groups,
+ };
+
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
if (ret) {
dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n");
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 540f664463a8..f0215d50d84d 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -395,7 +395,20 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
hha_pmu->sccl_id, hha_pmu->index_id);
- HISI_INIT_PMU(&hha_pmu->pmu, name, hisi_hha_pmu_attr_groups);
+ hha_pmu->pmu = (struct pmu) {
+ .name = name,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = hisi_hha_pmu_attr_groups,
+ };
+
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
if (ret) {
dev_err(hha_pmu->dev, "HHA PMU register failed!\n");
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 117edd114445..11563e29d983 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -385,7 +385,19 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
l3c_pmu->sccl_id, l3c_pmu->index_id);
- HISI_INIT_PMU(&l3c_pmu->pmu, name, hisi_l3c_pmu_attr_groups);
+ l3c_pmu->pmu = (struct pmu) {
+ .name = name,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = hisi_l3c_pmu_attr_groups,
+ };
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 8445ee581e46..8f2f2fc5dde4 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -100,21 +100,4 @@ ssize_t hisi_cpumask_sysfs_show(struct device *dev,
struct device_attribute *attr, char *buf);
int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node);
int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
-
-static inline void HISI_INIT_PMU(struct pmu *pmu, const char *name,
- const struct attribute_group **attr_groups)
-{
- pmu->name = name;
- pmu->task_ctx_nr = perf_invalid_context;
- pmu->event_init = hisi_uncore_pmu_event_init;
- pmu->pmu_enable = hisi_uncore_pmu_enable;
- pmu->pmu_disable = hisi_uncore_pmu_disable;
- pmu->add = hisi_uncore_pmu_add;
- pmu->del = hisi_uncore_pmu_del;
- pmu->start = hisi_uncore_pmu_start;
- pmu->stop = hisi_uncore_pmu_stop;
- pmu->read = hisi_uncore_pmu_read;
- pmu->attr_groups = attr_groups;
-}
-
#endif /* __HISI_UNCORE_PMU_H__ */
--
2.27.0

View File

@ -0,0 +1,315 @@
From 926642e8644c860c77141b8251767e1485c6427c Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Date: Thu, 18 Apr 2019 17:35:40 -0300
Subject: [PATCH 07/55] docs: perf: convert to ReST
mainline inclusion
from mainline-v5.3-rc1
commit 6baec31591cee0f2f6d446abb81c828499a6ed23
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6baec31591cee0f2f6d446abb81c828499a6ed23
---------------------------------------------------------------------
Rename the perf documentation files to ReST, add an
index for them and adjust in order to produce a nice html
output via the Sphinx build system.
At its new index.rst, let's add a :orphan: while this is not linked to
the main index.rst file, in order to avoid build warnings.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
.../perf/{arm-ccn.txt => arm-ccn.rst} | 18 +++++----
.../perf/{arm_dsu_pmu.txt => arm_dsu_pmu.rst} | 5 ++-
.../perf/{hisi-pmu.txt => hisi-pmu.rst} | 37 +++++++++++--------
Documentation/perf/index.rst | 16 ++++++++
.../perf/{qcom_l2_pmu.txt => qcom_l2_pmu.rst} | 3 +-
.../perf/{qcom_l3_pmu.txt => qcom_l3_pmu.rst} | 3 +-
.../perf/{xgene-pmu.txt => xgene-pmu.rst} | 3 +-
MAINTAINERS | 4 +-
drivers/perf/qcom_l3_pmu.c | 2 +-
9 files changed, 60 insertions(+), 31 deletions(-)
rename Documentation/perf/{arm-ccn.txt => arm-ccn.rst} (86%)
rename Documentation/perf/{arm_dsu_pmu.txt => arm_dsu_pmu.rst} (92%)
rename Documentation/perf/{hisi-pmu.txt => hisi-pmu.rst} (73%)
create mode 100644 Documentation/perf/index.rst
rename Documentation/perf/{qcom_l2_pmu.txt => qcom_l2_pmu.rst} (94%)
rename Documentation/perf/{qcom_l3_pmu.txt => qcom_l3_pmu.rst} (93%)
rename Documentation/perf/{xgene-pmu.txt => xgene-pmu.rst} (96%)
diff --git a/Documentation/perf/arm-ccn.txt b/Documentation/perf/arm-ccn.rst
similarity index 86%
rename from Documentation/perf/arm-ccn.txt
rename to Documentation/perf/arm-ccn.rst
index 15cdb7bc57c3..832b0c64023a 100644
--- a/Documentation/perf/arm-ccn.txt
+++ b/Documentation/perf/arm-ccn.rst
@@ -1,3 +1,4 @@
+==========================
ARM Cache Coherent Network
==========================
@@ -29,6 +30,7 @@ Crosspoint watchpoint-based events (special "event" value 0xfe)
require "xp" and "vc" as as above plus "port" (device port index),
"dir" (transmit/receive direction), comparator values ("cmp_l"
and "cmp_h") and "mask", being index of the comparator mask.
+
Masks are defined separately from the event description
(due to limited number of the config values) in the "cmp_mask"
directory, with first 8 configurable by user and additional
@@ -44,16 +46,16 @@ request the events on this processor (if not, the perf_event->cpu value
will be overwritten anyway). In case of this processor being offlined,
the events are migrated to another one and the attribute is updated.
-Example of perf tool use:
+Example of perf tool use::
-/ # perf list | grep ccn
- ccn/cycles/ [Kernel PMU event]
-<...>
- ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event]
-<...>
+ / # perf list | grep ccn
+ ccn/cycles/ [Kernel PMU event]
+ <...>
+ ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event]
+ <...>
-/ # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \
- sleep 1
+ / # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \
+ sleep 1
The driver does not support sampling, therefore "perf record" will
not work. Per-task (without "-a") perf sessions are not supported.
diff --git a/Documentation/perf/arm_dsu_pmu.txt b/Documentation/perf/arm_dsu_pmu.rst
similarity index 92%
rename from Documentation/perf/arm_dsu_pmu.txt
rename to Documentation/perf/arm_dsu_pmu.rst
index d611e15f5add..7fd34db75d13 100644
--- a/Documentation/perf/arm_dsu_pmu.txt
+++ b/Documentation/perf/arm_dsu_pmu.rst
@@ -1,3 +1,4 @@
+==================================
ARM DynamIQ Shared Unit (DSU) PMU
==================================
@@ -13,7 +14,7 @@ PMU doesn't support process specific events and cannot be used in sampling mode.
The DSU provides a bitmap for a subset of implemented events via hardware
registers. There is no way for the driver to determine if the other events
are available or not. Hence the driver exposes only those events advertised
-by the DSU, in "events" directory under :
+by the DSU, in "events" directory under::
/sys/bus/event_sources/devices/arm_dsu_<N>/
@@ -23,6 +24,6 @@ and use the raw event code for the unlisted events.
The driver also exposes the CPUs connected to the DSU instance in "associated_cpus".
-e.g usage :
+e.g usage::
perf stat -a -e arm_dsu_0/cycles/
diff --git a/Documentation/perf/hisi-pmu.txt b/Documentation/perf/hisi-pmu.rst
similarity index 73%
rename from Documentation/perf/hisi-pmu.txt
rename to Documentation/perf/hisi-pmu.rst
index 267a028b2741..404a5c3d9d00 100644
--- a/Documentation/perf/hisi-pmu.txt
+++ b/Documentation/perf/hisi-pmu.rst
@@ -1,5 +1,7 @@
+======================================================
HiSilicon SoC uncore Performance Monitoring Unit (PMU)
======================================================
+
The HiSilicon SoC chip includes various independent system device PMUs
such as L3 cache (L3C), Hydra Home Agent (HHA) and DDRC. These PMUs are
independent and have hardware logic to gather statistics and performance
@@ -11,11 +13,13 @@ called Super CPU cluster (SCCL) and is made up of 6 CCLs. Each SCCL has
two HHAs (0 - 1) and four DDRCs (0 - 3), respectively.
HiSilicon SoC uncore PMU driver
----------------------------------------
+-------------------------------
+
Each device PMU has separate registers for event counting, control and
interrupt, and the PMU driver shall register perf PMU drivers like L3C,
HHA and DDRC etc. The available events and configuration options shall
-be described in the sysfs, see :
+be described in the sysfs, see:
+
/sys/devices/hisi_sccl{X}_<l3c{Y}/hha{Y}/ddrc{Y}>/, or
/sys/bus/event_source/devices/hisi_sccl{X}_<l3c{Y}/hha{Y}/ddrc{Y}>.
The "perf list" command shall list the available events from sysfs.
@@ -24,27 +28,30 @@ Each L3C, HHA and DDRC is registered as a separate PMU with perf. The PMU
name will appear in event listing as hisi_sccl<sccl-id>_module<index-id>.
where "sccl-id" is the identifier of the SCCL and "index-id" is the index of
module.
+
e.g. hisi_sccl3_l3c0/rd_hit_cpipe is READ_HIT_CPIPE event of L3C index #0 in
SCCL ID #3.
+
e.g. hisi_sccl1_hha0/rx_operations is RX_OPERATIONS event of HHA index #0 in
SCCL ID #1.
The driver also provides a "cpumask" sysfs attribute, which shows the CPU core
ID used to count the uncore PMU event.
-Example usage of perf:
-$# perf list
-hisi_sccl3_l3c0/rd_hit_cpipe/ [kernel PMU event]
-------------------------------------------
-hisi_sccl3_l3c0/wr_hit_cpipe/ [kernel PMU event]
-------------------------------------------
-hisi_sccl1_l3c0/rd_hit_cpipe/ [kernel PMU event]
-------------------------------------------
-hisi_sccl1_l3c0/wr_hit_cpipe/ [kernel PMU event]
-------------------------------------------
-
-$# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5
-$# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5
+Example usage of perf::
+
+ $# perf list
+ hisi_sccl3_l3c0/rd_hit_cpipe/ [kernel PMU event]
+ ------------------------------------------
+ hisi_sccl3_l3c0/wr_hit_cpipe/ [kernel PMU event]
+ ------------------------------------------
+ hisi_sccl1_l3c0/rd_hit_cpipe/ [kernel PMU event]
+ ------------------------------------------
+ hisi_sccl1_l3c0/wr_hit_cpipe/ [kernel PMU event]
+ ------------------------------------------
+
+ $# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5
+ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5
The current driver does not support sampling. So "perf record" is unsupported.
Also attach to a task is unsupported as the events are all uncore.
diff --git a/Documentation/perf/index.rst b/Documentation/perf/index.rst
new file mode 100644
index 000000000000..4bf848e27f26
--- /dev/null
+++ b/Documentation/perf/index.rst
@@ -0,0 +1,16 @@
+:orphan:
+
+===========================
+Performance monitor support
+===========================
+
+.. toctree::
+ :maxdepth: 1
+
+ hisi-pmu
+ qcom_l2_pmu
+ qcom_l3_pmu
+ arm-ccn
+ xgene-pmu
+ arm_dsu_pmu
+ thunderx2-pmu
diff --git a/Documentation/perf/qcom_l2_pmu.txt b/Documentation/perf/qcom_l2_pmu.rst
similarity index 94%
rename from Documentation/perf/qcom_l2_pmu.txt
rename to Documentation/perf/qcom_l2_pmu.rst
index b25b97659ab9..c130178a4a55 100644
--- a/Documentation/perf/qcom_l2_pmu.txt
+++ b/Documentation/perf/qcom_l2_pmu.rst
@@ -1,3 +1,4 @@
+=====================================================================
Qualcomm Technologies Level-2 Cache Performance Monitoring Unit (PMU)
=====================================================================
@@ -28,7 +29,7 @@ The driver provides a "cpumask" sysfs attribute which contains a mask
consisting of one CPU per cluster which will be used to handle all the PMU
events on that cluster.
-Examples for use with perf:
+Examples for use with perf::
perf stat -e l2cache_0/config=0x001/,l2cache_0/config=0x042/ -a sleep 1
diff --git a/Documentation/perf/qcom_l3_pmu.txt b/Documentation/perf/qcom_l3_pmu.rst
similarity index 93%
rename from Documentation/perf/qcom_l3_pmu.txt
rename to Documentation/perf/qcom_l3_pmu.rst
index 96b3a9444a0d..a3d014a46bfd 100644
--- a/Documentation/perf/qcom_l3_pmu.txt
+++ b/Documentation/perf/qcom_l3_pmu.rst
@@ -1,3 +1,4 @@
+===========================================================================
Qualcomm Datacenter Technologies L3 Cache Performance Monitoring Unit (PMU)
===========================================================================
@@ -17,7 +18,7 @@ The hardware implements 32bit event counters and has a flat 8bit event space
exposed via the "event" format attribute. In addition to the 32bit physical
counters the driver supports virtual 64bit hardware counters by using hardware
counter chaining. This feature is exposed via the "lc" (long counter) format
-flag. E.g.:
+flag. E.g.::
perf stat -e l3cache_0_0/read-miss,lc/
diff --git a/Documentation/perf/xgene-pmu.txt b/Documentation/perf/xgene-pmu.rst
similarity index 96%
rename from Documentation/perf/xgene-pmu.txt
rename to Documentation/perf/xgene-pmu.rst
index d7cff4454e5b..644f8ed89152 100644
--- a/Documentation/perf/xgene-pmu.txt
+++ b/Documentation/perf/xgene-pmu.rst
@@ -1,3 +1,4 @@
+================================================
APM X-Gene SoC Performance Monitoring Unit (PMU)
================================================
@@ -33,7 +34,7 @@ each PMU, please refer to APM X-Gene User Manual.
Each perf driver also provides a "cpumask" sysfs attribute, which contains a
single CPU ID of the processor which will be used to handle all the PMU events.
-Example for perf tool use:
+Example for perf tool use::
/ # perf list | grep -e l3c -e iob -e mcb -e mc
l3c0/ackq-full/ [Kernel PMU event]
diff --git a/MAINTAINERS b/MAINTAINERS
index 5d0b782c973c..0b2a68401b0e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1040,7 +1040,7 @@ APPLIED MICRO (APM) X-GENE SOC PMU
M: Tai Nguyen <ttnguyen@apm.com>
S: Supported
F: drivers/perf/xgene_pmu.c
-F: Documentation/perf/xgene-pmu.txt
+F: Documentation/perf/xgene-pmu.rst
F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
APTINA CAMERA SENSOR PLL
@@ -6663,7 +6663,7 @@ M: Shaokun Zhang <zhangshaokun@hisilicon.com>
W: http://www.hisilicon.com
S: Supported
F: drivers/perf/hisilicon
-F: Documentation/perf/hisi-pmu.txt
+F: Documentation/perf/hisi-pmu.rst
HISILICON PTT DRIVER
M: Yicong Yang <yangyicong@hisilicon.com>
diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c
index b349e7bf4dd9..cc88dc92577e 100644
--- a/drivers/perf/qcom_l3_pmu.c
+++ b/drivers/perf/qcom_l3_pmu.c
@@ -7,7 +7,7 @@
* the slices. User space needs to aggregate to individual counts to provide
* a global picture.
*
- * See Documentation/perf/qcom_l3_pmu.txt for more details.
+ * See Documentation/perf/qcom_l3_pmu.rst for more details.
*
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
--
2.27.0

View File

@ -0,0 +1,113 @@
From 7901f6e0c3c188badd67a49ba546df8da2f0a123 Mon Sep 17 00:00:00 2001
From: Qi Liu <liuqi115@huawei.com>
Date: Thu, 16 Jul 2020 17:19:25 +0800
Subject: [PATCH 08/55] drivers/perf: Fix kernel panic when rmmod PMU modules
during perf sampling
mainline inclusion
from mainline-v5.8-rc1
commit bdc5c744c7b6457d18a95c26769dad0e7f480a08
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdc5c744c7b6457d18a95c26769dad0e7f480a08
----------------------------------------------------------------------
When users try to remove PMU modules during perf sampling, kernel panic
will happen because the pmu->read() is a NULL pointer here.
INFO on HiSilicon hip08 platform as follow:
pc : hisi_uncore_pmu_event_update+0x30/0xa4 [hisi_uncore_pmu]
lr : hisi_uncore_pmu_read+0x20/0x2c [hisi_uncore_pmu]
sp : ffff800010103e90
x29: ffff800010103e90 x28: ffff0027db0c0e40
x27: ffffa29a76f129d8 x26: ffffa29a77ceb000
x25: ffffa29a773a5000 x24: ffffa29a77392000
x23: ffffddffe5943f08 x22: ffff002784285960
x21: ffff002784285800 x20: ffff0027d2e76c80
x19: ffff0027842859e0 x18: ffff80003498bcc8
x17: ffffa29a76afe910 x16: ffffa29a7583f530
x15: 16151a1512061a1e x14: 0000000000000000
x13: ffffa29a76f1e238 x12: 0000000000000001
x11: 0000000000000400 x10: 00000000000009f0
x9 : ffff8000107b3e70 x8 : ffff0027db0c1890
x7 : ffffa29a773a7000 x6 : 00000007f5131013
x5 : 00000007f5131013 x4 : 09f257d417c00000
x3 : 00000002187bd7ce x2 : ffffa29a38f0f0d8
x1 : ffffa29a38eae268 x0 : ffff0027d2e76c80
Call trace:
hisi_uncore_pmu_event_update+0x30/0xa4 [hisi_uncore_pmu]
hisi_uncore_pmu_read+0x20/0x2c [hisi_uncore_pmu]
__perf_event_read+0x1a0/0x1f8
flush_smp_call_function_queue+0xa0/0x160
generic_smp_call_function_single_interrupt+0x18/0x20
handle_IPI+0x31c/0x4dc
gic_handle_irq+0x2c8/0x310
el1_irq+0xcc/0x180
arch_cpu_idle+0x4c/0x20c
default_idle_call+0x20/0x30
do_idle+0x1b4/0x270
cpu_startup_entry+0x28/0x30
secondary_start_kernel+0x1a4/0x1fc
To solve the above issue, current module should be registered to kernel,
so that try_module_get() can be invoked when perf sampling starts. This
adds the reference counting of module and could prevent users from removing
modules during sampling.
Reported-by: Haifeng Wang <wang.wanghaifeng@huawei.com>
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Reviewed-by: John Garry <john.garry@huawei.com>
Link: https://lore.kernel.org/r/1594891165-8228-1-git-send-email-liuqi115@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/fsl_imx8_ddr_perf.c
drivers/perf/arm_smmuv3_pmu.c
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 +
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 1 +
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index b3488ae1f2b8..620fa1345150 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -386,6 +386,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
ddrc_pmu->sccl_id, ddrc_pmu->index_id);
ddrc_pmu->pmu = (struct pmu) {
.name = name,
+ .module = THIS_MODULE,
.task_ctx_nr = perf_invalid_context,
.event_init = hisi_uncore_pmu_event_init,
.pmu_enable = hisi_uncore_pmu_enable,
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index f0215d50d84d..33a0da941be2 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -397,6 +397,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
hha_pmu->sccl_id, hha_pmu->index_id);
hha_pmu->pmu = (struct pmu) {
.name = name,
+ .module = THIS_MODULE,
.task_ctx_nr = perf_invalid_context,
.event_init = hisi_uncore_pmu_event_init,
.pmu_enable = hisi_uncore_pmu_enable,
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 11563e29d983..92485f00dcc8 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -387,6 +387,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
l3c_pmu->sccl_id, l3c_pmu->index_id);
l3c_pmu->pmu = (struct pmu) {
.name = name,
+ .module = THIS_MODULE,
.task_ctx_nr = perf_invalid_context,
.event_init = hisi_uncore_pmu_event_init,
.pmu_enable = hisi_uncore_pmu_enable,
--
2.27.0

View File

@ -0,0 +1,194 @@
From 6d7245609c516aae8719e8d27b737337635ad8c3 Mon Sep 17 00:00:00 2001
From: Andrew Murray <andrew.murray@arm.com>
Date: Thu, 10 Jan 2019 13:53:29 +0000
Subject: [PATCH 09/55] For drivers that do not support context exclusion let's
advertise the PERF_PMU_CAP_NO_EXCLUDE capability. This ensures that perf will
prevent us from handling events where any exclusion flags are set. Let's also
remove the now unnecessary check for exclusion flags.
mainline inclusion
from mainline-v5.1-rc1
commit 306563985819ed2af9df0a26ae368ed12cf28f41
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?=306563985819ed2af9df0a26ae368ed12cf28f41
--------------------------------------------------------------------
Signed-off-by: Andrew Murray <andrew.murray@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: robin.murphy@arm.com
Cc: suzuki.poulose@arm.com
Link: https://lkml.kernel.org/r/1547128414-50693-8-git-send-email-andrew.murray@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/thunderx2_pmu.c
---
drivers/perf/arm-cci.c | 10 +---------
drivers/perf/arm-ccn.c | 6 ++----
drivers/perf/arm_dsu_pmu.c | 9 ++-------
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 +
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 1 +
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 1 +
drivers/perf/hisilicon/hisi_uncore_pmu.c | 9 ---------
7 files changed, 8 insertions(+), 29 deletions(-)
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c
index 3bbc853dc12f..aca4570f78a8 100644
--- a/drivers/perf/arm-cci.c
+++ b/drivers/perf/arm-cci.c
@@ -1327,15 +1327,6 @@ static int cci_pmu_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EOPNOTSUPP;
- /* We have no filtering of any kind */
- if (event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle ||
- event->attr.exclude_host ||
- event->attr.exclude_guest)
- return -EINVAL;
-
/*
* Following the example set by other "uncore" PMUs, we accept any CPU
* and rewrite its affinity dynamically rather than having perf core
@@ -1433,6 +1424,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
.stop = cci_pmu_stop,
.read = pmu_read,
.attr_groups = pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
cci_pmu->plat_device = pdev;
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c
index e4e06d2fbe29..e13ff765b362 100644
--- a/drivers/perf/arm-ccn.c
+++ b/drivers/perf/arm-ccn.c
@@ -741,10 +741,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
return -EOPNOTSUPP;
}
- if (has_branch_stack(event) || event->attr.exclude_user ||
- event->attr.exclude_kernel || event->attr.exclude_hv ||
- event->attr.exclude_idle || event->attr.exclude_host ||
- event->attr.exclude_guest) {
+ if (has_branch_stack(event)) {
dev_dbg(ccn->dev, "Can't exclude execution levels!\n");
return -EINVAL;
}
@@ -1290,6 +1287,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
.read = arm_ccn_pmu_event_read,
.pmu_enable = arm_ccn_pmu_enable,
.pmu_disable = arm_ccn_pmu_disable,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
/* No overflow interrupt? Have to use a timer instead. */
diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
index f1cb7a910394..87573eaa7fdd 100644
--- a/drivers/perf/arm_dsu_pmu.c
+++ b/drivers/perf/arm_dsu_pmu.c
@@ -562,13 +562,7 @@ static int dsu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
- if (has_branch_stack(event) ||
- event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle ||
- event->attr.exclude_host ||
- event->attr.exclude_guest) {
+ if (has_branch_stack(event)) {
dev_dbg(dsu_pmu->pmu.dev, "Can't support filtering\n");
return -EINVAL;
}
@@ -735,6 +729,7 @@ static int dsu_pmu_device_probe(struct platform_device *pdev)
.read = dsu_pmu_read,
.attr_groups = dsu_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
rc = perf_pmu_register(&dsu_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 620fa1345150..4bab34504425 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -397,6 +397,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_ddrc_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 33a0da941be2..53711b945551 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -408,6 +408,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_hha_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 92485f00dcc8..171cf74405b3 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -398,6 +398,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = hisi_l3c_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 53f623ac4cc6..50b654a13305 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -148,15 +148,6 @@ int hisi_uncore_pmu_event_init(struct perf_event *event)
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
return -EOPNOTSUPP;
- /* counters do not have these bits */
- if (event->attr.exclude_user ||
- event->attr.exclude_kernel ||
- event->attr.exclude_host ||
- event->attr.exclude_guest ||
- event->attr.exclude_hv ||
- event->attr.exclude_idle)
- return -EINVAL;
-
/*
* The uncore counters not specific to any CPU, so cannot
* support per-task
--
2.27.0

View File

@ -0,0 +1,78 @@
From 9adb641d4a64e0ed52ba63ea401a9858efe8976d Mon Sep 17 00:00:00 2001
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Date: Wed, 20 Feb 2019 11:12:39 +0000
Subject: [PATCH 10/55] drivers: provide devm_platform_ioremap_resource()
mainline inclusion
from mainline-v5.1-rc1
commit 306563985819ed2af9df0a26ae368ed12cf28f41
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=306563985819ed2af9df0a26ae368ed12cf28f41
-------------------------------------------------------------------
There are currently 1200+ instances of using platform_get_resource()
and devm_ioremap_resource() together in the kernel tree.
This patch wraps these two calls in a single helper. Thanks to that
we don't have to declare a local variable for struct resource * and can
omit the redundant argument for resource type. We also have one
function call less.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/base/platform.c | 18 ++++++++++++++++++
include/linux/platform_device.h | 3 +++
2 files changed, 21 insertions(+)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index be8c82cc4445..23ec70ef6897 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -80,6 +80,24 @@ struct resource *platform_get_resource(struct platform_device *dev,
}
EXPORT_SYMBOL_GPL(platform_get_resource);
+/**
+ * devm_platform_ioremap_resource - call devm_ioremap_resource() for a platform
+ * device
+ *
+ * @pdev: platform device to use both for memory resource lookup as well as
+ * resource managemend
+ * @index: resource index
+ */
+void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev,
+ unsigned int index)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, index);
+ return devm_ioremap_resource(&pdev->dev, res);
+}
+EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource);
+
/**
* platform_get_irq - get an IRQ for a device
* @dev: platform device
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 1a9f38f27f65..9e5c98fcea8c 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -51,6 +51,9 @@ extern struct device platform_bus;
extern void arch_setup_pdev_archdata(struct platform_device *);
extern struct resource *platform_get_resource(struct platform_device *,
unsigned int, unsigned int);
+extern void __iomem *
+devm_platform_ioremap_resource(struct platform_device *pdev,
+ unsigned int index);
extern int platform_get_irq(struct platform_device *, unsigned int);
extern int platform_irq_count(struct platform_device *);
extern struct resource *platform_get_resource_byname(struct platform_device *,
--
2.27.0

View File

@ -0,0 +1,97 @@
From ce76ffbdbb8cf7dcdc4bbd2988971202f4ab7e0f Mon Sep 17 00:00:00 2001
From: YueHaibing <yuehaibing@huawei.com>
Date: Fri, 6 Sep 2019 22:36:44 +0800
Subject: [PATCH 11/55] perf: hisi: use devm_platform_ioremap_resource() to
simplify code
mainline inclusion
from mainline-v5.5-rc1
commit 42c184ade43a79d36f50a0b3394b3326633f53f5
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=42c184ade43a79d36f50a0b3394b3326633f53f5
---------------------------------------------------------------
Use devm_platform_ioremap_resource() to simplify the code a bit.
This is detected by coccinelle.
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 5 +----
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 4 +---
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 4 +---
3 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 4bab34504425..5d9dd4078994 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -248,8 +248,6 @@ MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match);
static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *ddrc_pmu)
{
- struct resource *res;
-
/*
* Use the SCCL_ID and DDRC channel ID to identify the
* DDRC PMU, while SCCL_ID is in MPIDR[aff2].
@@ -268,8 +266,7 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
/* DDRC PMUs only share the same SCCL */
ddrc_pmu->ccl_id = -1;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ddrc_pmu->base = devm_ioremap_resource(&pdev->dev, res);
+ ddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ddrc_pmu->base)) {
dev_err(&pdev->dev, "ioremap failed for ddrc_pmu resource\n");
return PTR_ERR(ddrc_pmu->base);
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 53711b945551..d3c517325a3f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -239,7 +239,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *hha_pmu)
{
unsigned long long id;
- struct resource *res;
acpi_status status;
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
@@ -261,8 +260,7 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
/* HHA PMUs only share the same SCCL */
hha_pmu->ccl_id = -1;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hha_pmu->base = devm_ioremap_resource(&pdev->dev, res);
+ hha_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hha_pmu->base)) {
dev_err(&pdev->dev, "ioremap failed for hha_pmu resource\n");
return PTR_ERR(hha_pmu->base);
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 171cf74405b3..cbbf73ea66e6 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -238,7 +238,6 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *l3c_pmu)
{
unsigned long long id;
- struct resource *res;
acpi_status status;
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
@@ -264,8 +263,7 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
return -EINVAL;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- l3c_pmu->base = devm_ioremap_resource(&pdev->dev, res);
+ l3c_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(l3c_pmu->base)) {
dev_err(&pdev->dev, "ioremap failed for l3c_pmu resource\n");
return PTR_ERR(l3c_pmu->base);
--
2.27.0

View File

@ -0,0 +1,218 @@
From 7da4fb60563da82f9b482af152909d29818b5d9e Mon Sep 17 00:00:00 2001
From: John Garry <john.garry@huawei.com>
Date: Fri, 30 Jul 2021 15:43:58 +0800
Subject: [PATCH 12/55] drivers/perf: hisi: Add identifier sysfs file
mainline inclusion
from mainline-v5.10-rc3
commit ac4511c9364c9a6390e8585cdd4596103bca16eb
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ac4511c9364c9a6390e8585cdd4596103bca16eb
------------------------------------------------------------------------
To allow userspace to identify the specific implementation of the device,
add an "identifier" sysfs file.
Encoding is as follows (same for all uncore drivers):
hi1620: 0x0
hi1630: 0x30
Signed-off-by: John Garry <john.garry@huawei.com>
Link: https://lore.kernel.org/r/1602149181-237415-2-git-send-email-john.garry@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 16 ++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 16 ++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 16 ++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.c | 10 ++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 7 +++++++
5 files changed, 65 insertions(+)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 5d9dd4078994..a88c7d840d38 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -36,6 +36,7 @@
#define DDRC_INT_MASK 0x6c8
#define DDRC_INT_STATUS 0x6cc
#define DDRC_INT_CLEAR 0x6d0
+#define DDRC_VERSION 0x710
/* DDRC has 8-counters */
#define DDRC_NR_COUNTERS 0x8
@@ -272,6 +273,8 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
return PTR_ERR(ddrc_pmu->base);
}
+ ddrc_pmu->identifier = readl(ddrc_pmu->base + DDRC_VERSION);
+
return 0;
}
@@ -313,10 +316,23 @@ static const struct attribute_group hisi_ddrc_pmu_cpumask_attr_group = {
.attrs = hisi_ddrc_pmu_cpumask_attrs,
};
+static struct device_attribute hisi_ddrc_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_ddrc_pmu_identifier_attrs[] = {
+ &hisi_ddrc_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_ddrc_pmu_identifier_group = {
+ .attrs = hisi_ddrc_pmu_identifier_attrs,
+};
+
static const struct attribute_group *hisi_ddrc_pmu_attr_groups[] = {
&hisi_ddrc_pmu_format_group,
&hisi_ddrc_pmu_events_group,
&hisi_ddrc_pmu_cpumask_attr_group,
+ &hisi_ddrc_pmu_identifier_group,
NULL,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index d3c517325a3f..1e0138bbe6e7 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -26,6 +26,7 @@
#define HHA_INT_MASK 0x0804
#define HHA_INT_STATUS 0x0808
#define HHA_INT_CLEAR 0x080C
+#define HHA_VERSION 0x1cf0
#define HHA_PERF_CTRL 0x1E00
#define HHA_EVENT_CTRL 0x1E04
#define HHA_EVENT_TYPE0 0x1E80
@@ -266,6 +267,8 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
return PTR_ERR(hha_pmu->base);
}
+ hha_pmu->identifier = readl(hha_pmu->base + HHA_VERSION);
+
return 0;
}
@@ -325,10 +328,23 @@ static const struct attribute_group hisi_hha_pmu_cpumask_attr_group = {
.attrs = hisi_hha_pmu_cpumask_attrs,
};
+static struct device_attribute hisi_hha_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_hha_pmu_identifier_attrs[] = {
+ &hisi_hha_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_hha_pmu_identifier_group = {
+ .attrs = hisi_hha_pmu_identifier_attrs,
+};
+
static const struct attribute_group *hisi_hha_pmu_attr_groups[] = {
&hisi_hha_pmu_format_group,
&hisi_hha_pmu_events_group,
&hisi_hha_pmu_cpumask_attr_group,
+ &hisi_hha_pmu_identifier_group,
NULL,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index cbbf73ea66e6..1707ae551ece 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -28,6 +28,7 @@
#define L3C_INT_STATUS 0x0808
#define L3C_INT_CLEAR 0x080c
#define L3C_EVENT_CTRL 0x1c00
+#define L3C_VERSION 0x1cf0
#define L3C_EVENT_TYPE0 0x1d00
/*
* Each counter is 48-bits and [48:63] are reserved
@@ -269,6 +270,8 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
return PTR_ERR(l3c_pmu->base);
}
+ l3c_pmu->identifier = readl(l3c_pmu->base + L3C_VERSION);
+
return 0;
}
@@ -315,10 +318,23 @@ static const struct attribute_group hisi_l3c_pmu_cpumask_attr_group = {
.attrs = hisi_l3c_pmu_cpumask_attrs,
};
+static struct device_attribute hisi_l3c_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_l3c_pmu_identifier_attrs[] = {
+ &hisi_l3c_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_l3c_pmu_identifier_group = {
+ .attrs = hisi_l3c_pmu_identifier_attrs,
+};
+
static const struct attribute_group *hisi_l3c_pmu_attr_groups[] = {
&hisi_l3c_pmu_format_group,
&hisi_l3c_pmu_events_group,
&hisi_l3c_pmu_cpumask_attr_group,
+ &hisi_l3c_pmu_identifier_group,
NULL,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 50b654a13305..f6a992da24bf 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -122,6 +122,16 @@ int hisi_uncore_pmu_get_event_idx(struct perf_event *event)
}
EXPORT_SYMBOL_GPL(hisi_uncore_pmu_get_event_idx);
+ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct hisi_pmu *hisi_pmu = to_hisi_pmu(dev_get_drvdata(dev));
+
+ return snprintf(page, PAGE_SIZE, "0x%08x\n", hisi_pmu->identifier);
+}
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_identifier_attr_show);
+
static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx)
{
if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 8f2f2fc5dde4..098a8f6dc7ee 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -78,6 +78,7 @@ struct hisi_pmu {
int counter_bits;
/* check event code range */
int check_event;
+ u32 identifier;
};
int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx);
@@ -100,4 +101,10 @@ ssize_t hisi_cpumask_sysfs_show(struct device *dev,
struct device_attribute *attr, char *buf);
int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node);
int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
+
+ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page);
+
+
#endif /* __HISI_UNCORE_PMU_H__ */
--
2.27.0

View File

@ -0,0 +1,193 @@
From 34861133469cfd5c5851f7f4ab05e3d3af1dd13a Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:02 +0800
Subject: [PATCH 13/55] drivers/perf: hisi: Remove unnecessary check of counter
index
mainline inclusion
from mainline-v5.12-rc3
commit 4e4cb8ca48bd68c00df67c10ff867016abb7391f
category: cleanup
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4e4cb8ca48bd68c00df67c10ff867016abb7391f
------------------------------------------------------------------------
The sanity check for counter index has been done in the function
hisi_uncore_pmu_get_event_idx, so remove the redundant interface
hisi_uncore_pmu_counter_valid() and sanity check.
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>
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-2-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 20 +++----------------
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 18 ++---------------
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 18 ++---------------
drivers/perf/hisilicon/hisi_uncore_pmu.c | 11 ----------
drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 -
5 files changed, 7 insertions(+), 61 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index a88c7d840d38..bcb2c2d66b7f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -68,29 +68,15 @@ static u32 hisi_ddrc_pmu_get_counter_offset(int cntr_idx)
static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc)
{
- /* Use event code as counter index */
- u32 idx = GET_DDRC_EVENTID(hwc);
-
- if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) {
- dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx);
- return 0;
- }
-
- return readl(ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx));
+ return readl(ddrc_pmu->base +
+ hisi_ddrc_pmu_get_counter_offset(hwc->idx));
}
static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc, u64 val)
{
- u32 idx = GET_DDRC_EVENTID(hwc);
-
- if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) {
- dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx);
- return;
- }
-
writel((u32)val,
- ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx));
+ ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(hwc->idx));
}
/*
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 1e0138bbe6e7..de1766342b4e 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -54,29 +54,15 @@ static u32 hisi_hha_pmu_get_counter_offset(u32 cntr_idx)
static u64 hisi_hha_pmu_read_counter(struct hisi_pmu *hha_pmu,
struct hw_perf_event *hwc)
{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) {
- dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx);
- return 0;
- }
-
/* Read 64 bits and like L3C, top 16 bits are RAZ */
- return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx));
+ return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx));
}
static void hisi_hha_pmu_write_counter(struct hisi_pmu *hha_pmu,
struct hw_perf_event *hwc, u64 val)
{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) {
- dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx);
- return;
- }
-
/* Write 64 bits and like L3C, top 16 bits are WI */
- writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx));
+ writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx));
}
static void hisi_hha_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 1707ae551ece..c4afeaaaa3a4 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -53,29 +53,15 @@ static u32 hisi_l3c_pmu_get_counter_offset(u32 cntr_idx)
static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu,
struct hw_perf_event *hwc)
{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) {
- dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx);
- return 0;
- }
-
/* Read 64-bits and the upper 16 bits are RAZ */
- return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx));
+ return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
}
static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu,
struct hw_perf_event *hwc, u64 val)
{
- u32 idx = hwc->idx;
-
- if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) {
- dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx);
- return;
- }
-
/* Write 64-bits and the upper 16 bits are WI */
- writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx));
+ writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
}
static void hisi_l3c_pmu_write_evtype(struct hisi_pmu *l3c_pmu, int idx,
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index f6a992da24bf..9ebdb76dd3a4 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -99,12 +99,6 @@ static bool hisi_validate_event_group(struct perf_event *event)
return counters <= hisi_pmu->num_counters;
}
-int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx)
-{
- return idx >= 0 && idx < hisi_pmu->num_counters;
-}
-EXPORT_SYMBOL_GPL(hisi_uncore_pmu_counter_valid);
-
int hisi_uncore_pmu_get_event_idx(struct perf_event *event)
{
struct hisi_pmu *hisi_pmu = to_hisi_pmu(event->pmu);
@@ -134,11 +128,6 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_identifier_attr_show);
static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx)
{
- if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) {
- dev_err(hisi_pmu->dev, "Unsupported event index:%d!\n", idx);
- return;
- }
-
clear_bit(idx, hisi_pmu->pmu_events.used_mask);
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 098a8f6dc7ee..d71a6c86b282 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -81,7 +81,6 @@ struct hisi_pmu {
u32 identifier;
};
-int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx);
int hisi_uncore_pmu_get_event_idx(struct perf_event *event);
void hisi_uncore_pmu_read(struct perf_event *event);
int hisi_uncore_pmu_add(struct perf_event *event, int flags);
--
2.27.0

View File

@ -0,0 +1,448 @@
From 990f0977794c7bc3a78dbea66e3b5e276eccaad4 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:03 +0800
Subject: [PATCH 14/55] drivers/perf: hisi: Refactor code for more uncore PMUs
mainline inclusion
from mainline-v5.12-rc3
commit baff06c315a146a6943b4fcabb4fe4fa36167413
category: cleanup
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=baff06c315a146a6943b4fcabb4fe4fa36167413
------------------------------------------------------------------------
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>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 61 +++----------------
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 61 +++----------------
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 61 +++----------------
drivers/perf/hisilicon/hisi_uncore_pmu.c | 54 ++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 6 +-
5 files changed, 80 insertions(+), 163 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index bcb2c2d66b7f..a03e3f8058b3 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/platform_device.h>
#include <linux/smp.h>
#include "hisi_uncore_pmu.h"
@@ -168,62 +167,14 @@ static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu,
writel(val, ddrc_pmu->base + DDRC_INT_MASK);
}
-static irqreturn_t hisi_ddrc_pmu_isr(int irq, void *dev_id)
+static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu)
{
- struct hisi_pmu *ddrc_pmu = dev_id;
- struct perf_event *event;
- unsigned long overflown;
- int idx;
-
- /* Read the DDRC_INT_STATUS register */
- overflown = readl(ddrc_pmu->base + DDRC_INT_STATUS);
- 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, DDRC_NR_COUNTERS) {
- /* Write 1 to clear the IRQ status flag */
- writel((1 << idx), ddrc_pmu->base + DDRC_INT_CLEAR);
-
- /* Get the corresponding event struct */
- event = ddrc_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;
+ return readl(ddrc_pmu->base + DDRC_INT_STATUS);
}
-static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu,
- struct platform_device *pdev)
+static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, int idx)
{
- int irq, ret;
-
- /* Read and init IRQ */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "DDRC PMU get irq fail; irq:%d\n", irq);
- return irq;
- }
-
- ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD,
- dev_name(&pdev->dev), ddrc_pmu);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Fail to request IRQ:%d ret:%d\n", irq, ret);
- return ret;
- }
-
- ddrc_pmu->irq = irq;
-
- return 0;
+ writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR);
}
static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
@@ -333,6 +284,8 @@ static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = {
.disable_counter_int = hisi_ddrc_pmu_disable_counter_int,
.write_counter = hisi_ddrc_pmu_write_counter,
.read_counter = hisi_ddrc_pmu_read_counter,
+ .get_int_status = hisi_ddrc_pmu_get_int_status,
+ .clear_int_status = hisi_ddrc_pmu_clear_int_status,
};
static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
@@ -344,7 +297,7 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- ret = hisi_ddrc_pmu_init_irq(ddrc_pmu, pdev);
+ ret = hisi_uncore_pmu_init_irq(ddrc_pmu, pdev);
if (ret)
return ret;
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index de1766342b4e..536d1f637fa7 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/platform_device.h>
#include <linux/smp.h>
#include "hisi_uncore_pmu.h"
@@ -158,62 +157,14 @@ static void hisi_hha_pmu_disable_counter_int(struct hisi_pmu *hha_pmu,
writel(val, hha_pmu->base + HHA_INT_MASK);
}
-static irqreturn_t hisi_hha_pmu_isr(int irq, void *dev_id)
+static u32 hisi_hha_pmu_get_int_status(struct hisi_pmu *hha_pmu)
{
- struct hisi_pmu *hha_pmu = dev_id;
- struct perf_event *event;
- unsigned long overflown;
- int idx;
-
- /* Read HHA_INT_STATUS register */
- overflown = readl(hha_pmu->base + HHA_INT_STATUS);
- 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, HHA_NR_COUNTERS) {
- /* Write 1 to clear the IRQ status flag */
- writel((1 << idx), hha_pmu->base + HHA_INT_CLEAR);
-
- /* Get the corresponding event struct */
- event = hha_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;
+ return readl(hha_pmu->base + HHA_INT_STATUS);
}
-static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu,
- struct platform_device *pdev)
+static void hisi_hha_pmu_clear_int_status(struct hisi_pmu *hha_pmu, int idx)
{
- int irq, ret;
-
- /* Read and init IRQ */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "HHA PMU get irq fail; irq:%d\n", irq);
- return irq;
- }
-
- ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD,
- dev_name(&pdev->dev), hha_pmu);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Fail to request IRQ:%d ret:%d\n", irq, ret);
- return ret;
- }
-
- hha_pmu->irq = irq;
-
- return 0;
+ writel(1 << idx, hha_pmu->base + HHA_INT_CLEAR);
}
static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = {
@@ -345,6 +296,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = {
.disable_counter_int = hisi_hha_pmu_disable_counter_int,
.write_counter = hisi_hha_pmu_write_counter,
.read_counter = hisi_hha_pmu_read_counter,
+ .get_int_status = hisi_hha_pmu_get_int_status,
+ .clear_int_status = hisi_hha_pmu_clear_int_status,
};
static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
@@ -356,7 +309,7 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- ret = hisi_hha_pmu_init_irq(hha_pmu, pdev);
+ ret = hisi_uncore_pmu_init_irq(hha_pmu, pdev);
if (ret)
return ret;
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index c4afeaaaa3a4..5256e4ce3384 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/list.h>
-#include <linux/platform_device.h>
#include <linux/smp.h>
#include "hisi_uncore_pmu.h"
@@ -157,62 +156,14 @@ static void hisi_l3c_pmu_disable_counter_int(struct hisi_pmu *l3c_pmu,
writel(val, l3c_pmu->base + L3C_INT_MASK);
}
-static irqreturn_t hisi_l3c_pmu_isr(int irq, void *dev_id)
+static u32 hisi_l3c_pmu_get_int_status(struct hisi_pmu *l3c_pmu)
{
- struct hisi_pmu *l3c_pmu = dev_id;
- struct perf_event *event;
- unsigned long overflown;
- int idx;
-
- /* Read L3C_INT_STATUS register */
- overflown = readl(l3c_pmu->base + L3C_INT_STATUS);
- 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, L3C_NR_COUNTERS) {
- /* Write 1 to clear the IRQ status flag */
- writel((1 << idx), l3c_pmu->base + L3C_INT_CLEAR);
-
- /* Get the corresponding event struct */
- event = l3c_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;
+ return readl(l3c_pmu->base + L3C_INT_STATUS);
}
-static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu,
- struct platform_device *pdev)
+static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx)
{
- int irq, ret;
-
- /* Read and init IRQ */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "L3C PMU get irq fail; irq:%d\n", irq);
- return irq;
- }
-
- ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD,
- dev_name(&pdev->dev), l3c_pmu);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Fail to request IRQ:%d ret:%d\n", irq, ret);
- return ret;
- }
-
- l3c_pmu->irq = irq;
-
- return 0;
+ writel(1 << idx, l3c_pmu->base + L3C_INT_CLEAR);
}
static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = {
@@ -335,6 +286,8 @@ static const struct hisi_uncore_ops hisi_uncore_l3c_ops = {
.disable_counter_int = hisi_l3c_pmu_disable_counter_int,
.write_counter = hisi_l3c_pmu_write_counter,
.read_counter = hisi_l3c_pmu_read_counter,
+ .get_int_status = hisi_l3c_pmu_get_int_status,
+ .clear_int_status = hisi_l3c_pmu_clear_int_status,
};
static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
@@ -346,7 +299,7 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- ret = hisi_l3c_pmu_init_irq(l3c_pmu, pdev);
+ ret = hisi_uncore_pmu_init_irq(l3c_pmu, pdev);
if (ret)
return ret;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 9ebdb76dd3a4..53ac9f062c0f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -131,6 +131,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;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index d71a6c86b282..3336723e8cf6 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/perf_event.h>
+#include <linux/platform_device.h>
#include <linux/types.h>
#undef pr_fmt
@@ -50,6 +51,8 @@ struct hisi_uncore_ops {
void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
void (*start_counters)(struct hisi_pmu *);
void (*stop_counters)(struct hisi_pmu *);
+ u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
+ void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
};
struct hisi_pmu_hwevents {
@@ -104,6 +107,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
struct device_attribute *attr,
char *page);
-
+int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
+ struct platform_device *pdev);
#endif /* __HISI_UNCORE_PMU_H__ */
--
2.27.0

View File

@ -0,0 +1,448 @@
From 3d5c7ff8c993e8f570d32755ba43ae17e02b007e Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:04 +0800
Subject: [PATCH 15/55] drivers/perf: hisi: Add PMU version for uncore PMU
drivers.
mainline inclusion
from mainline-v5.12-rc3
commit 3da582df575c3b2910e09e0445c27c3ebc8096e5
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3da582df575c3b2910e09e0445c27c3ebc8096e5
------------------------------------------------------------------------
For HiSilicon uncore PMU, more versions are supported and some variables
shall be added suffix to distinguish the version which are prepared for
the new drivers.
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>
Acked-by: Mark Rutland <mark.rutland@arm.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-4-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 96 ++++++++++---------
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 27 +++---
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 23 ++---
3 files changed, 75 insertions(+), 71 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index a03e3f8058b3..1d1c8e9f417e 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -39,7 +39,8 @@
/* DDRC has 8-counters */
#define DDRC_NR_COUNTERS 0x8
-#define DDRC_PERF_CTRL_EN 0x2
+#define DDRC_V1_PERF_CTRL_EN 0x2
+#define DDRC_V1_NR_EVENTS 0x7
/*
* For DDRC PMU, there are eight-events and every event has been mapped
@@ -56,26 +57,26 @@ static const u32 ddrc_reg_off[] = {
/*
* Select the counter register offset using the counter index.
- * In DDRC there are no programmable counter, the count
- * is readed form the statistics counter register itself.
+ * In PMU v1, there are no programmable counter, the count
+ * is read form the statistics counter register itself.
*/
-static u32 hisi_ddrc_pmu_get_counter_offset(int cntr_idx)
+static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx)
{
return ddrc_reg_off[cntr_idx];
}
-static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu,
+static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc)
{
return readl(ddrc_pmu->base +
- hisi_ddrc_pmu_get_counter_offset(hwc->idx));
+ hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx));
}
-static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu,
+static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc, u64 val)
{
writel((u32)val,
- ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(hwc->idx));
+ ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx));
}
/*
@@ -87,28 +88,28 @@ static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
{
}
-static void hisi_ddrc_pmu_start_counters(struct hisi_pmu *ddrc_pmu)
+static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu)
{
u32 val;
/* Set perf_enable in DDRC_PERF_CTRL to start event counting */
val = readl(ddrc_pmu->base + DDRC_PERF_CTRL);
- val |= DDRC_PERF_CTRL_EN;
+ val |= DDRC_V1_PERF_CTRL_EN;
writel(val, ddrc_pmu->base + DDRC_PERF_CTRL);
}
-static void hisi_ddrc_pmu_stop_counters(struct hisi_pmu *ddrc_pmu)
+static void hisi_ddrc_pmu_v1_stop_counters(struct hisi_pmu *ddrc_pmu)
{
u32 val;
/* Clear perf_enable in DDRC_PERF_CTRL to stop event counting */
val = readl(ddrc_pmu->base + DDRC_PERF_CTRL);
- val &= ~DDRC_PERF_CTRL_EN;
+ val &= ~DDRC_V1_PERF_CTRL_EN;
writel(val, ddrc_pmu->base + DDRC_PERF_CTRL);
}
-static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu,
- struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_v1_enable_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
{
u32 val;
@@ -118,8 +119,8 @@ static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu,
writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL);
}
-static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu,
- struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_v1_disable_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
{
u32 val;
@@ -129,7 +130,7 @@ static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu,
writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL);
}
-static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event)
+static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event)
{
struct hisi_pmu *ddrc_pmu = to_hisi_pmu(event->pmu);
unsigned long *used_mask = ddrc_pmu->pmu_events.used_mask;
@@ -145,8 +146,8 @@ static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event)
return idx;
}
-static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu,
- struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
{
u32 val;
@@ -156,8 +157,8 @@ static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu,
writel(val, ddrc_pmu->base + DDRC_INT_MASK);
}
-static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu,
- struct hw_perf_event *hwc)
+static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
{
u32 val;
@@ -167,12 +168,13 @@ static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu,
writel(val, ddrc_pmu->base + DDRC_INT_MASK);
}
-static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu)
+static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu)
{
return readl(ddrc_pmu->base + DDRC_INT_STATUS);
}
-static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, int idx)
+static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu,
+ int idx)
{
writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR);
}
@@ -215,17 +217,17 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
return 0;
}
-static struct attribute *hisi_ddrc_pmu_format_attr[] = {
+static struct attribute *hisi_ddrc_pmu_v1_format_attr[] = {
HISI_PMU_FORMAT_ATTR(event, "config:0-4"),
NULL,
};
-static const struct attribute_group hisi_ddrc_pmu_format_group = {
+static const struct attribute_group hisi_ddrc_pmu_v1_format_group = {
.name = "format",
- .attrs = hisi_ddrc_pmu_format_attr,
+ .attrs = hisi_ddrc_pmu_v1_format_attr,
};
-static struct attribute *hisi_ddrc_pmu_events_attr[] = {
+static struct attribute *hisi_ddrc_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(flux_wr, 0x00),
HISI_PMU_EVENT_ATTR(flux_rd, 0x01),
HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02),
@@ -237,9 +239,9 @@ static struct attribute *hisi_ddrc_pmu_events_attr[] = {
NULL,
};
-static const struct attribute_group hisi_ddrc_pmu_events_group = {
+static const struct attribute_group hisi_ddrc_pmu_v1_events_group = {
.name = "events",
- .attrs = hisi_ddrc_pmu_events_attr,
+ .attrs = hisi_ddrc_pmu_v1_events_attr,
};
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
@@ -265,27 +267,27 @@ static struct attribute_group hisi_ddrc_pmu_identifier_group = {
.attrs = hisi_ddrc_pmu_identifier_attrs,
};
-static const struct attribute_group *hisi_ddrc_pmu_attr_groups[] = {
- &hisi_ddrc_pmu_format_group,
- &hisi_ddrc_pmu_events_group,
+static const struct attribute_group *hisi_ddrc_pmu_v1_attr_groups[] = {
+ &hisi_ddrc_pmu_v1_format_group,
+ &hisi_ddrc_pmu_v1_events_group,
&hisi_ddrc_pmu_cpumask_attr_group,
&hisi_ddrc_pmu_identifier_group,
NULL,
};
-static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = {
+static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = {
.write_evtype = hisi_ddrc_pmu_write_evtype,
- .get_event_idx = hisi_ddrc_pmu_get_event_idx,
- .start_counters = hisi_ddrc_pmu_start_counters,
- .stop_counters = hisi_ddrc_pmu_stop_counters,
- .enable_counter = hisi_ddrc_pmu_enable_counter,
- .disable_counter = hisi_ddrc_pmu_disable_counter,
- .enable_counter_int = hisi_ddrc_pmu_enable_counter_int,
- .disable_counter_int = hisi_ddrc_pmu_disable_counter_int,
- .write_counter = hisi_ddrc_pmu_write_counter,
- .read_counter = hisi_ddrc_pmu_read_counter,
- .get_int_status = hisi_ddrc_pmu_get_int_status,
- .clear_int_status = hisi_ddrc_pmu_clear_int_status,
+ .get_event_idx = hisi_ddrc_pmu_v1_get_event_idx,
+ .start_counters = hisi_ddrc_pmu_v1_start_counters,
+ .stop_counters = hisi_ddrc_pmu_v1_stop_counters,
+ .enable_counter = hisi_ddrc_pmu_v1_enable_counter,
+ .disable_counter = hisi_ddrc_pmu_v1_disable_counter,
+ .enable_counter_int = hisi_ddrc_pmu_v1_enable_counter_int,
+ .disable_counter_int = hisi_ddrc_pmu_v1_disable_counter_int,
+ .write_counter = hisi_ddrc_pmu_v1_write_counter,
+ .read_counter = hisi_ddrc_pmu_v1_read_counter,
+ .get_int_status = hisi_ddrc_pmu_v1_get_int_status,
+ .clear_int_status = hisi_ddrc_pmu_v1_clear_int_status,
};
static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
@@ -303,10 +305,10 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
ddrc_pmu->num_counters = DDRC_NR_COUNTERS;
ddrc_pmu->counter_bits = 32;
- ddrc_pmu->ops = &hisi_uncore_ddrc_ops;
+ ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops;
ddrc_pmu->dev = &pdev->dev;
ddrc_pmu->on_cpu = -1;
- ddrc_pmu->check_event = 7;
+ ddrc_pmu->check_event = DDRC_V1_NR_EVENTS;
return 0;
}
@@ -348,7 +350,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_ddrc_pmu_attr_groups,
+ .attr_groups = hisi_ddrc_pmu_v1_attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 536d1f637fa7..7941900ea667 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -36,10 +36,11 @@
#define HHA_CNT0_LOWER 0x1F00
/* HHA has 16-counters */
-#define HHA_NR_COUNTERS 0x10
+#define HHA_V1_NR_COUNTERS 0x10
#define HHA_PERF_CTRL_EN 0x1
#define HHA_EVTYPE_NONE 0xff
+#define HHA_V1_NR_EVENT 0x65
/*
* Select the counter register offset using the counter index
@@ -209,17 +210,17 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
return 0;
}
-static struct attribute *hisi_hha_pmu_format_attr[] = {
+static struct attribute *hisi_hha_pmu_v1_format_attr[] = {
HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
NULL,
};
-static const struct attribute_group hisi_hha_pmu_format_group = {
+static const struct attribute_group hisi_hha_pmu_v1_format_group = {
.name = "format",
- .attrs = hisi_hha_pmu_format_attr,
+ .attrs = hisi_hha_pmu_v1_format_attr,
};
-static struct attribute *hisi_hha_pmu_events_attr[] = {
+static struct attribute *hisi_hha_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00),
HISI_PMU_EVENT_ATTR(rx_outer, 0x01),
HISI_PMU_EVENT_ATTR(rx_sccl, 0x02),
@@ -249,9 +250,9 @@ static struct attribute *hisi_hha_pmu_events_attr[] = {
NULL,
};
-static const struct attribute_group hisi_hha_pmu_events_group = {
+static const struct attribute_group hisi_hha_pmu_v1_events_group = {
.name = "events",
- .attrs = hisi_hha_pmu_events_attr,
+ .attrs = hisi_hha_pmu_v1_events_attr,
};
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
@@ -277,9 +278,9 @@ static struct attribute_group hisi_hha_pmu_identifier_group = {
.attrs = hisi_hha_pmu_identifier_attrs,
};
-static const struct attribute_group *hisi_hha_pmu_attr_groups[] = {
- &hisi_hha_pmu_format_group,
- &hisi_hha_pmu_events_group,
+static const struct attribute_group *hisi_hha_pmu_v1_attr_groups[] = {
+ &hisi_hha_pmu_v1_format_group,
+ &hisi_hha_pmu_v1_events_group,
&hisi_hha_pmu_cpumask_attr_group,
&hisi_hha_pmu_identifier_group,
NULL,
@@ -313,12 +314,12 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- hha_pmu->num_counters = HHA_NR_COUNTERS;
+ hha_pmu->num_counters = HHA_V1_NR_COUNTERS;
hha_pmu->counter_bits = 48;
hha_pmu->ops = &hisi_uncore_hha_ops;
hha_pmu->dev = &pdev->dev;
hha_pmu->on_cpu = -1;
- hha_pmu->check_event = 0x65;
+ hha_pmu->check_event = HHA_V1_NR_EVENT;
return 0;
}
@@ -360,7 +361,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_hha_pmu_attr_groups,
+ .attr_groups = hisi_hha_pmu_v1_attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 5256e4ce3384..5a4975e64368 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -40,6 +40,7 @@
#define L3C_PERF_CTRL_EN 0x10000
#define L3C_EVTYPE_NONE 0xff
+#define L3C_V1_NR_EVENTS 0x59
/*
* Select the counter register offset using the counter index
@@ -212,17 +213,17 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
return 0;
}
-static struct attribute *hisi_l3c_pmu_format_attr[] = {
+static struct attribute *hisi_l3c_pmu_v1_format_attr[] = {
HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
NULL,
};
-static const struct attribute_group hisi_l3c_pmu_format_group = {
+static const struct attribute_group hisi_l3c_pmu_v1_format_group = {
.name = "format",
- .attrs = hisi_l3c_pmu_format_attr,
+ .attrs = hisi_l3c_pmu_v1_format_attr,
};
-static struct attribute *hisi_l3c_pmu_events_attr[] = {
+static struct attribute *hisi_l3c_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00),
HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01),
HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02),
@@ -239,9 +240,9 @@ static struct attribute *hisi_l3c_pmu_events_attr[] = {
NULL,
};
-static const struct attribute_group hisi_l3c_pmu_events_group = {
+static const struct attribute_group hisi_l3c_pmu_v1_events_group = {
.name = "events",
- .attrs = hisi_l3c_pmu_events_attr,
+ .attrs = hisi_l3c_pmu_v1_events_attr,
};
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
@@ -267,9 +268,9 @@ static struct attribute_group hisi_l3c_pmu_identifier_group = {
.attrs = hisi_l3c_pmu_identifier_attrs,
};
-static const struct attribute_group *hisi_l3c_pmu_attr_groups[] = {
- &hisi_l3c_pmu_format_group,
- &hisi_l3c_pmu_events_group,
+static const struct attribute_group *hisi_l3c_pmu_v1_attr_groups[] = {
+ &hisi_l3c_pmu_v1_format_group,
+ &hisi_l3c_pmu_v1_events_group,
&hisi_l3c_pmu_cpumask_attr_group,
&hisi_l3c_pmu_identifier_group,
NULL,
@@ -308,7 +309,7 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
l3c_pmu->ops = &hisi_uncore_l3c_ops;
l3c_pmu->dev = &pdev->dev;
l3c_pmu->on_cpu = -1;
- l3c_pmu->check_event = 0x59;
+ l3c_pmu->check_event = L3C_V1_NR_EVENTS;
return 0;
}
@@ -350,7 +351,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_l3c_pmu_attr_groups,
+ .attr_groups = hisi_l3c_pmu_v1_attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
--
2.27.0

View File

@ -0,0 +1,505 @@
From d4d47e781c088759005a0a6dc4e843a8bfeb5bdd Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:05 +0800
Subject: [PATCH 16/55] drivers/perf: hisi: Add new functions for L3C PMU
mainline inclusion
from mainline-v5.12-rc3
commit 486a7f46b966a825484808d4edf53bbe02698fb3
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=486a7f46b966a825484808d4edf53bbe02698fb3
------------------------------------------------------------------------
On HiSilicon Hip09 platform, some new functions are enhanced on L3C PMU:
* tt_req: it is the abbreviation of tracetag request and allows user to
count only read/write/atomic operations. tt_req is 3-bit and details are
listed in the hisi-pmu document.
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5
* tt_core: it is the abbreviation of tracetag core and allows user to
filter by core/thread within the cluster, it is a 8-bit bitmap that each
bit represents the corresponding core/thread in this L3C.
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0xf/ sleep 5
* datasrc_cfg: it is the abbreviation of data source configuration and
allows user to check where the data comes from, such as: from local DDR,
cross-die DDR or cross-socket DDR. Its is 5-bit and represents different
data source in the SoC.
$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0xe/ sleep 5
* datasrc_skt: it is the abbreviation of data source from another socket
and is used in the multi-chips, if user wants to check the cross-socket
datat source, it shall be added in perf command. Only one bit is used to
control this.
$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0x10,datasrc_skt=1/ sleep 5
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-5-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 259 +++++++++++++++++--
drivers/perf/hisilicon/hisi_uncore_pmu.c | 8 +-
drivers/perf/hisilicon/hisi_uncore_pmu.h | 11 +
3 files changed, 258 insertions(+), 20 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 5a4975e64368..87ca2a9ca8c5 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -26,12 +26,17 @@
#define L3C_INT_MASK 0x0800
#define L3C_INT_STATUS 0x0808
#define L3C_INT_CLEAR 0x080c
+#define L3C_CORE_CTRL 0x1b04
+#define L3C_TRACETAG_CTRL 0x1b20
+#define L3C_DATSRC_TYPE 0x1b48
+#define L3C_DATSRC_CTRL 0x1bf0
#define L3C_EVENT_CTRL 0x1c00
#define L3C_VERSION 0x1cf0
#define L3C_EVENT_TYPE0 0x1d00
/*
- * Each counter is 48-bits and [48:63] are reserved
- * which are Read-As-Zero and Writes-Ignored.
+ * If the HW version only supports a 48-bit counter, then
+ * bits [63:48] are reserved, which are Read-As-Zero and
+ * Writes-Ignored.
*/
#define L3C_CNTR0_LOWER 0x1e00
@@ -39,8 +44,186 @@
#define L3C_NR_COUNTERS 0x8
#define L3C_PERF_CTRL_EN 0x10000
+#define L3C_TRACETAG_EN BIT(31)
+#define L3C_TRACETAG_REQ_SHIFT 7
+#define L3C_TRACETAG_MARK_EN BIT(0)
+#define L3C_TRACETAG_REQ_EN (L3C_TRACETAG_MARK_EN | BIT(2))
+#define L3C_TRACETAG_CORE_EN (L3C_TRACETAG_MARK_EN | BIT(3))
+#define L3C_CORE_EN BIT(20)
+#define L3C_COER_NONE 0x0
+#define L3C_DATSRC_MASK 0xFF
+#define L3C_DATSRC_SKT_EN BIT(23)
+#define L3C_DATSRC_NONE 0x0
#define L3C_EVTYPE_NONE 0xff
#define L3C_V1_NR_EVENTS 0x59
+#define L3C_V2_NR_EVENTS 0xFF
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_core, config1, 7, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_req, config1, 10, 8);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_cfg, config1, 15, 11);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 16, 16);
+
+static void hisi_l3c_pmu_config_req_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_req = hisi_get_tt_req(event);
+
+ if (tt_req) {
+ u32 val;
+
+ /* Set request-type for tracetag */
+ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
+ val |= tt_req << L3C_TRACETAG_REQ_SHIFT;
+ val |= L3C_TRACETAG_REQ_EN;
+ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
+
+ /* Enable request-tracetag statistics */
+ val = readl(l3c_pmu->base + L3C_PERF_CTRL);
+ val |= L3C_TRACETAG_EN;
+ writel(val, l3c_pmu->base + L3C_PERF_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_clear_req_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_req = hisi_get_tt_req(event);
+
+ if (tt_req) {
+ u32 val;
+
+ /* Clear request-type */
+ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
+ val &= ~(tt_req << L3C_TRACETAG_REQ_SHIFT);
+ val &= ~L3C_TRACETAG_REQ_EN;
+ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
+
+ /* Disable request-tracetag statistics */
+ val = readl(l3c_pmu->base + L3C_PERF_CTRL);
+ val &= ~L3C_TRACETAG_EN;
+ writel(val, l3c_pmu->base + L3C_PERF_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_write_ds(struct perf_event *event, u32 ds_cfg)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ u32 reg, reg_idx, shift, val;
+ int idx = hwc->idx;
+
+ /*
+ * Select the appropriate datasource register(L3C_DATSRC_TYPE0/1).
+ * There are 2 datasource ctrl register for the 8 hardware counters.
+ * Datasrc is 8-bits and for the former 4 hardware counters,
+ * L3C_DATSRC_TYPE0 is chosen. For the latter 4 hardware counters,
+ * L3C_DATSRC_TYPE1 is chosen.
+ */
+ reg = L3C_DATSRC_TYPE + (idx / 4) * 4;
+ reg_idx = idx % 4;
+ shift = 8 * reg_idx;
+
+ val = readl(l3c_pmu->base + reg);
+ val &= ~(L3C_DATSRC_MASK << shift);
+ val |= ds_cfg << shift;
+ writel(val, l3c_pmu->base + reg);
+}
+
+static void hisi_l3c_pmu_config_ds(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 ds_cfg = hisi_get_datasrc_cfg(event);
+ u32 ds_skt = hisi_get_datasrc_skt(event);
+
+ if (ds_cfg)
+ hisi_l3c_pmu_write_ds(event, ds_cfg);
+
+ if (ds_skt) {
+ u32 val;
+
+ val = readl(l3c_pmu->base + L3C_DATSRC_CTRL);
+ val |= L3C_DATSRC_SKT_EN;
+ writel(val, l3c_pmu->base + L3C_DATSRC_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_clear_ds(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 ds_cfg = hisi_get_datasrc_cfg(event);
+ u32 ds_skt = hisi_get_datasrc_skt(event);
+
+ if (ds_cfg)
+ hisi_l3c_pmu_write_ds(event, L3C_DATSRC_NONE);
+
+ if (ds_skt) {
+ u32 val;
+
+ val = readl(l3c_pmu->base + L3C_DATSRC_CTRL);
+ val &= ~L3C_DATSRC_SKT_EN;
+ writel(val, l3c_pmu->base + L3C_DATSRC_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_config_core_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 core = hisi_get_tt_core(event);
+
+ if (core) {
+ u32 val;
+
+ /* Config and enable core information */
+ writel(core, l3c_pmu->base + L3C_CORE_CTRL);
+ val = readl(l3c_pmu->base + L3C_PERF_CTRL);
+ val |= L3C_CORE_EN;
+ writel(val, l3c_pmu->base + L3C_PERF_CTRL);
+
+ /* Enable core-tracetag statistics */
+ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
+ val |= L3C_TRACETAG_CORE_EN;
+ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_clear_core_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu);
+ u32 core = hisi_get_tt_core(event);
+
+ if (core) {
+ u32 val;
+
+ /* Clear core information */
+ writel(L3C_COER_NONE, l3c_pmu->base + L3C_CORE_CTRL);
+ val = readl(l3c_pmu->base + L3C_PERF_CTRL);
+ val &= ~L3C_CORE_EN;
+ writel(val, l3c_pmu->base + L3C_PERF_CTRL);
+
+ /* Disable core-tracetag statistics */
+ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL);
+ val &= ~L3C_TRACETAG_CORE_EN;
+ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL);
+ }
+}
+
+static void hisi_l3c_pmu_enable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_l3c_pmu_config_req_tracetag(event);
+ hisi_l3c_pmu_config_core_tracetag(event);
+ hisi_l3c_pmu_config_ds(event);
+ }
+}
+
+static void hisi_l3c_pmu_disable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_l3c_pmu_clear_ds(event);
+ hisi_l3c_pmu_clear_core_tracetag(event);
+ hisi_l3c_pmu_clear_req_tracetag(event);
+ }
+}
/*
* Select the counter register offset using the counter index
@@ -53,14 +236,12 @@ static u32 hisi_l3c_pmu_get_counter_offset(u32 cntr_idx)
static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu,
struct hw_perf_event *hwc)
{
- /* Read 64-bits and the upper 16 bits are RAZ */
return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
}
static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu,
struct hw_perf_event *hwc, u64 val)
{
- /* Write 64-bits and the upper 16 bits are WI */
writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
}
@@ -169,23 +350,14 @@ static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx)
static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = {
{ "HISI0213", },
- {},
+ { "HISI0214", },
+ {}
};
MODULE_DEVICE_TABLE(acpi, hisi_l3c_pmu_acpi_match);
static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *l3c_pmu)
{
- unsigned long long id;
- acpi_status status;
-
- status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
- "_UID", NULL, &id);
- if (ACPI_FAILURE(status))
- return -EINVAL;
-
- l3c_pmu->index_id = id;
-
/*
* Use the SCCL_ID and CCL_ID to identify the L3C PMU, while
* SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
@@ -223,6 +395,20 @@ static const struct attribute_group hisi_l3c_pmu_v1_format_group = {
.attrs = hisi_l3c_pmu_v1_format_attr,
};
+static struct attribute *hisi_l3c_pmu_v2_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ HISI_PMU_FORMAT_ATTR(tt_core, "config1:0-7"),
+ HISI_PMU_FORMAT_ATTR(tt_req, "config1:8-10"),
+ HISI_PMU_FORMAT_ATTR(datasrc_cfg, "config1:11-15"),
+ HISI_PMU_FORMAT_ATTR(datasrc_skt, "config1:16"),
+ NULL
+};
+
+static const struct attribute_group hisi_l3c_pmu_v2_format_group = {
+ .name = "format",
+ .attrs = hisi_l3c_pmu_v2_format_attr,
+};
+
static struct attribute *hisi_l3c_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00),
HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01),
@@ -245,6 +431,19 @@ static const struct attribute_group hisi_l3c_pmu_v1_events_group = {
.attrs = hisi_l3c_pmu_v1_events_attr,
};
+static struct attribute *hisi_l3c_pmu_v2_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(l3c_hit, 0x48),
+ HISI_PMU_EVENT_ATTR(cycles, 0x7f),
+ HISI_PMU_EVENT_ATTR(l3c_ref, 0xb8),
+ HISI_PMU_EVENT_ATTR(dat_access, 0xb9),
+ NULL
+};
+
+static const struct attribute_group hisi_l3c_pmu_v2_events_group = {
+ .name = "events",
+ .attrs = hisi_l3c_pmu_v2_events_attr,
+};
+
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
static struct attribute *hisi_l3c_pmu_cpumask_attrs[] = {
@@ -276,6 +475,14 @@ static const struct attribute_group *hisi_l3c_pmu_v1_attr_groups[] = {
NULL,
};
+static const struct attribute_group *hisi_l3c_pmu_v2_attr_groups[] = {
+ &hisi_l3c_pmu_v2_format_group,
+ &hisi_l3c_pmu_v2_events_group,
+ &hisi_l3c_pmu_cpumask_attr_group,
+ &hisi_l3c_pmu_identifier_group,
+ NULL
+};
+
static const struct hisi_uncore_ops hisi_uncore_l3c_ops = {
.write_evtype = hisi_l3c_pmu_write_evtype,
.get_event_idx = hisi_uncore_pmu_get_event_idx,
@@ -289,6 +496,8 @@ static const struct hisi_uncore_ops hisi_uncore_l3c_ops = {
.read_counter = hisi_l3c_pmu_read_counter,
.get_int_status = hisi_l3c_pmu_get_int_status,
.clear_int_status = hisi_l3c_pmu_clear_int_status,
+ .enable_filter = hisi_l3c_pmu_enable_filter,
+ .disable_filter = hisi_l3c_pmu_disable_filter,
};
static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
@@ -304,12 +513,20 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
+ if (l3c_pmu->identifier >= HISI_PMU_V2) {
+ l3c_pmu->counter_bits = 64;
+ l3c_pmu->check_event = L3C_V2_NR_EVENTS;
+ l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v2_attr_groups;
+ } else {
+ l3c_pmu->counter_bits = 48;
+ l3c_pmu->check_event = L3C_V1_NR_EVENTS;
+ l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v1_attr_groups;
+ }
+
l3c_pmu->num_counters = L3C_NR_COUNTERS;
- l3c_pmu->counter_bits = 48;
l3c_pmu->ops = &hisi_uncore_l3c_ops;
l3c_pmu->dev = &pdev->dev;
l3c_pmu->on_cpu = -1;
- l3c_pmu->check_event = L3C_V1_NR_EVENTS;
return 0;
}
@@ -337,8 +554,12 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
return ret;
}
+ /*
+ * CCL_ID is used to identify the L3C in the same SCCL which was
+ * used _UID by mistake.
+ */
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
- l3c_pmu->sccl_id, l3c_pmu->index_id);
+ l3c_pmu->sccl_id, l3c_pmu->ccl_id);
l3c_pmu->pmu = (struct pmu) {
.name = name,
.module = THIS_MODULE,
@@ -351,7 +572,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_l3c_pmu_v1_attr_groups,
+ .attr_groups = l3c_pmu->pmu_events.attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 53ac9f062c0f..c0f221e39aff 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -24,7 +24,7 @@
#include "hisi_uncore_pmu.h"
#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff)
-#define HISI_MAX_PERIOD(nr) (BIT_ULL(nr) - 1)
+#define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0))
/*
* PMU format attributes
@@ -248,6 +248,9 @@ static void hisi_uncore_pmu_enable_event(struct perf_event *event)
hisi_pmu->ops->write_evtype(hisi_pmu, hwc->idx,
HISI_GET_EVENTID(event));
+ if (hisi_pmu->ops->enable_filter)
+ hisi_pmu->ops->enable_filter(event);
+
hisi_pmu->ops->enable_counter_int(hisi_pmu, hwc);
hisi_pmu->ops->enable_counter(hisi_pmu, hwc);
}
@@ -262,6 +265,9 @@ static void hisi_uncore_pmu_disable_event(struct perf_event *event)
hisi_pmu->ops->disable_counter(hisi_pmu, hwc);
hisi_pmu->ops->disable_counter_int(hisi_pmu, hwc);
+
+ if (hisi_pmu->ops->disable_filter)
+ hisi_pmu->ops->disable_filter(event);
}
void hisi_uncore_pmu_set_event_period(struct perf_event *event)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 3336723e8cf6..1147dbd25344 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -14,6 +14,7 @@
#ifndef __HISI_UNCORE_PMU_H__
#define __HISI_UNCORE_PMU_H__
+#include <linux/bitfield.h>
#include <linux/cpumask.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -25,6 +26,7 @@
#undef pr_fmt
#define pr_fmt(fmt) "hisi_pmu: " fmt
+#define HISI_PMU_V2 0x30
#define HISI_MAX_COUNTERS 0x10
#define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu))
@@ -38,6 +40,12 @@
#define HISI_PMU_EVENT_ATTR(_name, _config) \
HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config)
+#define HISI_PMU_EVENT_ATTR_EXTRACTOR(name, config, hi, lo) \
+ static inline u32 hisi_get_##name(struct perf_event *event) \
+ { \
+ return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config); \
+ }
+
struct hisi_pmu;
struct hisi_uncore_ops {
@@ -53,11 +61,14 @@ struct hisi_uncore_ops {
void (*stop_counters)(struct hisi_pmu *);
u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
+ void (*enable_filter)(struct perf_event *event);
+ void (*disable_filter)(struct perf_event *event);
};
struct hisi_pmu_hwevents {
struct perf_event *hw_events[HISI_MAX_COUNTERS];
DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
+ const struct attribute_group **attr_groups;
};
/* Generic pmu struct for different pmu types */
--
2.27.0

View File

@ -0,0 +1,340 @@
From 77e91e65e043b7cec81e193b005ead3183316bb6 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:06 +0800
Subject: [PATCH 17/55] drivers/perf: hisi: Add new functions for HHA PMU
mainline inclusion
from mainline-v5.12-rc3
commit 932f6a99f9b0c6b7039a5e2ce961009a8dc8c07c
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=932f6a99f9b0c6b7039a5e2ce961009a8dc8c07c
------------------------------------------------------------------------
On HiSilicon Hip09 platform, some new functions are also supported on
HHA PMU.
* tracetag_en: it is the abbreviation of tracetag enable and allows user
to count events according to tt_req or tt_core set in L3C PMU.
* datasrc_skt: it is the abbreviation of data source from another
socket and it is used in the multi-chips. It's the same as L3C PMU.
* srcid_cmd & srcid_msk: pair of the fields are used to filter
statistics that come from the specific CCL/ICL by the configuration.
These are the abbreviation of source ID command and mask. The source
ID is 11-bit and detailed descriptions are documented in
Documentation/admin-guide/perf/hisi-pmu.rst.
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-6-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 203 +++++++++++++++++--
1 file changed, 188 insertions(+), 15 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 7941900ea667..a7e1749fc3e4 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -28,19 +28,136 @@
#define HHA_VERSION 0x1cf0
#define HHA_PERF_CTRL 0x1E00
#define HHA_EVENT_CTRL 0x1E04
+#define HHA_SRCID_CTRL 0x1E08
+#define HHA_DATSRC_CTRL 0x1BF0
#define HHA_EVENT_TYPE0 0x1E80
/*
- * Each counter is 48-bits and [48:63] are reserved
- * which are Read-As-Zero and Writes-Ignored.
+ * If the HW version only supports a 48-bit counter, then
+ * bits [63:48] are reserved, which are Read-As-Zero and
+ * Writes-Ignored.
*/
#define HHA_CNT0_LOWER 0x1F00
-/* HHA has 16-counters */
+/* HHA PMU v1 has 16 counters and v2 only has 8 counters */
#define HHA_V1_NR_COUNTERS 0x10
+#define HHA_V2_NR_COUNTERS 0x8
#define HHA_PERF_CTRL_EN 0x1
+#define HHA_TRACETAG_EN BIT(31)
+#define HHA_SRCID_EN BIT(2)
+#define HHA_SRCID_CMD_SHIFT 6
+#define HHA_SRCID_MSK_SHIFT 20
+#define HHA_SRCID_CMD GENMASK(16, 6)
+#define HHA_SRCID_MSK GENMASK(30, 20)
+#define HHA_DATSRC_SKT_EN BIT(23)
#define HHA_EVTYPE_NONE 0xff
#define HHA_V1_NR_EVENT 0x65
+#define HHA_V2_NR_EVENT 0xCE
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 10, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 21, 11);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 22, 22);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 23, 23);
+
+static void hisi_hha_pmu_enable_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_en = hisi_get_tracetag_en(event);
+
+ if (tt_en) {
+ u32 val;
+
+ val = readl(hha_pmu->base + HHA_SRCID_CTRL);
+ val |= HHA_TRACETAG_EN;
+ writel(val, hha_pmu->base + HHA_SRCID_CTRL);
+ }
+}
+
+static void hisi_hha_pmu_clear_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 val;
+
+ val = readl(hha_pmu->base + HHA_SRCID_CTRL);
+ val &= ~HHA_TRACETAG_EN;
+ writel(val, hha_pmu->base + HHA_SRCID_CTRL);
+}
+
+static void hisi_hha_pmu_config_ds(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 ds_skt = hisi_get_datasrc_skt(event);
+
+ if (ds_skt) {
+ u32 val;
+
+ val = readl(hha_pmu->base + HHA_DATSRC_CTRL);
+ val |= HHA_DATSRC_SKT_EN;
+ writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL);
+ }
+}
+
+static void hisi_hha_pmu_clear_ds(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 ds_skt = hisi_get_datasrc_skt(event);
+
+ if (ds_skt) {
+ u32 val;
+
+ val = readl(hha_pmu->base + HHA_DATSRC_CTRL);
+ val &= ~HHA_DATSRC_SKT_EN;
+ writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL);
+ }
+}
+
+static void hisi_hha_pmu_config_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd) {
+ u32 val, msk;
+
+ msk = hisi_get_srcid_msk(event);
+ val = readl(hha_pmu->base + HHA_SRCID_CTRL);
+ val |= HHA_SRCID_EN | (cmd << HHA_SRCID_CMD_SHIFT) |
+ (msk << HHA_SRCID_MSK_SHIFT);
+ writel(val, hha_pmu->base + HHA_SRCID_CTRL);
+ }
+}
+
+static void hisi_hha_pmu_disable_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd) {
+ u32 val;
+
+ val = readl(hha_pmu->base + HHA_SRCID_CTRL);
+ val &= ~(HHA_SRCID_EN | HHA_SRCID_MSK | HHA_SRCID_CMD);
+ writel(val, hha_pmu->base + HHA_SRCID_CTRL);
+ }
+}
+
+static void hisi_hha_pmu_enable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_hha_pmu_enable_tracetag(event);
+ hisi_hha_pmu_config_ds(event);
+ hisi_hha_pmu_config_srcid(event);
+ }
+}
+
+static void hisi_hha_pmu_disable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_hha_pmu_disable_srcid(event);
+ hisi_hha_pmu_clear_ds(event);
+ hisi_hha_pmu_clear_tracetag(event);
+ }
+}
/*
* Select the counter register offset using the counter index
@@ -170,7 +287,8 @@ static void hisi_hha_pmu_clear_int_status(struct hisi_pmu *hha_pmu, int idx)
static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = {
{ "HISI0243", },
- {},
+ { "HISI0244", },
+ {}
};
MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match);
@@ -180,13 +298,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
unsigned long long id;
acpi_status status;
- status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
- "_UID", NULL, &id);
- if (ACPI_FAILURE(status))
- return -EINVAL;
-
- hha_pmu->index_id = id;
-
/*
* Use SCCL_ID and UID to identify the HHA PMU, while
* SCCL_ID is in MPIDR[aff2].
@@ -196,6 +307,22 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
dev_err(&pdev->dev, "Can not read hha sccl-id!\n");
return -EINVAL;
}
+
+ /*
+ * Early versions of BIOS support _UID by mistake, so we support
+ * both "hisilicon, idx-id" as preference, if available.
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
+ &hha_pmu->index_id)) {
+ status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
+ "_UID", NULL, &id);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&pdev->dev, "Cannot read idx-id!\n");
+ return -EINVAL;
+ }
+
+ hha_pmu->index_id = id;
+ }
/* HHA PMUs only share the same SCCL */
hha_pmu->ccl_id = -1;
@@ -220,6 +347,20 @@ static const struct attribute_group hisi_hha_pmu_v1_format_group = {
.attrs = hisi_hha_pmu_v1_format_attr,
};
+static struct attribute *hisi_hha_pmu_v2_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:0-10"),
+ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:11-21"),
+ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:22"),
+ HISI_PMU_FORMAT_ATTR(datasrc_skt, "config1:23"),
+ NULL
+};
+
+static const struct attribute_group hisi_hha_pmu_v2_format_group = {
+ .name = "format",
+ .attrs = hisi_hha_pmu_v2_format_attr,
+};
+
static struct attribute *hisi_hha_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00),
HISI_PMU_EVENT_ATTR(rx_outer, 0x01),
@@ -255,6 +396,20 @@ static const struct attribute_group hisi_hha_pmu_v1_events_group = {
.attrs = hisi_hha_pmu_v1_events_attr,
};
+static struct attribute *hisi_hha_pmu_v2_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00),
+ HISI_PMU_EVENT_ATTR(rx_outer, 0x01),
+ HISI_PMU_EVENT_ATTR(rx_sccl, 0x02),
+ HISI_PMU_EVENT_ATTR(hha_retry, 0x2e),
+ HISI_PMU_EVENT_ATTR(cycles, 0x55),
+ NULL
+};
+
+static const struct attribute_group hisi_hha_pmu_v2_events_group = {
+ .name = "events",
+ .attrs = hisi_hha_pmu_v2_events_attr,
+};
+
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
static struct attribute *hisi_hha_pmu_cpumask_attrs[] = {
@@ -286,6 +441,14 @@ static const struct attribute_group *hisi_hha_pmu_v1_attr_groups[] = {
NULL,
};
+static const struct attribute_group *hisi_hha_pmu_v2_attr_groups[] = {
+ &hisi_hha_pmu_v2_format_group,
+ &hisi_hha_pmu_v2_events_group,
+ &hisi_hha_pmu_cpumask_attr_group,
+ &hisi_hha_pmu_identifier_group,
+ NULL
+};
+
static const struct hisi_uncore_ops hisi_uncore_hha_ops = {
.write_evtype = hisi_hha_pmu_write_evtype,
.get_event_idx = hisi_uncore_pmu_get_event_idx,
@@ -299,6 +462,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = {
.read_counter = hisi_hha_pmu_read_counter,
.get_int_status = hisi_hha_pmu_get_int_status,
.clear_int_status = hisi_hha_pmu_clear_int_status,
+ .enable_filter = hisi_hha_pmu_enable_filter,
+ .disable_filter = hisi_hha_pmu_disable_filter,
};
static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
@@ -314,12 +479,20 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
- hha_pmu->num_counters = HHA_V1_NR_COUNTERS;
- hha_pmu->counter_bits = 48;
+ if (hha_pmu->identifier >= HISI_PMU_V2) {
+ hha_pmu->counter_bits = 64;
+ hha_pmu->check_event = HHA_V2_NR_EVENT;
+ hha_pmu->pmu_events.attr_groups = hisi_hha_pmu_v2_attr_groups;
+ hha_pmu->num_counters = HHA_V2_NR_COUNTERS;
+ } else {
+ hha_pmu->counter_bits = 48;
+ hha_pmu->check_event = HHA_V1_NR_EVENT;
+ hha_pmu->pmu_events.attr_groups = hisi_hha_pmu_v1_attr_groups;
+ hha_pmu->num_counters = HHA_V1_NR_COUNTERS;
+ }
hha_pmu->ops = &hisi_uncore_hha_ops;
hha_pmu->dev = &pdev->dev;
hha_pmu->on_cpu = -1;
- hha_pmu->check_event = HHA_V1_NR_EVENT;
return 0;
}
@@ -361,7 +534,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_hha_pmu_v1_attr_groups,
+ .attr_groups = hha_pmu->pmu_events.attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
--
2.27.0

View File

@ -0,0 +1,400 @@
From c00401895e634812a41f81e20223244782e503a8 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:07 +0800
Subject: [PATCH 18/55] drivers/perf: hisi: Update DDRC PMU for programmable
counter
mainline inclusion
from mainline-v5.12-rc3
commit cce03e702c9f26a43b16c51bf03029911feab692
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cce03e702c9f26a43b16c51bf03029911feab692
------------------------------------------------------------------------
DDRC PMU's events are useful for performance profiling, but the events
are limited and counter is fixed. On HiSilicon Hip09 platform, PMU
counters are the programmable and more events are supported. Let's
add the DDRC PMU v2 driver.
Bandwidth events are exposed directly in driver and some more events
will listed in JSON file later.
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-7-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 207 ++++++++++++++++--
drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 +
2 files changed, 196 insertions(+), 13 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 1d1c8e9f417e..af5f8c16eab1 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -21,7 +21,7 @@
#include "hisi_uncore_pmu.h"
-/* DDRC register definition */
+/* DDRC register definition in v1 */
#define DDRC_PERF_CTRL 0x010
#define DDRC_FLUX_WR 0x380
#define DDRC_FLUX_RD 0x384
@@ -37,13 +37,24 @@
#define DDRC_INT_CLEAR 0x6d0
#define DDRC_VERSION 0x710
+/* DDRC register definition in v2 */
+#define DDRC_V2_INT_MASK 0x528
+#define DDRC_V2_INT_STATUS 0x52c
+#define DDRC_V2_INT_CLEAR 0x530
+#define DDRC_V2_EVENT_CNT 0xe00
+#define DDRC_V2_EVENT_CTRL 0xe70
+#define DDRC_V2_EVENT_TYPE 0xe74
+#define DDRC_V2_PERF_CTRL 0xeA0
+
/* DDRC has 8-counters */
#define DDRC_NR_COUNTERS 0x8
#define DDRC_V1_PERF_CTRL_EN 0x2
+#define DDRC_V2_PERF_CTRL_EN 0x1
#define DDRC_V1_NR_EVENTS 0x7
+#define DDRC_V2_NR_EVENTS 0x90
/*
- * For DDRC PMU, there are eight-events and every event has been mapped
+ * For PMU v1, there are eight-events and every event has been mapped
* to fixed-purpose counters which register offset is not consistent.
* Therefore there is no write event type and we assume that event
* code (0 to 7) is equal to counter index in PMU driver.
@@ -65,6 +76,11 @@ static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx)
return ddrc_reg_off[cntr_idx];
}
+static u32 hisi_ddrc_pmu_v2_get_counter_offset(int cntr_idx)
+{
+ return DDRC_V2_EVENT_CNT + cntr_idx * 8;
+}
+
static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc)
{
@@ -79,13 +95,34 @@ static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu,
ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx));
}
+static u64 hisi_ddrc_pmu_v2_read_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(ddrc_pmu->base +
+ hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx));
+}
+
+static void hisi_ddrc_pmu_v2_write_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val,
+ ddrc_pmu->base + hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx));
+}
+
/*
- * For DDRC PMU, event has been mapped to fixed-purpose counter by hardware,
- * so there is no need to write event type.
+ * For DDRC PMU v1, event has been mapped to fixed-purpose counter by hardware,
+ * so there is no need to write event type, while it is programmable counter in
+ * PMU v2.
*/
static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
u32 type)
{
+ u32 offset;
+
+ if (hha_pmu->identifier >= HISI_PMU_V2) {
+ offset = DDRC_V2_EVENT_TYPE + 4 * idx;
+ writel(type, hha_pmu->base + offset);
+ }
}
static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu)
@@ -146,6 +183,49 @@ static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event)
return idx;
}
+static int hisi_ddrc_pmu_v2_get_event_idx(struct perf_event *event)
+{
+ return hisi_uncore_pmu_get_event_idx(event);
+}
+
+static void hisi_ddrc_pmu_v2_start_counters(struct hisi_pmu *ddrc_pmu)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+ val |= DDRC_V2_PERF_CTRL_EN;
+ writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+}
+
+static void hisi_ddrc_pmu_v2_stop_counters(struct hisi_pmu *ddrc_pmu)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+ val &= ~DDRC_V2_PERF_CTRL_EN;
+ writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL);
+}
+
+static void hisi_ddrc_pmu_v2_enable_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
+ val |= 1 << hwc->idx;
+ writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
+}
+
+static void hisi_ddrc_pmu_v2_disable_counter(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
+ val &= ~(1 << hwc->idx);
+ writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL);
+}
+
static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu,
struct hw_perf_event *hwc)
{
@@ -153,7 +233,7 @@ static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu,
/* Write 0 to enable interrupt */
val = readl(ddrc_pmu->base + DDRC_INT_MASK);
- val &= ~(1 << GET_DDRC_EVENTID(hwc));
+ val &= ~(1 << hwc->idx);
writel(val, ddrc_pmu->base + DDRC_INT_MASK);
}
@@ -164,10 +244,30 @@ static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu,
/* Write 1 to mask interrupt */
val = readl(ddrc_pmu->base + DDRC_INT_MASK);
- val |= (1 << GET_DDRC_EVENTID(hwc));
+ val |= 1 << hwc->idx;
writel(val, ddrc_pmu->base + DDRC_INT_MASK);
}
+static void hisi_ddrc_pmu_v2_enable_counter_int(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK);
+ val &= ~(1 << hwc->idx);
+ writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK);
+}
+
+static void hisi_ddrc_pmu_v2_disable_counter_int(struct hisi_pmu *ddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK);
+ val |= 1 << hwc->idx;
+ writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK);
+}
+
static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu)
{
return readl(ddrc_pmu->base + DDRC_INT_STATUS);
@@ -179,9 +279,21 @@ static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu,
writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR);
}
+static u32 hisi_ddrc_pmu_v2_get_int_status(struct hisi_pmu *ddrc_pmu)
+{
+ return readl(ddrc_pmu->base + DDRC_V2_INT_STATUS);
+}
+
+static void hisi_ddrc_pmu_v2_clear_int_status(struct hisi_pmu *ddrc_pmu,
+ int idx)
+{
+ writel(1 << idx, ddrc_pmu->base + DDRC_V2_INT_CLEAR);
+}
+
static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
{ "HISI0233", },
- {},
+ { "HISI0234", },
+ {}
};
MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match);
@@ -213,6 +325,13 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
}
ddrc_pmu->identifier = readl(ddrc_pmu->base + DDRC_VERSION);
+ if (ddrc_pmu->identifier >= HISI_PMU_V2) {
+ if (device_property_read_u32(&pdev->dev, "hisilicon,sub-id",
+ &ddrc_pmu->sub_id)) {
+ dev_err(&pdev->dev, "Can not read sub-id!\n");
+ return -EINVAL;
+ }
+ }
return 0;
}
@@ -227,6 +346,16 @@ static const struct attribute_group hisi_ddrc_pmu_v1_format_group = {
.attrs = hisi_ddrc_pmu_v1_format_attr,
};
+static struct attribute *hisi_ddrc_pmu_v2_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ NULL
+};
+
+static const struct attribute_group hisi_ddrc_pmu_v2_format_group = {
+ .name = "format",
+ .attrs = hisi_ddrc_pmu_v2_format_attr,
+};
+
static struct attribute *hisi_ddrc_pmu_v1_events_attr[] = {
HISI_PMU_EVENT_ATTR(flux_wr, 0x00),
HISI_PMU_EVENT_ATTR(flux_rd, 0x01),
@@ -244,6 +373,18 @@ static const struct attribute_group hisi_ddrc_pmu_v1_events_group = {
.attrs = hisi_ddrc_pmu_v1_events_attr,
};
+static struct attribute *hisi_ddrc_pmu_v2_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(cycles, 0x00),
+ HISI_PMU_EVENT_ATTR(flux_wr, 0x83),
+ HISI_PMU_EVENT_ATTR(flux_rd, 0x84),
+ NULL
+};
+
+static const struct attribute_group hisi_ddrc_pmu_v2_events_group = {
+ .name = "events",
+ .attrs = hisi_ddrc_pmu_v2_events_attr,
+};
+
static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
static struct attribute *hisi_ddrc_pmu_cpumask_attrs[] = {
@@ -275,6 +416,14 @@ static const struct attribute_group *hisi_ddrc_pmu_v1_attr_groups[] = {
NULL,
};
+static const struct attribute_group *hisi_ddrc_pmu_v2_attr_groups[] = {
+ &hisi_ddrc_pmu_v2_format_group,
+ &hisi_ddrc_pmu_v2_events_group,
+ &hisi_ddrc_pmu_cpumask_attr_group,
+ &hisi_ddrc_pmu_identifier_group,
+ NULL
+};
+
static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = {
.write_evtype = hisi_ddrc_pmu_write_evtype,
.get_event_idx = hisi_ddrc_pmu_v1_get_event_idx,
@@ -290,6 +439,21 @@ static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = {
.clear_int_status = hisi_ddrc_pmu_v1_clear_int_status,
};
+static const struct hisi_uncore_ops hisi_uncore_ddrc_v2_ops = {
+ .write_evtype = hisi_ddrc_pmu_write_evtype,
+ .get_event_idx = hisi_ddrc_pmu_v2_get_event_idx,
+ .start_counters = hisi_ddrc_pmu_v2_start_counters,
+ .stop_counters = hisi_ddrc_pmu_v2_stop_counters,
+ .enable_counter = hisi_ddrc_pmu_v2_enable_counter,
+ .disable_counter = hisi_ddrc_pmu_v2_disable_counter,
+ .enable_counter_int = hisi_ddrc_pmu_v2_enable_counter_int,
+ .disable_counter_int = hisi_ddrc_pmu_v2_disable_counter_int,
+ .write_counter = hisi_ddrc_pmu_v2_write_counter,
+ .read_counter = hisi_ddrc_pmu_v2_read_counter,
+ .get_int_status = hisi_ddrc_pmu_v2_get_int_status,
+ .clear_int_status = hisi_ddrc_pmu_v2_clear_int_status,
+};
+
static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
struct hisi_pmu *ddrc_pmu)
{
@@ -303,12 +467,21 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
if (ret)
return ret;
+ if (ddrc_pmu->identifier >= HISI_PMU_V2) {
+ ddrc_pmu->counter_bits = 48;
+ ddrc_pmu->check_event = DDRC_V2_NR_EVENTS;
+ ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v2_attr_groups;
+ ddrc_pmu->ops = &hisi_uncore_ddrc_v2_ops;
+ } else {
+ ddrc_pmu->counter_bits = 32;
+ ddrc_pmu->check_event = DDRC_V1_NR_EVENTS;
+ ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v1_attr_groups;
+ ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops;
+ }
+
ddrc_pmu->num_counters = DDRC_NR_COUNTERS;
- ddrc_pmu->counter_bits = 32;
- ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops;
ddrc_pmu->dev = &pdev->dev;
ddrc_pmu->on_cpu = -1;
- ddrc_pmu->check_event = DDRC_V1_NR_EVENTS;
return 0;
}
@@ -336,8 +509,16 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
return ret;
}
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_ddrc%u",
- ddrc_pmu->sccl_id, ddrc_pmu->index_id);
+ if (ddrc_pmu->identifier >= HISI_PMU_V2)
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "hisi_sccl%u_ddrc%u_%u",
+ ddrc_pmu->sccl_id, ddrc_pmu->index_id,
+ ddrc_pmu->sub_id);
+ else
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
+ ddrc_pmu->index_id);
+
ddrc_pmu->pmu = (struct pmu) {
.name = name,
.module = THIS_MODULE,
@@ -350,7 +531,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
- .attr_groups = hisi_ddrc_pmu_v1_attr_groups,
+ .attr_groups = ddrc_pmu->pmu_events.attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 1147dbd25344..de6aa17a1355 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -88,6 +88,8 @@ struct hisi_pmu {
void __iomem *base;
/* the ID of the PMU modules */
u32 index_id;
+ /* For DDRC PMU v2: each DDRC has more than one DMC */
+ u32 sub_id;
int num_counters;
int counter_bits;
/* check event code range */
--
2.27.0

View File

@ -0,0 +1,618 @@
From 16c054f4640b9f7c21bb784ac54e1ea32ac65df0 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:08 +0800
Subject: [PATCH 19/55] drivers/perf: hisi: Add support for HiSilicon SLLC PMU
driver
mainline inclusion
from mainline-v5.12-rc3
commit 3bf30882c3c7b6e376d9d6d04082c9aa2d2ac30a
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3bf30882c3c7b6e376d9d6d04082c9aa2d2ac30a
------------------------------------------------------------------------
HiSilicon's Hip09 is comprised by multi-dies that can be connected by SLLC
module (Skyros Link Layer Controller), its has separate PMU registers which
the driver can program it freely and interrupt is supported to handle
counter overflow. Let's support its driver under the framework of HiSilicon
uncore PMU driver.
SLLC PMU supports the following filter functions:
* tracetag_en: allows user to count data according to tt_req or
tt_core set in L3C PMU.
* srcid_cmd & srcid_msk: allows user to filter statistics that come from
specific CCL/ICL by configuration source ID.
* tgtid_hi & tgtid_lo: it also supports event statistics that these
operations will go to the CCL/ICL by configuration target ID or
target ID range. It's the same as source ID with 11-bit width in
the SoC. More introduction is added in documentation:
Documentation/admin-guide/perf/hisi-pmu.rst
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-8-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/hisilicon/Makefile
---
drivers/perf/hisilicon/Makefile | 4 +-
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 530 ++++++++++++++++++
include/linux/cpuhotplug.h | 1 +
3 files changed, 534 insertions(+), 1 deletion(-)
create mode 100644 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 2621d51ae87a..6600a9d45dd8 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1 +1,3 @@
-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
+ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
new file mode 100644
index 000000000000..46be312fa126
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SLLC uncore Hardware event counters support
+ *
+ * Copyright (C) 2020 Hisilicon Limited
+ * Author: Shaokun Zhang <zhangshaokun@hisilicon.com>
+ *
+ * This code is based on the uncore PMUs like arm-cci and arm-ccn.
+ */
+#include <linux/acpi.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* SLLC register definition */
+#define SLLC_INT_MASK 0x0814
+#define SLLC_INT_STATUS 0x0818
+#define SLLC_INT_CLEAR 0x081c
+#define SLLC_PERF_CTRL 0x1c00
+#define SLLC_SRCID_CTRL 0x1c04
+#define SLLC_TGTID_CTRL 0x1c08
+#define SLLC_EVENT_CTRL 0x1c14
+#define SLLC_EVENT_TYPE0 0x1c18
+#define SLLC_VERSION 0x1cf0
+#define SLLC_EVENT_CNT0_L 0x1d00
+
+#define SLLC_EVTYPE_MASK 0xff
+#define SLLC_PERF_CTRL_EN BIT(0)
+#define SLLC_FILT_EN BIT(1)
+#define SLLC_TRACETAG_EN BIT(2)
+#define SLLC_SRCID_EN BIT(4)
+#define SLLC_SRCID_NONE 0x0
+#define SLLC_TGTID_EN BIT(5)
+#define SLLC_TGTID_NONE 0x0
+#define SLLC_TGTID_MIN_SHIFT 1
+#define SLLC_TGTID_MAX_SHIFT 12
+#define SLLC_SRCID_CMD_SHIFT 1
+#define SLLC_SRCID_MSK_SHIFT 12
+#define SLLC_NR_EVENTS 0x80
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_max, config1, 21, 11);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
+
+static bool tgtid_is_valid(u32 max, u32 min)
+{
+ return max > 0 && max >= min;
+}
+
+static void hisi_sllc_pmu_enable_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_en = hisi_get_tracetag_en(event);
+
+ if (tt_en) {
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val |= SLLC_TRACETAG_EN | SLLC_FILT_EN;
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_disable_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_en = hisi_get_tracetag_en(event);
+
+ if (tt_en) {
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val &= ~(SLLC_TRACETAG_EN | SLLC_FILT_EN);
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_config_tgtid(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 min = hisi_get_tgtid_min(event);
+ u32 max = hisi_get_tgtid_max(event);
+
+ if (tgtid_is_valid(max, min)) {
+ u32 val = (max << SLLC_TGTID_MAX_SHIFT) | (min << SLLC_TGTID_MIN_SHIFT);
+
+ writel(val, sllc_pmu->base + SLLC_TGTID_CTRL);
+ /* Enable the tgtid */
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val |= SLLC_TGTID_EN | SLLC_FILT_EN;
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_clear_tgtid(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 min = hisi_get_tgtid_min(event);
+ u32 max = hisi_get_tgtid_max(event);
+
+ if (tgtid_is_valid(max, min)) {
+ u32 val;
+
+ writel(SLLC_TGTID_NONE, sllc_pmu->base + SLLC_TGTID_CTRL);
+ /* Disable the tgtid */
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val &= ~(SLLC_TGTID_EN | SLLC_FILT_EN);
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_config_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd) {
+ u32 val, msk;
+
+ msk = hisi_get_srcid_msk(event);
+ val = (cmd << SLLC_SRCID_CMD_SHIFT) | (msk << SLLC_SRCID_MSK_SHIFT);
+ writel(val, sllc_pmu->base + SLLC_SRCID_CTRL);
+ /* Enable the srcid */
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val |= SLLC_SRCID_EN | SLLC_FILT_EN;
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_clear_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd) {
+ u32 val;
+
+ writel(SLLC_SRCID_NONE, sllc_pmu->base + SLLC_SRCID_CTRL);
+ /* Disable the srcid */
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val &= ~(SLLC_SRCID_EN | SLLC_FILT_EN);
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+ }
+}
+
+static void hisi_sllc_pmu_enable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_sllc_pmu_enable_tracetag(event);
+ hisi_sllc_pmu_config_srcid(event);
+ hisi_sllc_pmu_config_tgtid(event);
+ }
+}
+
+static void hisi_sllc_pmu_clear_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_sllc_pmu_disable_tracetag(event);
+ hisi_sllc_pmu_clear_srcid(event);
+ hisi_sllc_pmu_clear_tgtid(event);
+ }
+}
+
+static u32 hisi_sllc_pmu_get_counter_offset(int idx)
+{
+ return (SLLC_EVENT_CNT0_L + idx * 8);
+}
+
+static u64 hisi_sllc_pmu_read_counter(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(sllc_pmu->base +
+ hisi_sllc_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_sllc_pmu_write_counter(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val, sllc_pmu->base +
+ hisi_sllc_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx,
+ u32 type)
+{
+ u32 reg, reg_idx, shift, val;
+
+ /*
+ * Select the appropriate event select register(SLLC_EVENT_TYPE0/1).
+ * There are 2 event select registers for the 8 hardware counters.
+ * Event code is 8-bits and for the former 4 hardware counters,
+ * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
+ * SLLC_EVENT_TYPE1 is chosen.
+ */
+ reg = SLLC_EVENT_TYPE0 + (idx / 4) * 4;
+ reg_idx = idx % 4;
+ shift = 8 * reg_idx;
+
+ /* Write event code to SLLC_EVENT_TYPEx Register */
+ val = readl(sllc_pmu->base + reg);
+ val &= ~(SLLC_EVTYPE_MASK << shift);
+ val |= (type << shift);
+ writel(val, sllc_pmu->base + reg);
+}
+
+static void hisi_sllc_pmu_start_counters(struct hisi_pmu *sllc_pmu)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val |= SLLC_PERF_CTRL_EN;
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+}
+
+static void hisi_sllc_pmu_stop_counters(struct hisi_pmu *sllc_pmu)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_PERF_CTRL);
+ val &= ~(SLLC_PERF_CTRL_EN);
+ writel(val, sllc_pmu->base + SLLC_PERF_CTRL);
+}
+
+static void hisi_sllc_pmu_enable_counter(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_EVENT_CTRL);
+ val |= 1 << hwc->idx;
+ writel(val, sllc_pmu->base + SLLC_EVENT_CTRL);
+}
+
+static void hisi_sllc_pmu_disable_counter(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_EVENT_CTRL);
+ val &= ~(1 << hwc->idx);
+ writel(val, sllc_pmu->base + SLLC_EVENT_CTRL);
+}
+
+static void hisi_sllc_pmu_enable_counter_int(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_INT_MASK);
+ /* Write 0 to enable interrupt */
+ val &= ~(1 << hwc->idx);
+ writel(val, sllc_pmu->base + SLLC_INT_MASK);
+}
+
+static void hisi_sllc_pmu_disable_counter_int(struct hisi_pmu *sllc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(sllc_pmu->base + SLLC_INT_MASK);
+ /* Write 1 to mask interrupt */
+ val |= 1 << hwc->idx;
+ writel(val, sllc_pmu->base + SLLC_INT_MASK);
+}
+
+static u32 hisi_sllc_pmu_get_int_status(struct hisi_pmu *sllc_pmu)
+{
+ return readl(sllc_pmu->base + SLLC_INT_STATUS);
+}
+
+static void hisi_sllc_pmu_clear_int_status(struct hisi_pmu *sllc_pmu, int idx)
+{
+ writel(1 << idx, sllc_pmu->base + SLLC_INT_CLEAR);
+}
+
+static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = {
+ { "HISI0263", },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match);
+
+static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *sllc_pmu)
+{
+ /*
+ * Use the SCCL_ID and the index ID to identify the SLLC PMU,
+ * while SCCL_ID is from MPIDR_EL1 by CPU.
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &sllc_pmu->sccl_id)) {
+ dev_err(&pdev->dev, "Cannot read sccl-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
+ &sllc_pmu->index_id)) {
+ dev_err(&pdev->dev, "Cannot read idx-id!\n");
+ return -EINVAL;
+ }
+
+ /* SLLC PMUs only share the same SCCL */
+ sllc_pmu->ccl_id = -1;
+
+ sllc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(sllc_pmu->base)) {
+ dev_err(&pdev->dev, "ioremap failed for sllc_pmu resource.\n");
+ return PTR_ERR(sllc_pmu->base);
+ }
+
+ sllc_pmu->identifier = readl(sllc_pmu->base + SLLC_VERSION);
+
+ return 0;
+}
+
+static struct attribute *hisi_sllc_pmu_v2_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ HISI_PMU_FORMAT_ATTR(tgtid_min, "config1:0-10"),
+ HISI_PMU_FORMAT_ATTR(tgtid_max, "config1:11-21"),
+ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:22-32"),
+ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:33-43"),
+ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:44"),
+ NULL
+};
+
+static const struct attribute_group hisi_sllc_pmu_v2_format_group = {
+ .name = "format",
+ .attrs = hisi_sllc_pmu_v2_format_attr,
+};
+
+static struct attribute *hisi_sllc_pmu_v2_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(rx_req, 0x30),
+ HISI_PMU_EVENT_ATTR(rx_data, 0x31),
+ HISI_PMU_EVENT_ATTR(tx_req, 0x34),
+ HISI_PMU_EVENT_ATTR(tx_data, 0x35),
+ HISI_PMU_EVENT_ATTR(cycles, 0x09),
+ NULL
+};
+
+static const struct attribute_group hisi_sllc_pmu_v2_events_group = {
+ .name = "events",
+ .attrs = hisi_sllc_pmu_v2_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_sllc_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL
+};
+
+static const struct attribute_group hisi_sllc_pmu_cpumask_attr_group = {
+ .attrs = hisi_sllc_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_sllc_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_sllc_pmu_identifier_attrs[] = {
+ &hisi_sllc_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_sllc_pmu_identifier_group = {
+ .attrs = hisi_sllc_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_sllc_pmu_v2_attr_groups[] = {
+ &hisi_sllc_pmu_v2_format_group,
+ &hisi_sllc_pmu_v2_events_group,
+ &hisi_sllc_pmu_cpumask_attr_group,
+ &hisi_sllc_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_uncore_ops hisi_uncore_sllc_ops = {
+ .write_evtype = hisi_sllc_pmu_write_evtype,
+ .get_event_idx = hisi_uncore_pmu_get_event_idx,
+ .start_counters = hisi_sllc_pmu_start_counters,
+ .stop_counters = hisi_sllc_pmu_stop_counters,
+ .enable_counter = hisi_sllc_pmu_enable_counter,
+ .disable_counter = hisi_sllc_pmu_disable_counter,
+ .enable_counter_int = hisi_sllc_pmu_enable_counter_int,
+ .disable_counter_int = hisi_sllc_pmu_disable_counter_int,
+ .write_counter = hisi_sllc_pmu_write_counter,
+ .read_counter = hisi_sllc_pmu_read_counter,
+ .get_int_status = hisi_sllc_pmu_get_int_status,
+ .clear_int_status = hisi_sllc_pmu_clear_int_status,
+ .enable_filter = hisi_sllc_pmu_enable_filter,
+ .disable_filter = hisi_sllc_pmu_clear_filter,
+};
+
+static int hisi_sllc_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *sllc_pmu)
+{
+ int ret;
+
+ ret = hisi_sllc_pmu_init_data(pdev, sllc_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(sllc_pmu, pdev);
+ if (ret)
+ return ret;
+
+ sllc_pmu->pmu_events.attr_groups = hisi_sllc_pmu_v2_attr_groups;
+ sllc_pmu->ops = &hisi_uncore_sllc_ops;
+ sllc_pmu->check_event = SLLC_NR_EVENTS;
+ sllc_pmu->counter_bits = 64;
+ sllc_pmu->num_counters = 8;
+ sllc_pmu->dev = &pdev->dev;
+ sllc_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static int hisi_sllc_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *sllc_pmu;
+ char *name;
+ int ret;
+
+ sllc_pmu = devm_kzalloc(&pdev->dev, sizeof(*sllc_pmu), GFP_KERNEL);
+ if (!sllc_pmu)
+ return -ENOMEM;
+
+ ret = hisi_sllc_pmu_dev_probe(pdev, sllc_pmu);
+ if (ret)
+ return ret;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_sllc%u",
+ sllc_pmu->sccl_id, sllc_pmu->index_id);
+ if (!name)
+ return -ENOMEM;
+
+ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
+ &sllc_pmu->node);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
+ return ret;
+ }
+
+ sllc_pmu->pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = sllc_pmu->pmu_events.attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
+ if (ret) {
+ dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
+ cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
+ &sllc_pmu->node);
+ irq_set_affinity_hint(sllc_pmu->irq, NULL);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, sllc_pmu);
+
+ return ret;
+}
+
+static int hisi_sllc_pmu_remove(struct platform_device *pdev)
+{
+ struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&sllc_pmu->pmu);
+ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
+ &sllc_pmu->node);
+ irq_set_affinity_hint(sllc_pmu->irq, NULL);
+
+ return 0;
+}
+
+static struct platform_driver hisi_sllc_pmu_driver = {
+ .driver = {
+ .name = "hisi_sllc_pmu",
+ .acpi_match_table = hisi_sllc_pmu_acpi_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_sllc_pmu_probe,
+ .remove = hisi_sllc_pmu_remove,
+};
+
+static int __init hisi_sllc_pmu_module_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
+ "AP_PERF_ARM_HISI_SLLC_ONLINE",
+ hisi_uncore_pmu_online_cpu,
+ hisi_uncore_pmu_offline_cpu);
+ if (ret) {
+ pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = platform_driver_register(&hisi_sllc_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
+
+ return ret;
+}
+module_init(hisi_sllc_pmu_module_init);
+
+static void __exit hisi_sllc_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_sllc_pmu_driver);
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
+}
+module_exit(hisi_sllc_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon SLLC uncore PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");
+MODULE_AUTHOR("Qi Liu <liuqi115@huawei.com>");
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index d67c0035165c..b5c55a408a30 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -161,6 +161,7 @@ enum cpuhp_state {
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
+ CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
CPUHP_AP_PERF_ARM_L2X0_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE,
--
2.27.0

View File

@ -0,0 +1,584 @@
From 71cf98350d1423660b390740a190ce8a98502c37 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:09 +0800
Subject: [PATCH 20/55] drivers/perf: hisi: Add support for HiSilicon PA PMU
driver
mainline inclusion
from mainline-v5.12-rc3
commit a0ab25cd82eeb68bfa19a4d93a097521af5011b8
category: feature
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a0ab25cd82eeb68bfa19a4d93a097521af5011b8
------------------------------------------------------------------------
On HiSilicon Hip09 platform, there is a PA (Protocol Adapter) module on
each chip SICL (Super I/O Cluster) which incorporates three Hydra interface
and facilitates the cache coherency between the dies on the chip. While PA
uncore PMU model is the same as other Hip09 PMU modules and many PMU events
are supported. Let's support the PMU driver using the HiSilicon uncore PMU
framework.
PA PMU supports the following filter functions:
* tracetag_en: allows user to count events according to tt_req or
tt_core set in L3C PMU. It's the same as other PMUs.
* srcid_cmd & srcid_msk: allows user to filter statistics that come from
specific CCL/ICL by configuration source ID.
* tgtid_cmd & tgtid_msk: it is the similar function to srcid_cmd &
srcid_msk. Both are used to check where the data comes from or go to.
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-9-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/Makefile | 3 +-
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 500 ++++++++++++++++++++
include/linux/cpuhotplug.h | 1 +
3 files changed, 503 insertions(+), 1 deletion(-)
create mode 100644 drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 6600a9d45dd8..7643c9f93e36 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
- hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o
+ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
+ hisi_uncore_pa_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
new file mode 100644
index 000000000000..5517a90552ec
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon PA uncore Hardware event counters support
+ *
+ * Copyright (C) 2020 HiSilicon Limited
+ * Author: Shaokun Zhang <zhangshaokun@hisilicon.com>
+ *
+ * This code is based on the uncore PMUs like arm-cci and arm-ccn.
+ */
+#include <linux/acpi.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* PA register definition */
+#define PA_PERF_CTRL 0x1c00
+#define PA_EVENT_CTRL 0x1c04
+#define PA_TT_CTRL 0x1c08
+#define PA_TGTID_CTRL 0x1c14
+#define PA_SRCID_CTRL 0x1c18
+#define PA_INT_MASK 0x1c70
+#define PA_INT_STATUS 0x1c78
+#define PA_INT_CLEAR 0x1c7c
+#define PA_EVENT_TYPE0 0x1c80
+#define PA_PMU_VERSION 0x1cf0
+#define PA_EVENT_CNT0_L 0x1d00
+
+#define PA_EVTYPE_MASK 0xff
+#define PA_NR_COUNTERS 0x8
+#define PA_PERF_CTRL_EN BIT(0)
+#define PA_TRACETAG_EN BIT(4)
+#define PA_TGTID_EN BIT(11)
+#define PA_SRCID_EN BIT(11)
+#define PA_TGTID_NONE 0
+#define PA_SRCID_NONE 0
+#define PA_TGTID_MSK_SHIFT 12
+#define PA_SRCID_MSK_SHIFT 12
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_cmd, config1, 10, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_msk, config1, 21, 11);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
+
+static void hisi_pa_pmu_enable_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_en = hisi_get_tracetag_en(event);
+
+ if (tt_en) {
+ u32 val;
+
+ val = readl(pa_pmu->base + PA_TT_CTRL);
+ val |= PA_TRACETAG_EN;
+ writel(val, pa_pmu->base + PA_TT_CTRL);
+ }
+}
+
+static void hisi_pa_pmu_clear_tracetag(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 tt_en = hisi_get_tracetag_en(event);
+
+ if (tt_en) {
+ u32 val;
+
+ val = readl(pa_pmu->base + PA_TT_CTRL);
+ val &= ~PA_TRACETAG_EN;
+ writel(val, pa_pmu->base + PA_TT_CTRL);
+ }
+}
+
+static void hisi_pa_pmu_config_tgtid(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_tgtid_cmd(event);
+
+ if (cmd) {
+ u32 msk = hisi_get_tgtid_msk(event);
+ u32 val = cmd | PA_TGTID_EN | (msk << PA_TGTID_MSK_SHIFT);
+
+ writel(val, pa_pmu->base + PA_TGTID_CTRL);
+ }
+}
+
+static void hisi_pa_pmu_clear_tgtid(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_tgtid_cmd(event);
+
+ if (cmd)
+ writel(PA_TGTID_NONE, pa_pmu->base + PA_TGTID_CTRL);
+}
+
+static void hisi_pa_pmu_config_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd) {
+ u32 msk = hisi_get_srcid_msk(event);
+ u32 val = cmd | PA_SRCID_EN | (msk << PA_SRCID_MSK_SHIFT);
+
+ writel(val, pa_pmu->base + PA_SRCID_CTRL);
+ }
+}
+
+static void hisi_pa_pmu_clear_srcid(struct perf_event *event)
+{
+ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
+ u32 cmd = hisi_get_srcid_cmd(event);
+
+ if (cmd)
+ writel(PA_SRCID_NONE, pa_pmu->base + PA_SRCID_CTRL);
+}
+
+static void hisi_pa_pmu_enable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_pa_pmu_enable_tracetag(event);
+ hisi_pa_pmu_config_srcid(event);
+ hisi_pa_pmu_config_tgtid(event);
+ }
+}
+
+static void hisi_pa_pmu_disable_filter(struct perf_event *event)
+{
+ if (event->attr.config1 != 0x0) {
+ hisi_pa_pmu_clear_tgtid(event);
+ hisi_pa_pmu_clear_srcid(event);
+ hisi_pa_pmu_clear_tracetag(event);
+ }
+}
+
+static u32 hisi_pa_pmu_get_counter_offset(int idx)
+{
+ return (PA_EVENT_CNT0_L + idx * 8);
+}
+
+static u64 hisi_pa_pmu_read_counter(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(pa_pmu->base + hisi_pa_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_pa_pmu_write_counter(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val, pa_pmu->base + hisi_pa_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_pa_pmu_write_evtype(struct hisi_pmu *pa_pmu, int idx,
+ u32 type)
+{
+ u32 reg, reg_idx, shift, val;
+
+ /*
+ * Select the appropriate event select register(PA_EVENT_TYPE0/1).
+ * There are 2 event select registers for the 8 hardware counters.
+ * Event code is 8-bits and for the former 4 hardware counters,
+ * PA_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
+ * PA_EVENT_TYPE1 is chosen.
+ */
+ reg = PA_EVENT_TYPE0 + (idx / 4) * 4;
+ reg_idx = idx % 4;
+ shift = 8 * reg_idx;
+
+ /* Write event code to pa_EVENT_TYPEx Register */
+ val = readl(pa_pmu->base + reg);
+ val &= ~(PA_EVTYPE_MASK << shift);
+ val |= (type << shift);
+ writel(val, pa_pmu->base + reg);
+}
+
+static void hisi_pa_pmu_start_counters(struct hisi_pmu *pa_pmu)
+{
+ u32 val;
+
+ val = readl(pa_pmu->base + PA_PERF_CTRL);
+ val |= PA_PERF_CTRL_EN;
+ writel(val, pa_pmu->base + PA_PERF_CTRL);
+}
+
+static void hisi_pa_pmu_stop_counters(struct hisi_pmu *pa_pmu)
+{
+ u32 val;
+
+ val = readl(pa_pmu->base + PA_PERF_CTRL);
+ val &= ~(PA_PERF_CTRL_EN);
+ writel(val, pa_pmu->base + PA_PERF_CTRL);
+}
+
+static void hisi_pa_pmu_enable_counter(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Enable counter index in PA_EVENT_CTRL register */
+ val = readl(pa_pmu->base + PA_EVENT_CTRL);
+ val |= 1 << hwc->idx;
+ writel(val, pa_pmu->base + PA_EVENT_CTRL);
+}
+
+static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Clear counter index in PA_EVENT_CTRL register */
+ val = readl(pa_pmu->base + PA_EVENT_CTRL);
+ val &= ~(1 << hwc->idx);
+ writel(val, pa_pmu->base + PA_EVENT_CTRL);
+}
+
+static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 0 to enable interrupt */
+ val = readl(pa_pmu->base + PA_INT_MASK);
+ val &= ~(1 << hwc->idx);
+ writel(val, pa_pmu->base + PA_INT_MASK);
+}
+
+static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 1 to mask interrupt */
+ val = readl(pa_pmu->base + PA_INT_MASK);
+ val |= 1 << hwc->idx;
+ writel(val, pa_pmu->base + PA_INT_MASK);
+}
+
+static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu)
+{
+ return readl(pa_pmu->base + PA_INT_STATUS);
+}
+
+static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx)
+{
+ writel(1 << idx, pa_pmu->base + PA_INT_CLEAR);
+}
+
+static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
+ { "HISI0273", },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
+
+static int hisi_pa_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *pa_pmu)
+{
+ /*
+ * Use the SCCL_ID and the index ID to identify the PA PMU,
+ * while SCCL_ID is the nearst SCCL_ID from this SICL and
+ * CPU core is chosen from this SCCL to manage this PMU.
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &pa_pmu->sccl_id)) {
+ dev_err(&pdev->dev, "Cannot read sccl-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
+ &pa_pmu->index_id)) {
+ dev_err(&pdev->dev, "Cannot read idx-id!\n");
+ return -EINVAL;
+ }
+
+ pa_pmu->ccl_id = -1;
+
+ pa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pa_pmu->base)) {
+ dev_err(&pdev->dev, "ioremap failed for pa_pmu resource.\n");
+ return PTR_ERR(pa_pmu->base);
+ }
+
+ pa_pmu->identifier = readl(pa_pmu->base + PA_PMU_VERSION);
+
+ return 0;
+}
+
+static struct attribute *hisi_pa_pmu_v2_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ HISI_PMU_FORMAT_ATTR(tgtid_cmd, "config1:0-10"),
+ HISI_PMU_FORMAT_ATTR(tgtid_msk, "config1:11-21"),
+ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:22-32"),
+ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:33-43"),
+ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:44"),
+ NULL,
+};
+
+static const struct attribute_group hisi_pa_pmu_v2_format_group = {
+ .name = "format",
+ .attrs = hisi_pa_pmu_v2_format_attr,
+};
+
+static struct attribute *hisi_pa_pmu_v2_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(rx_req, 0x40),
+ HISI_PMU_EVENT_ATTR(tx_req, 0x5c),
+ HISI_PMU_EVENT_ATTR(cycle, 0x78),
+ NULL
+};
+
+static const struct attribute_group hisi_pa_pmu_v2_events_group = {
+ .name = "events",
+ .attrs = hisi_pa_pmu_v2_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_pa_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL
+};
+
+static const struct attribute_group hisi_pa_pmu_cpumask_attr_group = {
+ .attrs = hisi_pa_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_pa_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_pa_pmu_identifier_attrs[] = {
+ &hisi_pa_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_pa_pmu_identifier_group = {
+ .attrs = hisi_pa_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
+ &hisi_pa_pmu_v2_format_group,
+ &hisi_pa_pmu_v2_events_group,
+ &hisi_pa_pmu_cpumask_attr_group,
+ &hisi_pa_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_uncore_ops hisi_uncore_pa_ops = {
+ .write_evtype = hisi_pa_pmu_write_evtype,
+ .get_event_idx = hisi_uncore_pmu_get_event_idx,
+ .start_counters = hisi_pa_pmu_start_counters,
+ .stop_counters = hisi_pa_pmu_stop_counters,
+ .enable_counter = hisi_pa_pmu_enable_counter,
+ .disable_counter = hisi_pa_pmu_disable_counter,
+ .enable_counter_int = hisi_pa_pmu_enable_counter_int,
+ .disable_counter_int = hisi_pa_pmu_disable_counter_int,
+ .write_counter = hisi_pa_pmu_write_counter,
+ .read_counter = hisi_pa_pmu_read_counter,
+ .get_int_status = hisi_pa_pmu_get_int_status,
+ .clear_int_status = hisi_pa_pmu_clear_int_status,
+ .enable_filter = hisi_pa_pmu_enable_filter,
+ .disable_filter = hisi_pa_pmu_disable_filter,
+};
+
+static int hisi_pa_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *pa_pmu)
+{
+ int ret;
+
+ ret = hisi_pa_pmu_init_data(pdev, pa_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(pa_pmu, pdev);
+ if (ret)
+ return ret;
+
+ pa_pmu->pmu_events.attr_groups = hisi_pa_pmu_v2_attr_groups;
+ pa_pmu->num_counters = PA_NR_COUNTERS;
+ pa_pmu->ops = &hisi_uncore_pa_ops;
+ pa_pmu->check_event = 0xB0;
+ pa_pmu->counter_bits = 64;
+ pa_pmu->dev = &pdev->dev;
+ pa_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static int hisi_pa_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *pa_pmu;
+ char *name;
+ int ret;
+
+ pa_pmu = devm_kzalloc(&pdev->dev, sizeof(*pa_pmu), GFP_KERNEL);
+ if (!pa_pmu)
+ return -ENOMEM;
+
+ ret = hisi_pa_pmu_dev_probe(pdev, pa_pmu);
+ if (ret)
+ return ret;
+ /*
+ * PA is attached in SICL and the CPU core is chosen to manage this
+ * PMU which is the nearest SCCL, while its SCCL_ID is greater than
+ * one with the SICL_ID.
+ */
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u",
+ pa_pmu->sccl_id - 1, pa_pmu->index_id);
+ if (!name)
+ return -ENOMEM;
+
+ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
+ &pa_pmu->node);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
+ return ret;
+ }
+
+ pa_pmu->pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = pa_pmu->pmu_events.attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
+ if (ret) {
+ dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
+ cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
+ &pa_pmu->node);
+ irq_set_affinity_hint(pa_pmu->irq, NULL);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pa_pmu);
+ return ret;
+}
+
+static int hisi_pa_pmu_remove(struct platform_device *pdev)
+{
+ struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&pa_pmu->pmu);
+ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
+ &pa_pmu->node);
+ irq_set_affinity_hint(pa_pmu->irq, NULL);
+
+ return 0;
+}
+
+static struct platform_driver hisi_pa_pmu_driver = {
+ .driver = {
+ .name = "hisi_pa_pmu",
+ .acpi_match_table = hisi_pa_pmu_acpi_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_pa_pmu_probe,
+ .remove = hisi_pa_pmu_remove,
+};
+
+static int __init hisi_pa_pmu_module_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
+ "AP_PERF_ARM_HISI_PA_ONLINE",
+ hisi_uncore_pmu_online_cpu,
+ hisi_uncore_pmu_offline_cpu);
+ if (ret) {
+ pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = platform_driver_register(&hisi_pa_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
+
+ return ret;
+}
+module_init(hisi_pa_pmu_module_init);
+
+static void __exit hisi_pa_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_pa_pmu_driver);
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
+}
+module_exit(hisi_pa_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon Protocol Adapter uncore PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");
+MODULE_AUTHOR("Qi Liu <liuqi115@huawei.com>");
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index b5c55a408a30..225b095a96db 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -161,6 +161,7 @@ enum cpuhp_state {
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
+ CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
CPUHP_AP_PERF_ARM_L2X0_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE,
--
2.27.0

View File

@ -0,0 +1,181 @@
From e0b763c0b1c8c96a04fd56f7be82d13903123b19 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Fri, 30 Jul 2021 15:44:12 +0800
Subject: [PATCH 21/55] perf/hisi: Use irq_set_affinity()
mainline inclusion
from mainline-v5.13-rc3
commit 77b06ddc04354293f746d0434f00700110d3392d
category: bugfix
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=77b06ddc04354293f746d0434f00700110d3392d
------------------------------------------------------------------------
These drivers use irq_set_affinity_hint() to set the affinity for the PMU
interrupts, which relies on the undocumented side effect that this function
actually sets the affinity under the hood.
Setting an hint is clearly not a guarantee and for these PMU interrupts an
affinity hint, which is supposed to guide userspace for setting affinity,
is beyond pointless, because the affinity of these interrupts cannot be
modified from user space.
Aside of that the error checks are bogus because the only error which is
returned from irq_set_affinity_hint() is when there is no irq descriptor
for the interrupt number, but not when the affinity set fails. That's on
purpose because the hint can point to an offline CPU.
Replace the mindless abuse with irq_set_affinity().
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Shaokun Zhang <zhangshaokun@hisilicon.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Acked-by: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/r/20210518093118.813375875@linutronix.de
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 3 ---
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 3 ---
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 3 ---
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 3 ---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 ++--
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 3 ---
6 files changed, 2 insertions(+), 17 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index af5f8c16eab1..457ac6a1ad64 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -540,7 +540,6 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n");
cpuhp_state_remove_instance_nocalls(
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, &ddrc_pmu->node);
- irq_set_affinity_hint(ddrc_pmu->irq, NULL);
}
return ret;
@@ -553,8 +552,6 @@ static int hisi_ddrc_pmu_remove(struct platform_device *pdev)
perf_pmu_unregister(&ddrc_pmu->pmu);
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
&ddrc_pmu->node);
- irq_set_affinity_hint(ddrc_pmu->irq, NULL);
-
return 0;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index a7e1749fc3e4..89996b4d939f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -543,7 +543,6 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
dev_err(hha_pmu->dev, "HHA PMU register failed!\n");
cpuhp_state_remove_instance_nocalls(
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, &hha_pmu->node);
- irq_set_affinity_hint(hha_pmu->irq, NULL);
}
return ret;
@@ -556,8 +555,6 @@ static int hisi_hha_pmu_remove(struct platform_device *pdev)
perf_pmu_unregister(&hha_pmu->pmu);
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
&hha_pmu->node);
- irq_set_affinity_hint(hha_pmu->irq, NULL);
-
return 0;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 87ca2a9ca8c5..d70a01587d72 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -581,7 +581,6 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
dev_err(l3c_pmu->dev, "L3C PMU register failed!\n");
cpuhp_state_remove_instance_nocalls(
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node);
- irq_set_affinity_hint(l3c_pmu->irq, NULL);
}
return ret;
@@ -594,8 +593,6 @@ static int hisi_l3c_pmu_remove(struct platform_device *pdev)
perf_pmu_unregister(&l3c_pmu->pmu);
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
&l3c_pmu->node);
- irq_set_affinity_hint(l3c_pmu->irq, NULL);
-
return 0;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 5517a90552ec..390e59f4ef60 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -436,7 +436,6 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
&pa_pmu->node);
- irq_set_affinity_hint(pa_pmu->irq, NULL);
return ret;
}
@@ -451,8 +450,6 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev)
perf_pmu_unregister(&pa_pmu->pmu);
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
&pa_pmu->node);
- irq_set_affinity_hint(pa_pmu->irq, NULL);
-
return 0;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index c0f221e39aff..2758cab39a58 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -491,7 +491,7 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
hisi_pmu->on_cpu = cpu;
/* Overflow interrupt also should use the same CPU */
- WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(cpu)));
+ WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu)));
return 0;
}
@@ -524,7 +524,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target);
/* Use this CPU for event counting */
hisi_pmu->on_cpu = target;
- WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(target)));
+ WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target)));
return 0;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 46be312fa126..835ec3e2178f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -465,7 +465,6 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
&sllc_pmu->node);
- irq_set_affinity_hint(sllc_pmu->irq, NULL);
return ret;
}
@@ -481,8 +480,6 @@ static int hisi_sllc_pmu_remove(struct platform_device *pdev)
perf_pmu_unregister(&sllc_pmu->pmu);
cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
&sllc_pmu->node);
- irq_set_affinity_hint(sllc_pmu->irq, NULL);
-
return 0;
}
--
2.27.0

View File

@ -0,0 +1,60 @@
From 07451c781b0890dd194b0a53606250bed8f6ecbf Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Fri, 30 Jul 2021 15:44:13 +0800
Subject: [PATCH 22/55] drivers/perf: hisi: Fix data source control
mainline inclusion
from mainline-v5.13-rc3
commit 814be609baae62aaa6c02fa6f3ad66cff32a6d15
category: bugfix
bugzilla: 175148
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=814be609baae62aaa6c02fa6f3ad66cff32a6d15
------------------------------------------------------------------------
'Data source' is a new function for HHA PMU and config / clear
interface was wrong by mistake. 'HHA_DATSRC_CTRL' register is
mainly used for data source configuration, if we enable bit0
as driver, it will go on count the event and we didn't check
it carefully. So fix the issue and do as the initial purpose.
Fixes: 932f6a99f9b0 ("drivers/perf: hisi: Add new functions for HHA PMU")
Reported-by: kernel test robot <lkp@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Link: https://lore.kernel.org/r/1622709291-37996-1-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 89996b4d939f..3b120fc55e01 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -93,7 +93,7 @@ static void hisi_hha_pmu_config_ds(struct perf_event *event)
val = readl(hha_pmu->base + HHA_DATSRC_CTRL);
val |= HHA_DATSRC_SKT_EN;
- writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL);
+ writel(val, hha_pmu->base + HHA_DATSRC_CTRL);
}
}
@@ -107,7 +107,7 @@ static void hisi_hha_pmu_clear_ds(struct perf_event *event)
val = readl(hha_pmu->base + HHA_DATSRC_CTRL);
val &= ~HHA_DATSRC_SKT_EN;
- writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL);
+ writel(val, hha_pmu->base + HHA_DATSRC_CTRL);
}
}
--
2.27.0

View File

@ -0,0 +1,44 @@
From d6ffa958e5f2fd9eff8cec5b41817e9bdec94f5e Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Thu, 19 May 2022 20:09:48 +0800
Subject: [PATCH 23/55] perf: hisi: Make irq shared
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2
CVE: NA
--------------------------------
On some platforms, there are some error:
genirq: Flags mismatch irq 23. 00010804 (xxx) vs. 00010804 (xxx)
The reason is that there are more than one pmu nodes witch uses the same
irq number.
Add IROF_SHARED when devm_request_irq
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Reviewed-by: Weilong Chen <chenweilong@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 2758cab39a58..eceff43c89f7 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -171,7 +171,7 @@ int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
return irq;
ret = devm_request_irq(&pdev->dev, irq, hisi_uncore_pmu_isr,
- IRQF_NOBALANCING | IRQF_NO_THREAD,
+ IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED,
dev_name(&pdev->dev), hisi_pmu);
if (ret < 0) {
dev_err(&pdev->dev,
--
2.27.0

View File

@ -0,0 +1,57 @@
From 52b22aa2df42650d15ff80d32c827a55e6907a49 Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Thu, 19 May 2022 20:09:49 +0800
Subject: [PATCH 24/55] perf: hisi: Fix read sccl_id and ccl_id error in some
platform
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2
CVE: NA
--------------------------------
Some platforms with TSV200 or CORTEX_A55, sccl and ccl are keep in
aff2 if mt.
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Reviewed-by: Weilong Chen <chenweilong@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index eceff43c89f7..4a781c2e1992 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -437,12 +437,19 @@ static void hisi_read_sccl_and_ccl_id(int *scclp, int *cclp)
bool mt = mpidr & MPIDR_MT_BITMASK;
int sccl, ccl;
- if (mt && read_cpuid_part_number() == HISI_CPU_PART_TSV110) {
- sccl = aff2 >> 3;
- ccl = aff2 & 0x7;
- } else if (mt) {
- sccl = aff3;
- ccl = aff2;
+ if (mt) {
+ switch (read_cpuid_part_number()) {
+ case HISI_CPU_PART_TSV110:
+ case HISI_CPU_PART_TSV200:
+ case ARM_CPU_PART_CORTEX_A55:
+ sccl = aff2 >> 3;
+ ccl = aff2 & 0x7;
+ break;
+ default:
+ sccl = aff3;
+ ccl = aff2;
+ break;
+ }
} else {
sccl = aff2;
ccl = aff1;
--
2.27.0

View File

@ -0,0 +1,461 @@
From 88223b8764dabcbfde85e37927fbd12100957f22 Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Thu, 19 May 2022 20:09:50 +0800
Subject: [PATCH 25/55] perf: hisi: Add support for HiSilicon SoC L3T PMU
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2
CVE: NA
--------------------------------
Add support for HiSilicon SoC L3T PMU
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Reviewed-by: Weilong Chen <chenweilong@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/Makefile | 3 +-
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c | 403 +++++++++++++++++++
3 files changed, 406 insertions(+), 2 deletions(-)
create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 7643c9f93e36..18abcb612216 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
- hisi_uncore_pa_pmu.o
+ hisi_uncore_pa_pmu.o \
+ hisi_uncore_l3t_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index d70a01587d72..bb39b44761a5 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -611,7 +611,7 @@ static int __init hisi_l3c_pmu_module_init(void)
int ret;
ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
- "AP_PERF_ARM_HISI_L3_ONLINE",
+ "AP_PERF_ARM_HISI_L3T_ONLINE",
hisi_uncore_pmu_online_cpu,
hisi_uncore_pmu_offline_cpu);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
new file mode 100644
index 000000000000..f414dc1736aa
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SoC L3T uncore Hardware event counters support
+ *
+ * Copyright (C) 2017 Hisilicon Limited
+ * Author: Anurup M <anurup.m@huawei.com>
+ * Shaokun Zhang <zhangshaokun@hisilicon.com>
+ *
+ * This code is based on the uncore PMUs like arm-cci and arm-ccn.
+ */
+#include <linux/acpi.h>
+#include <linux/bug.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* L3T register definition */
+#define L3T_PERF_CTRL 0x0408
+#define L3T_INT_MASK 0x0800
+#define L3T_INT_STATUS 0x0808
+#define L3T_INT_CLEAR 0x080c
+#define L3T_EVENT_CTRL 0x1c00
+#define L3T_VERSION 0x1cf0
+#define L3T_EVENT_TYPE0 0x1d00
+/*
+ * If the HW version only supports a 48-bit counter, then
+ * bits [63:48] are reserved, which are Read-As-Zero and
+ * Writes-Ignored.
+ */
+#define L3T_CNTR0_LOWER 0x1e00
+
+/* L3T has 8-counters */
+#define L3T_NR_COUNTERS 0x8
+
+#define L3T_PERF_CTRL_EN 0x20000
+#define L3T_EVTYPE_NONE 0xff
+#define L3T_NR_EVENTS 0x59
+
+/*
+ * Select the counter register offset using the counter index
+ */
+static u32 hisi_l3t_pmu_get_counter_offset(int cntr_idx)
+{
+ return (L3T_CNTR0_LOWER + (cntr_idx * 8));
+}
+
+static u64 hisi_l3t_pmu_read_counter(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_l3t_pmu_write_counter(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val, l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_l3t_pmu_write_evtype(struct hisi_pmu *l3t_pmu, int idx,
+ u32 type)
+{
+ u32 reg, reg_idx, shift, val;
+
+ /*
+ * Select the appropriate event select register(L3T_EVENT_TYPE0/1).
+ * There are 2 event select registers for the 8 hardware counters.
+ * Event code is 8-bits and for the former 4 hardware counters,
+ * L3T_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
+ * L3T_EVENT_TYPE1 is chosen.
+ */
+ reg = L3T_EVENT_TYPE0 + (idx / 4) * 4;
+ reg_idx = idx % 4;
+ shift = 8 * reg_idx;
+
+ /* Write event code to L3T_EVENT_TYPEx Register */
+ val = readl(l3t_pmu->base + reg);
+ val &= ~(L3T_EVTYPE_NONE << shift);
+ val |= (type << shift);
+ writel(val, l3t_pmu->base + reg);
+}
+
+static void hisi_l3t_pmu_start_counters(struct hisi_pmu *l3t_pmu)
+{
+ u32 val;
+
+ /*
+ * Set perf_enable bit in L3T_PERF_CTRL register to start counting
+ * for all enabled counters.
+ */
+ val = readl(l3t_pmu->base + L3T_PERF_CTRL);
+ val |= L3T_PERF_CTRL_EN;
+ writel(val, l3t_pmu->base + L3T_PERF_CTRL);
+}
+
+static void hisi_l3t_pmu_stop_counters(struct hisi_pmu *l3t_pmu)
+{
+ u32 val;
+
+ /*
+ * Clear perf_enable bit in L3T_PERF_CTRL register to stop counting
+ * for all enabled counters.
+ */
+ val = readl(l3t_pmu->base + L3T_PERF_CTRL);
+ val &= ~(L3T_PERF_CTRL_EN);
+ writel(val, l3t_pmu->base + L3T_PERF_CTRL);
+}
+
+static void hisi_l3t_pmu_enable_counter(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Enable counter index in L3T_EVENT_CTRL register */
+ val = readl(l3t_pmu->base + L3T_EVENT_CTRL);
+ val |= (1 << hwc->idx);
+ writel(val, l3t_pmu->base + L3T_EVENT_CTRL);
+}
+
+static void hisi_l3t_pmu_disable_counter(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Clear counter index in L3T_EVENT_CTRL register */
+ val = readl(l3t_pmu->base + L3T_EVENT_CTRL);
+ val &= ~(1 << hwc->idx);
+ writel(val, l3t_pmu->base + L3T_EVENT_CTRL);
+}
+
+static void hisi_l3t_pmu_enable_counter_int(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(l3t_pmu->base + L3T_INT_MASK);
+ /* Write 0 to enable interrupt */
+ val &= ~(1 << hwc->idx);
+ writel(val, l3t_pmu->base + L3T_INT_MASK);
+}
+
+static void hisi_l3t_pmu_disable_counter_int(struct hisi_pmu *l3t_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ val = readl(l3t_pmu->base + L3T_INT_MASK);
+ /* Write 1 to mask interrupt */
+ val |= (1 << hwc->idx);
+ writel(val, l3t_pmu->base + L3T_INT_MASK);
+}
+
+static u32 hisi_l3t_pmu_get_int_status(struct hisi_pmu *l3t_pmu)
+{
+ return readl(l3t_pmu->base + L3T_INT_STATUS);
+}
+
+static void hisi_l3t_pmu_clear_int_status(struct hisi_pmu *l3t_pmu, int idx)
+{
+ writel(1 << idx, l3t_pmu->base + L3T_INT_CLEAR);
+}
+
+static const struct acpi_device_id hisi_l3t_pmu_acpi_match[] = {
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_l3t_pmu_acpi_match);
+
+static const struct of_device_id l3t_of_match[] = {
+ { .compatible = "hisilicon,l3t-pmu", },
+ {},
+};
+
+static int hisi_l3t_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *l3t_pmu)
+{
+ /*
+ * Use the SCCL_ID and CCL_ID to identify the L3T PMU, while
+ * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &l3t_pmu->sccl_id)) {
+ dev_err(&pdev->dev, "Can not read l3t sccl-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
+ &l3t_pmu->ccl_id)) {
+ dev_err(&pdev->dev, "Can not read l3t ccl-id!\n");
+ return -EINVAL;
+ }
+
+ l3t_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(l3t_pmu->base)) {
+ dev_err(&pdev->dev, "ioremap failed for l3t_pmu resource\n");
+ return PTR_ERR(l3t_pmu->base);
+ }
+
+ l3t_pmu->identifier = readl(l3t_pmu->base + L3T_VERSION);
+
+ return 0;
+}
+
+static struct attribute *hisi_l3t_pmu_v1_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+ NULL,
+};
+
+static const struct attribute_group hisi_l3t_pmu_v1_format_group = {
+ .name = "format",
+ .attrs = hisi_l3t_pmu_v1_format_attr,
+};
+
+static struct attribute *hisi_l3t_pmu_v1_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00),
+ HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01),
+ HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02),
+ HISI_PMU_EVENT_ATTR(wr_hit_cpipe, 0x03),
+ HISI_PMU_EVENT_ATTR(victim_num, 0x04),
+ HISI_PMU_EVENT_ATTR(rd_spipe, 0x20),
+ HISI_PMU_EVENT_ATTR(wr_spipe, 0x21),
+ HISI_PMU_EVENT_ATTR(rd_hit_spipe, 0x22),
+ HISI_PMU_EVENT_ATTR(wr_hit_spipe, 0x23),
+ HISI_PMU_EVENT_ATTR(back_invalid, 0x29),
+ HISI_PMU_EVENT_ATTR(retry_cpu, 0x40),
+ HISI_PMU_EVENT_ATTR(retry_ring, 0x41),
+ HISI_PMU_EVENT_ATTR(prefetch_drop, 0x42),
+ NULL,
+};
+
+static const struct attribute_group hisi_l3t_pmu_v1_events_group = {
+ .name = "events",
+ .attrs = hisi_l3t_pmu_v1_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_l3t_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL,
+};
+
+static const struct attribute_group hisi_l3t_pmu_cpumask_attr_group = {
+ .attrs = hisi_l3t_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_l3t_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_l3t_pmu_identifier_attrs[] = {
+ &hisi_l3t_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_l3t_pmu_identifier_group = {
+ .attrs = hisi_l3t_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_l3t_pmu_v1_attr_groups[] = {
+ &hisi_l3t_pmu_v1_format_group,
+ &hisi_l3t_pmu_v1_events_group,
+ &hisi_l3t_pmu_cpumask_attr_group,
+ &hisi_l3t_pmu_identifier_group,
+ NULL,
+};
+
+static const struct hisi_uncore_ops hisi_uncore_l3t_ops = {
+ .write_evtype = hisi_l3t_pmu_write_evtype,
+ .get_event_idx = hisi_uncore_pmu_get_event_idx,
+ .start_counters = hisi_l3t_pmu_start_counters,
+ .stop_counters = hisi_l3t_pmu_stop_counters,
+ .enable_counter = hisi_l3t_pmu_enable_counter,
+ .disable_counter = hisi_l3t_pmu_disable_counter,
+ .enable_counter_int = hisi_l3t_pmu_enable_counter_int,
+ .disable_counter_int = hisi_l3t_pmu_disable_counter_int,
+ .write_counter = hisi_l3t_pmu_write_counter,
+ .read_counter = hisi_l3t_pmu_read_counter,
+ .get_int_status = hisi_l3t_pmu_get_int_status,
+ .clear_int_status = hisi_l3t_pmu_clear_int_status,
+};
+
+static int hisi_l3t_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *l3t_pmu)
+{
+ int ret;
+
+ ret = hisi_l3t_pmu_init_data(pdev, l3t_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(l3t_pmu, pdev);
+ if (ret)
+ return ret;
+
+ l3t_pmu->counter_bits = 48;
+ l3t_pmu->check_event = L3T_NR_EVENTS;
+ l3t_pmu->pmu_events.attr_groups = hisi_l3t_pmu_v1_attr_groups;
+
+ l3t_pmu->num_counters = L3T_NR_COUNTERS;
+ l3t_pmu->ops = &hisi_uncore_l3t_ops;
+ l3t_pmu->dev = &pdev->dev;
+ l3t_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static int hisi_l3t_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *l3t_pmu;
+ char *name;
+ int ret;
+
+ l3t_pmu = devm_kzalloc(&pdev->dev, sizeof(*l3t_pmu), GFP_KERNEL);
+ if (!l3t_pmu)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, l3t_pmu);
+
+ ret = hisi_l3t_pmu_dev_probe(pdev, l3t_pmu);
+ if (ret)
+ return ret;
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,index-id", &l3t_pmu->index_id)) {
+ dev_err(&pdev->dev, "Can not read l3t index-id!\n");
+ return -EINVAL;
+ }
+
+ /*
+ * CCL_ID is used to identify the L3T in the same SCCL which was
+ * used _UID by mistake.
+ */
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3t%u",
+ l3t_pmu->sccl_id, l3t_pmu->index_id);
+ l3t_pmu->pmu = (struct pmu) {
+ .name = name,
+ .module = THIS_MODULE,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = l3t_pmu->pmu_events.attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ /* Pick one core to use for cpumask attributes */
+ cpumask_set_cpu(smp_processor_id(), &l3t_pmu->associated_cpus);
+
+ l3t_pmu->on_cpu = cpumask_first(&l3t_pmu->associated_cpus);
+ if (l3t_pmu->on_cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ ret = perf_pmu_register(&l3t_pmu->pmu, name, -1);
+
+ return ret;
+}
+
+static int hisi_l3t_pmu_remove(struct platform_device *pdev)
+{
+ struct hisi_pmu *l3t_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&l3t_pmu->pmu);
+
+ return 0;
+}
+
+static struct platform_driver hisi_l3t_pmu_driver = {
+ .driver = {
+ .name = "hisi_l3t_pmu",
+ .acpi_match_table = ACPI_PTR(hisi_l3t_pmu_acpi_match),
+ .of_match_table = l3t_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_l3t_pmu_probe,
+ .remove = hisi_l3t_pmu_remove,
+};
+
+static int __init hisi_l3t_pmu_module_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&hisi_l3t_pmu_driver);
+
+ return ret;
+}
+module_init(hisi_l3t_pmu_module_init);
+
+static void __exit hisi_l3t_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_l3t_pmu_driver);
+}
+module_exit(hisi_l3t_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon SoC L3T uncore PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Anurup M <anurup.m@huawei.com>");
+MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");
--
2.27.0

View File

@ -0,0 +1,452 @@
From f61fd1d5a4ff1adaae0626f0a99fc38e82efde55 Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Thu, 19 May 2022 20:09:51 +0800
Subject: [PATCH 26/55] perf: hisi: Add support for HiSilicon SoC LPDDRC PMU
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2
CVE: NA
--------------------------------
Add support for HiSilicon SoC LPDDRC PMU
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Reviewed-by: Weilong Chen <chenweilong@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/Makefile | 3 +-
.../perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 408 ++++++++++++++++++
2 files changed, 410 insertions(+), 1 deletion(-)
create mode 100644 drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 18abcb612216..22e384cdfd53 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -2,4 +2,5 @@
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
hisi_uncore_pa_pmu.o \
- hisi_uncore_l3t_pmu.o
+ hisi_uncore_l3t_pmu.o \
+ hisi_uncore_lpddrc_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
new file mode 100644
index 000000000000..03a4bb1a9948
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c
@@ -0,0 +1,408 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SoC LPDDRC uncore Hardware event counters support
+ *
+ * Copyright (C) 2017 Hisilicon Limited
+ * Author: Shaokun Zhang <zhangshaokun@hisilicon.com>
+ * Anurup M <anurup.m@huawei.com>
+ *
+ * This code is based on the uncore PMUs like arm-cci and arm-ccn.
+ */
+#include <linux/acpi.h>
+#include <linux/bug.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* LPDDRC register definition in v1 */
+#define LPDDRC_PERF_CTRL 0x4930
+#define LPDDRC_FLUX_WR 0x4948
+#define LPDDRC_FLUX_RD 0x494c
+#define LPDDRC_FLUX_WCMD 0x4950
+#define LPDDRC_FLUX_RCMD 0x4954
+#define LPDDRC_PRE_CMD 0x4984
+#define LPDDRC_ACT_CMD 0x4988
+#define LPDDRC_RNK_CHG 0x4990
+#define LPDDRC_RW_CHG 0x4994
+#define LPDDRC_EVENT_CTRL 0x4d60
+#define LPDDRC_INT_MASK 0x6c8
+#define LPDDRC_INT_STATUS 0x6cc
+#define LPDDRC_INT_CLEAR 0x6d0
+#define LPDDRC_VERSION 0x710
+
+#define LPDDRC_NR_COUNTERS 0x8
+#define LPDDRC_V1_PERF_CTRL_EN 0x1
+#define LPDDRC_V1_NR_EVENTS 0x7
+
+/*
+ * For PMU v1, there are eight-events and every event has been mapped
+ * to fixed-purpose counters which register offset is not consistent.
+ * Therefore there is no write event type and we assume that event
+ * code (0 to 7) is equal to counter index in PMU driver.
+ */
+#define GET_LPDDRC_EVENTID(hwc) (hwc->config_base & 0x7)
+
+static const u32 lpddrc_reg_off[] = {
+ LPDDRC_FLUX_WR, LPDDRC_FLUX_RD, LPDDRC_FLUX_WCMD, LPDDRC_FLUX_RCMD,
+ LPDDRC_PRE_CMD, LPDDRC_ACT_CMD, LPDDRC_RNK_CHG, LPDDRC_RW_CHG
+};
+
+/*
+ * Select the counter register offset using the counter index.
+ * In PMU v1, there are no programmable counter, the count
+ * is read form the statistics counter register itself.
+ */
+static u32 hisi_lpddrc_pmu_v1_get_counter_offset(int cntr_idx)
+{
+ return lpddrc_reg_off[cntr_idx];
+}
+
+static u64 hisi_lpddrc_pmu_v1_read_counter(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readl(lpddrc_pmu->base +
+ hisi_lpddrc_pmu_v1_get_counter_offset(hwc->idx));
+}
+
+/*
+ * For LPDDRC PMU, event counter should be reset when start counters,
+ * reset the prev_count by software, because the counter register was RO.
+ */
+static void hisi_lpddrc_pmu_v1_write_counter(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ local64_set(&hwc->prev_count, 0);
+}
+
+/*
+ * For LPDDRC PMU v1, event has been mapped to fixed-purpose counter by hardware,
+ * so there is no need to write event type, while it is programmable counter in
+ * PMU v2.
+ */
+static void hisi_lpddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
+ u32 type)
+{
+}
+
+static void hisi_lpddrc_pmu_v1_start_counters(struct hisi_pmu *lpddrc_pmu)
+{
+ u32 val;
+
+ /* Set perf_enable in LPDDRC_PERF_CTRL to start event counting */
+ val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL);
+ val |= LPDDRC_V1_PERF_CTRL_EN;
+ writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL);
+}
+
+static void hisi_lpddrc_pmu_v1_stop_counters(struct hisi_pmu *lpddrc_pmu)
+{
+ u32 val;
+
+ /* Clear perf_enable in LPDDRC_PERF_CTRL to stop event counting */
+ val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL);
+ val &= ~LPDDRC_V1_PERF_CTRL_EN;
+ writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL);
+}
+
+static void hisi_lpddrc_pmu_v1_enable_counter(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Set counter index(event code) in LPDDRC_EVENT_CTRL register */
+ val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
+ val |= (1 << GET_LPDDRC_EVENTID(hwc));
+ writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
+}
+
+static void hisi_lpddrc_pmu_v1_disable_counter(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Clear counter index(event code) in LPDDRC_EVENT_CTRL register */
+ val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
+ val &= ~(1 << GET_LPDDRC_EVENTID(hwc));
+ writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL);
+}
+
+static int hisi_lpddrc_pmu_v1_get_event_idx(struct perf_event *event)
+{
+ struct hisi_pmu *lpddrc_pmu = to_hisi_pmu(event->pmu);
+ unsigned long *used_mask = lpddrc_pmu->pmu_events.used_mask;
+ struct hw_perf_event *hwc = &event->hw;
+ /* For LPDDRC PMU, we use event code as counter index */
+ int idx = GET_LPDDRC_EVENTID(hwc);
+
+ if (test_bit(idx, used_mask))
+ return -EAGAIN;
+
+ set_bit(idx, used_mask);
+
+ return idx;
+}
+
+static void hisi_lpddrc_pmu_v1_enable_counter_int(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 0 to enable interrupt */
+ val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK);
+ val &= ~(1 << hwc->idx);
+ writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK);
+}
+
+static void hisi_lpddrc_pmu_v1_disable_counter_int(struct hisi_pmu *lpddrc_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 1 to mask interrupt */
+ val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK);
+ val |= 1 << hwc->idx;
+ writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK);
+}
+
+static u32 hisi_lpddrc_pmu_v1_get_int_status(struct hisi_pmu *lpddrc_pmu)
+{
+ return readl(lpddrc_pmu->base + LPDDRC_INT_STATUS);
+}
+
+static void hisi_lpddrc_pmu_v1_clear_int_status(struct hisi_pmu *lpddrc_pmu,
+ int idx)
+{
+ writel(1 << idx, lpddrc_pmu->base + LPDDRC_INT_CLEAR);
+}
+
+static const struct acpi_device_id hisi_lpddrc_pmu_acpi_match[] = {
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_lpddrc_pmu_acpi_match);
+
+static const struct of_device_id lpddrc_of_match[] = {
+ { .compatible = "hisilicon,lpddrc-pmu", },
+ {},
+};
+
+static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *lpddrc_pmu)
+{
+ /*
+ * Use the SCCL_ID and LPDDRC channel ID to identify the
+ * LPDDRC PMU, while SCCL_ID is in MPIDR[aff2].
+ */
+ if (device_property_read_u32(&pdev->dev, "hisilicon,ch-id",
+ &lpddrc_pmu->index_id)) {
+ dev_err(&pdev->dev, "Can not read lpddrc channel-id!\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &lpddrc_pmu->sccl_id)) {
+ dev_err(&pdev->dev, "Can not read lpddrc sccl-id!\n");
+ return -EINVAL;
+ }
+ /* LPDDRC PMUs only share the same SCCL */
+ lpddrc_pmu->ccl_id = -1;
+
+ lpddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(lpddrc_pmu->base)) {
+ dev_err(&pdev->dev, "ioremap failed for lpddrc_pmu resource\n");
+ return PTR_ERR(lpddrc_pmu->base);
+ }
+
+ lpddrc_pmu->identifier = readl(lpddrc_pmu->base + LPDDRC_VERSION);
+
+ return 0;
+}
+
+static struct attribute *hisi_lpddrc_pmu_v1_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-4"),
+ NULL,
+};
+
+static const struct attribute_group hisi_lpddrc_pmu_v1_format_group = {
+ .name = "format",
+ .attrs = hisi_lpddrc_pmu_v1_format_attr,
+};
+
+static struct attribute *hisi_lpddrc_pmu_v1_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(flux_wr, 0x00),
+ HISI_PMU_EVENT_ATTR(flux_rd, 0x01),
+ HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02),
+ HISI_PMU_EVENT_ATTR(flux_rcmd, 0x03),
+ HISI_PMU_EVENT_ATTR(pre_cmd, 0x04),
+ HISI_PMU_EVENT_ATTR(act_cmd, 0x05),
+ HISI_PMU_EVENT_ATTR(rnk_chg, 0x06),
+ HISI_PMU_EVENT_ATTR(rw_chg, 0x07),
+ NULL,
+};
+
+static const struct attribute_group hisi_lpddrc_pmu_v1_events_group = {
+ .name = "events",
+ .attrs = hisi_lpddrc_pmu_v1_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_lpddrc_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL,
+};
+
+static const struct attribute_group hisi_lpddrc_pmu_cpumask_attr_group = {
+ .attrs = hisi_lpddrc_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_lpddrc_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_lpddrc_pmu_identifier_attrs[] = {
+ &hisi_lpddrc_pmu_identifier_attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_lpddrc_pmu_identifier_group = {
+ .attrs = hisi_lpddrc_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_lpddrc_pmu_v1_attr_groups[] = {
+ &hisi_lpddrc_pmu_v1_format_group,
+ &hisi_lpddrc_pmu_v1_events_group,
+ &hisi_lpddrc_pmu_cpumask_attr_group,
+ &hisi_lpddrc_pmu_identifier_group,
+ NULL,
+};
+
+static const struct hisi_uncore_ops hisi_uncore_lpddrc_v1_ops = {
+ .write_evtype = hisi_lpddrc_pmu_write_evtype,
+ .get_event_idx = hisi_lpddrc_pmu_v1_get_event_idx,
+ .start_counters = hisi_lpddrc_pmu_v1_start_counters,
+ .stop_counters = hisi_lpddrc_pmu_v1_stop_counters,
+ .enable_counter = hisi_lpddrc_pmu_v1_enable_counter,
+ .disable_counter = hisi_lpddrc_pmu_v1_disable_counter,
+ .enable_counter_int = hisi_lpddrc_pmu_v1_enable_counter_int,
+ .disable_counter_int = hisi_lpddrc_pmu_v1_disable_counter_int,
+ .write_counter = hisi_lpddrc_pmu_v1_write_counter,
+ .read_counter = hisi_lpddrc_pmu_v1_read_counter,
+ .get_int_status = hisi_lpddrc_pmu_v1_get_int_status,
+ .clear_int_status = hisi_lpddrc_pmu_v1_clear_int_status,
+};
+
+static int hisi_lpddrc_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *lpddrc_pmu)
+{
+ int ret;
+
+ ret = hisi_lpddrc_pmu_init_data(pdev, lpddrc_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(lpddrc_pmu, pdev);
+ if (ret)
+ return ret;
+
+ lpddrc_pmu->counter_bits = 32;
+ lpddrc_pmu->check_event = LPDDRC_V1_NR_EVENTS;
+ lpddrc_pmu->pmu_events.attr_groups = hisi_lpddrc_pmu_v1_attr_groups;
+ lpddrc_pmu->ops = &hisi_uncore_lpddrc_v1_ops;
+
+ lpddrc_pmu->num_counters = LPDDRC_NR_COUNTERS;
+ lpddrc_pmu->dev = &pdev->dev;
+ lpddrc_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static int hisi_lpddrc_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *lpddrc_pmu;
+ char *name;
+ int ret;
+
+ lpddrc_pmu = devm_kzalloc(&pdev->dev, sizeof(*lpddrc_pmu), GFP_KERNEL);
+ if (!lpddrc_pmu)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, lpddrc_pmu);
+
+ ret = hisi_lpddrc_pmu_dev_probe(pdev, lpddrc_pmu);
+ if (ret)
+ return ret;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "hisi_sccl%u_lpddrc%u", lpddrc_pmu->sccl_id,
+ lpddrc_pmu->index_id);
+
+ lpddrc_pmu->pmu = (struct pmu) {
+ .name = name,
+ .module = THIS_MODULE,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = lpddrc_pmu->pmu_events.attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ /* Pick one core to use for cpumask attributes */
+ cpumask_set_cpu(smp_processor_id(), &lpddrc_pmu->associated_cpus);
+
+ lpddrc_pmu->on_cpu = cpumask_first(&lpddrc_pmu->associated_cpus);
+ if (lpddrc_pmu->on_cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ ret = perf_pmu_register(&lpddrc_pmu->pmu, name, -1);
+
+ return ret;
+}
+
+static int hisi_lpddrc_pmu_remove(struct platform_device *pdev)
+{
+ struct hisi_pmu *lpddrc_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&lpddrc_pmu->pmu);
+ return 0;
+}
+
+static struct platform_driver hisi_lpddrc_pmu_driver = {
+ .driver = {
+ .name = "hisi_lpddrc_pmu",
+ .acpi_match_table = ACPI_PTR(hisi_lpddrc_pmu_acpi_match),
+ .of_match_table = lpddrc_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_lpddrc_pmu_probe,
+ .remove = hisi_lpddrc_pmu_remove,
+};
+
+static int __init hisi_lpddrc_pmu_module_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&hisi_lpddrc_pmu_driver);
+
+ return ret;
+}
+module_init(hisi_lpddrc_pmu_module_init);
+
+static void __exit hisi_lpddrc_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_lpddrc_pmu_driver);
+}
+module_exit(hisi_lpddrc_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon SoC LPDDRC uncore PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");
+MODULE_AUTHOR("Anurup M <anurup.m@huawei.com>");
--
2.27.0

View File

@ -0,0 +1,41 @@
From 91e203d62a15728846824029f1eb18fa8eb03aeb Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Mon, 23 May 2022 21:18:33 +0800
Subject: [PATCH 27/55] perf: hisi: Fix unexpected modifications in
hisi_uncore_l3c_pmu.c
hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2
CVE: NA
--------------------------------
the name passed to cpuhp_setup_state_multi in hisi_uncore_l3c_pmu.c was
modification unexpected.
Fixes: 744d0990ad13 ("perf: hisi: Add support for HiSilicon SoC L3TPMU")
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Reviewed-by: Weilong Chen <chenweilong@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index bb39b44761a5..d70a01587d72 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -611,7 +611,7 @@ static int __init hisi_l3c_pmu_module_init(void)
int ret;
ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
- "AP_PERF_ARM_HISI_L3T_ONLINE",
+ "AP_PERF_ARM_HISI_L3_ONLINE",
hisi_uncore_pmu_online_cpu,
hisi_uncore_pmu_offline_cpu);
if (ret) {
--
2.27.0

View File

@ -0,0 +1,114 @@
From 5fe54aa034e28dc979d147c3cf4a2ae25c529ff7 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Wed, 24 Apr 2019 21:11:58 +0200
Subject: [PATCH 28/55] PCI: Add pci_dev_id() helper
mainline inclusion
from mainline-v5.2-rc1
commit 4e544bac8267f65a0bf06aed1bde9964da4812ed
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4e544bac8267f65a0bf06aed1bde9964da4812ed
----------------------------------------------------------------
In several places in the kernel we find PCI_DEVID used like this:
PCI_DEVID(dev->bus->number, dev->devfn)
Add a "pci_dev_id(struct pci_dev *dev)" helper to simplify callers.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/pci/msi.c | 6 +++---
drivers/pci/search.c | 10 +++-------
include/linux/pci.h | 5 +++++
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index bf560dcf8dd4..8138f67123a1 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1385,7 +1385,7 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
struct msi_desc *desc)
{
return (irq_hw_number_t)desc->msi_attrib.entry_nr |
- PCI_DEVID(dev->bus->number, dev->devfn) << 11 |
+ pci_dev_id(dev) << 11 |
(pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
}
@@ -1555,7 +1555,7 @@ static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data)
u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
{
struct device_node *of_node;
- u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ u32 rid = pci_dev_id(pdev);
pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
@@ -1578,7 +1578,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
{
struct irq_domain *dom;
- u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ u32 rid = pci_dev_id(pdev);
pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
dom = of_msi_map_get_device_domain(&pdev->dev, rid);
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 2b5f720862d3..5c7922612733 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -33,7 +33,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
struct pci_bus *bus;
int ret;
- ret = fn(pdev, PCI_DEVID(pdev->bus->number, pdev->devfn), data);
+ ret = fn(pdev, pci_dev_id(pdev), data);
if (ret)
return ret;
@@ -88,9 +88,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
return ret;
continue;
case PCI_EXP_TYPE_PCIE_BRIDGE:
- ret = fn(tmp,
- PCI_DEVID(tmp->bus->number,
- tmp->devfn), data);
+ ret = fn(tmp, pci_dev_id(tmp), data);
if (ret)
return ret;
continue;
@@ -101,9 +99,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
PCI_DEVID(tmp->subordinate->number,
PCI_DEVFN(0, 0)), data);
else
- ret = fn(tmp,
- PCI_DEVID(tmp->bus->number,
- tmp->devfn), data);
+ ret = fn(tmp, pci_dev_id(tmp), data);
if (ret)
return ret;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index bc49349fcc53..bfc26f8d5552 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -633,6 +633,11 @@ struct pci_bus {
#define to_pci_bus(n) container_of(n, struct pci_bus, dev)
+static inline u16 pci_dev_id(struct pci_dev *dev)
+{
+ return PCI_DEVID(dev->bus->number, dev->devfn);
+}
+
/*
* Returns true if the PCI bus is root (behind host-PCI bridge),
* false otherwise
--
2.27.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
From 0b7b0513121aea4c200c8cd639edf3d1eda1c248 Mon Sep 17 00:00:00 2001
From: Qi Liu <liuqi115@huawei.com>
Date: Tue, 9 Aug 2022 23:06:42 +0800
Subject: [PATCH 30/55] drivers/perf: hisi: Associate PMUs in SICL with CPUs
online
mainline inclusion
from mainline-v5.19-rc1
commit 807907dae9701c4b0593d5195d4839f17d103314
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5AZ87
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=807907dae970
--------------------------------------------------------------------------
If a PMU is in a SICL (Super IO cluster), it is not appropriate to
associate this PMU with a CPU die. So we associate it with all CPUs
online, rather than CPUs in the nearest SCCL.
As the firmware of Hip09 platform hasn't been published yet, change
of PMU driver will not influence backwards compatibility between
driver and firmware.
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Reviewed-by: John Garry <john.garry@huawei.com>
Link: https://lore.kernel.org/r/20220415102352.6665-2-liuqi115@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Wangming Shao <shaowangming@h-partners.com>
Reviewed-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: Yang Jihong <yangjihong1@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 18 +++++++-----------
drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 ++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 +
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 390e59f4ef60..f1e6b5cee075 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -258,13 +258,12 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *pa_pmu)
{
/*
- * Use the SCCL_ID and the index ID to identify the PA PMU,
- * while SCCL_ID is the nearst SCCL_ID from this SICL and
- * CPU core is chosen from this SCCL to manage this PMU.
+ * As PA PMU is in a SICL, use the SICL_ID and the index ID
+ * to identify the PA PMU.
*/
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
- &pa_pmu->sccl_id)) {
- dev_err(&pdev->dev, "Cannot read sccl-id!\n");
+ &pa_pmu->sicl_id)) {
+ dev_err(&pdev->dev, "Cannot read sicl-id!\n");
return -EINVAL;
}
@@ -275,6 +274,7 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
}
pa_pmu->ccl_id = -1;
+ pa_pmu->sccl_id = -1;
pa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pa_pmu->base)) {
@@ -399,13 +399,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
ret = hisi_pa_pmu_dev_probe(pdev, pa_pmu);
if (ret)
return ret;
- /*
- * PA is attached in SICL and the CPU core is chosen to manage this
- * PMU which is the nearest SCCL, while its SCCL_ID is greater than
- * one with the SICL_ID.
- */
+
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u",
- pa_pmu->sccl_id - 1, pa_pmu->index_id);
+ pa_pmu->sicl_id, pa_pmu->index_id);
if (!name)
return -ENOMEM;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 4a781c2e1992..9aaaf9cf2b2a 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -468,6 +468,10 @@ static bool hisi_pmu_cpu_is_associated_pmu(struct hisi_pmu *hisi_pmu)
{
int sccl_id, ccl_id;
+ /* If SCCL_ID is -1, the PMU is in a SICL and has no CPU affinity */
+ if (hisi_pmu->sccl_id == -1)
+ return true;
+
if (hisi_pmu->ccl_id == -1) {
/* If CCL_ID is -1, the PMU only shares the same SCCL */
hisi_read_sccl_and_ccl_id(&sccl_id, NULL);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index de6aa17a1355..75dfc12e6497 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -84,6 +84,7 @@ struct hisi_pmu {
struct device *dev;
struct hlist_node node;
int sccl_id;
+ int sicl_id;
int ccl_id;
void __iomem *base;
/* the ID of the PMU modules */
--
2.27.0

View File

@ -0,0 +1,75 @@
From 55424d384fb9dab1f8ac81c7fdfce3260ec255e7 Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Thu, 19 Oct 2023 15:08:35 +0800
Subject: [PATCH 31/55] driver/perf: hisi: fix kabi broken for struct hisi_pmu
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
-------------------------------------------------------------------
fix kabi broken in struct hisi_uncore_ops, hisi_pmu_hwevents,
and hisi_pmu, then keep function "hisi_uncore_pmu_counter_valid" interface
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 75dfc12e6497..6a78c13176c2 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -59,16 +59,20 @@ struct hisi_uncore_ops {
void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
void (*start_counters)(struct hisi_pmu *);
void (*stop_counters)(struct hisi_pmu *);
+#ifndef __GENKSYMS__
u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
void (*enable_filter)(struct perf_event *event);
void (*disable_filter)(struct perf_event *event);
+#endif
};
struct hisi_pmu_hwevents {
struct perf_event *hw_events[HISI_MAX_COUNTERS];
DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
+#ifndef __GENKSYMS__
const struct attribute_group **attr_groups;
+#endif
};
/* Generic pmu struct for different pmu types */
@@ -84,20 +88,27 @@ struct hisi_pmu {
struct device *dev;
struct hlist_node node;
int sccl_id;
+#ifndef __GENKSYMS__
int sicl_id;
+#endif
int ccl_id;
void __iomem *base;
/* the ID of the PMU modules */
u32 index_id;
+#ifndef __GENKSYMS__
/* For DDRC PMU v2: each DDRC has more than one DMC */
u32 sub_id;
+#endif
int num_counters;
int counter_bits;
/* check event code range */
int check_event;
+#ifndef __GENKSYMS__
u32 identifier;
+#endif
};
+int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx);
int hisi_uncore_pmu_get_event_idx(struct perf_event *event);
void hisi_uncore_pmu_read(struct perf_event *event);
int hisi_uncore_pmu_add(struct perf_event *event, int flags);
--
2.27.0

View File

@ -0,0 +1,486 @@
From a75b20496157f6605843bf6399c7d082ec2a37b2 Mon Sep 17 00:00:00 2001
From: Qi Liu <liuqi115@huawei.com>
Date: Tue, 9 Aug 2022 23:06:43 +0800
Subject: [PATCH 32/55] drivers/perf: hisi: Add Support for CPA PMU
mainline inclusion
from mainline-v5.19-rc1
commit 6b79738b6ed91a2d0fe958819469eeedac3bca81
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5AZ87
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b79738b6ed9
--------------------------------------------------------------------------
On HiSilicon Hip09 platform, there is a CPA (Coherency Protocol Agent) on
each SICL (Super IO Cluster) which implements packet format translation,
route parsing and traffic statistics.
CPA PMU has 8 PMU counters and interrupt is supported to handle counter
overflow. Let's support its driver under the framework of HiSilicon PMU
driver.
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Reviewed-by: John Garry <john.garry@huawei.com>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Link: https://lore.kernel.org/r/20220415102352.6665-3-liuqi115@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Wangming Shao <shaowangming@h-partners.com>
Reviewed-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: Yang Jihong <yangjihong1@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/Makefile | 2 +-
drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 409 +++++++++++++++++++
include/linux/cpuhotplug.h | 3 +
3 files changed, 413 insertions(+), 1 deletion(-)
create mode 100644 drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index ad0e8110f373..a3522abb3975 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
- hisi_uncore_pa_pmu.o \
+ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o \
hisi_uncore_l3t_pmu.o \
hisi_uncore_lpddrc_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
new file mode 100644
index 000000000000..a9bb73f76be4
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HiSilicon SoC CPA(Coherency Protocol Agent) hardware event counters support
+ *
+ * Copyright (C) 2022 HiSilicon Limited
+ * Author: Qi Liu <liuqi115@huawei.com>
+ *
+ * This code is based on the uncore PMUs like arm-cci and arm-ccn.
+ */
+
+#define pr_fmt(fmt) "cpa pmu: " fmt
+#include <linux/acpi.h>
+#include <linux/bug.h>
+#include <linux/cpuhotplug.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+
+#include "hisi_uncore_pmu.h"
+
+/* CPA register definition */
+#define CPA_PERF_CTRL 0x1c00
+#define CPA_EVENT_CTRL 0x1c04
+#define CPA_INT_MASK 0x1c70
+#define CPA_INT_STATUS 0x1c78
+#define CPA_INT_CLEAR 0x1c7c
+#define CPA_EVENT_TYPE0 0x1c80
+#define CPA_VERSION 0x1cf0
+#define CPA_CNT0_LOWER 0x1d00
+#define CPA_CFG_REG 0x0534
+
+/* CPA operation command */
+#define CPA_PERF_CTRL_EN BIT_ULL(0)
+#define CPA_EVTYPE_MASK 0xffUL
+#define CPA_PM_CTRL BIT_ULL(9)
+
+/* CPA has 8-counters */
+#define CPA_NR_COUNTERS 0x8
+#define CPA_COUNTER_BITS 64
+#define CPA_NR_EVENTS 0xff
+#define CPA_REG_OFFSET 0x8
+
+static u32 hisi_cpa_pmu_get_counter_offset(int idx)
+{
+ return (CPA_CNT0_LOWER + idx * CPA_REG_OFFSET);
+}
+
+static u64 hisi_cpa_pmu_read_counter(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc)
+{
+ return readq(cpa_pmu->base + hisi_cpa_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_cpa_pmu_write_counter(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc, u64 val)
+{
+ writeq(val, cpa_pmu->base + hisi_cpa_pmu_get_counter_offset(hwc->idx));
+}
+
+static void hisi_cpa_pmu_write_evtype(struct hisi_pmu *cpa_pmu, int idx,
+ u32 type)
+{
+ u32 reg, reg_idx, shift, val;
+
+ /*
+ * Select the appropriate event select register(CPA_EVENT_TYPE0/1).
+ * There are 2 event select registers for the 8 hardware counters.
+ * Event code is 8-bits and for the former 4 hardware counters,
+ * CPA_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
+ * CPA_EVENT_TYPE1 is chosen.
+ */
+ reg = CPA_EVENT_TYPE0 + (idx / 4) * 4;
+ reg_idx = idx % 4;
+ shift = CPA_REG_OFFSET * reg_idx;
+
+ /* Write event code to CPA_EVENT_TYPEx Register */
+ val = readl(cpa_pmu->base + reg);
+ val &= ~(CPA_EVTYPE_MASK << shift);
+ val |= type << shift;
+ writel(val, cpa_pmu->base + reg);
+}
+
+static void hisi_cpa_pmu_start_counters(struct hisi_pmu *cpa_pmu)
+{
+ u32 val;
+
+ val = readl(cpa_pmu->base + CPA_PERF_CTRL);
+ val |= CPA_PERF_CTRL_EN;
+ writel(val, cpa_pmu->base + CPA_PERF_CTRL);
+}
+
+static void hisi_cpa_pmu_stop_counters(struct hisi_pmu *cpa_pmu)
+{
+ u32 val;
+
+ val = readl(cpa_pmu->base + CPA_PERF_CTRL);
+ val &= ~(CPA_PERF_CTRL_EN);
+ writel(val, cpa_pmu->base + CPA_PERF_CTRL);
+}
+
+static void hisi_cpa_pmu_disable_pm(struct hisi_pmu *cpa_pmu)
+{
+ u32 val;
+
+ val = readl(cpa_pmu->base + CPA_CFG_REG);
+ val |= CPA_PM_CTRL;
+ writel(val, cpa_pmu->base + CPA_CFG_REG);
+}
+
+static void hisi_cpa_pmu_enable_pm(struct hisi_pmu *cpa_pmu)
+{
+ u32 val;
+
+ val = readl(cpa_pmu->base + CPA_CFG_REG);
+ val &= ~(CPA_PM_CTRL);
+ writel(val, cpa_pmu->base + CPA_CFG_REG);
+}
+
+static void hisi_cpa_pmu_enable_counter(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Enable counter index in CPA_EVENT_CTRL register */
+ val = readl(cpa_pmu->base + CPA_EVENT_CTRL);
+ val |= 1 << hwc->idx;
+ writel(val, cpa_pmu->base + CPA_EVENT_CTRL);
+}
+
+static void hisi_cpa_pmu_disable_counter(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Clear counter index in CPA_EVENT_CTRL register */
+ val = readl(cpa_pmu->base + CPA_EVENT_CTRL);
+ val &= ~(1UL << hwc->idx);
+ writel(val, cpa_pmu->base + CPA_EVENT_CTRL);
+}
+
+static void hisi_cpa_pmu_enable_counter_int(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 0 to enable interrupt */
+ val = readl(cpa_pmu->base + CPA_INT_MASK);
+ val &= ~(1UL << hwc->idx);
+ writel(val, cpa_pmu->base + CPA_INT_MASK);
+}
+
+static void hisi_cpa_pmu_disable_counter_int(struct hisi_pmu *cpa_pmu,
+ struct hw_perf_event *hwc)
+{
+ u32 val;
+
+ /* Write 1 to mask interrupt */
+ val = readl(cpa_pmu->base + CPA_INT_MASK);
+ val |= 1 << hwc->idx;
+ writel(val, cpa_pmu->base + CPA_INT_MASK);
+}
+
+static u32 hisi_cpa_pmu_get_int_status(struct hisi_pmu *cpa_pmu)
+{
+ return readl(cpa_pmu->base + CPA_INT_STATUS);
+}
+
+static void hisi_cpa_pmu_clear_int_status(struct hisi_pmu *cpa_pmu, int idx)
+{
+ writel(1 << idx, cpa_pmu->base + CPA_INT_CLEAR);
+}
+
+static const struct acpi_device_id hisi_cpa_pmu_acpi_match[] = {
+ { "HISI0281", },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, hisi_cpa_pmu_acpi_match);
+
+static int hisi_cpa_pmu_init_data(struct platform_device *pdev,
+ struct hisi_pmu *cpa_pmu)
+{
+ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
+ &cpa_pmu->sicl_id)) {
+ dev_err(&pdev->dev, "Can not read sicl-id\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
+ &cpa_pmu->index_id)) {
+ dev_err(&pdev->dev, "Cannot read idx-id\n");
+ return -EINVAL;
+ }
+
+ cpa_pmu->ccl_id = -1;
+ cpa_pmu->sccl_id = -1;
+ cpa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(cpa_pmu->base))
+ return PTR_ERR(cpa_pmu->base);
+
+ cpa_pmu->identifier = readl(cpa_pmu->base + CPA_VERSION);
+
+ return 0;
+}
+
+static struct attribute *hisi_cpa_pmu_format_attr[] = {
+ HISI_PMU_FORMAT_ATTR(event, "config:0-15"),
+ NULL
+};
+
+static const struct attribute_group hisi_cpa_pmu_format_group = {
+ .name = "format",
+ .attrs = hisi_cpa_pmu_format_attr,
+};
+
+static struct attribute *hisi_cpa_pmu_events_attr[] = {
+ HISI_PMU_EVENT_ATTR(cpa_cycles, 0x00),
+ HISI_PMU_EVENT_ATTR(cpa_p1_wr_dat, 0x61),
+ HISI_PMU_EVENT_ATTR(cpa_p1_rd_dat, 0x62),
+ HISI_PMU_EVENT_ATTR(cpa_p0_wr_dat, 0xE1),
+ HISI_PMU_EVENT_ATTR(cpa_p0_rd_dat, 0xE2),
+ NULL
+};
+
+static const struct attribute_group hisi_cpa_pmu_events_group = {
+ .name = "events",
+ .attrs = hisi_cpa_pmu_events_attr,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_cpa_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL
+};
+
+static const struct attribute_group hisi_cpa_pmu_cpumask_attr_group = {
+ .attrs = hisi_cpa_pmu_cpumask_attrs,
+};
+
+static struct device_attribute hisi_cpa_pmu_identifier_attr =
+ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL);
+
+static struct attribute *hisi_cpa_pmu_identifier_attrs[] = {
+ &hisi_cpa_pmu_identifier_attr.attr,
+ NULL
+};
+
+static const struct attribute_group hisi_cpa_pmu_identifier_group = {
+ .attrs = hisi_cpa_pmu_identifier_attrs,
+};
+
+static const struct attribute_group *hisi_cpa_pmu_attr_groups[] = {
+ &hisi_cpa_pmu_format_group,
+ &hisi_cpa_pmu_events_group,
+ &hisi_cpa_pmu_cpumask_attr_group,
+ &hisi_cpa_pmu_identifier_group,
+ NULL
+};
+
+static const struct hisi_uncore_ops hisi_uncore_cpa_pmu_ops = {
+ .write_evtype = hisi_cpa_pmu_write_evtype,
+ .get_event_idx = hisi_uncore_pmu_get_event_idx,
+ .start_counters = hisi_cpa_pmu_start_counters,
+ .stop_counters = hisi_cpa_pmu_stop_counters,
+ .enable_counter = hisi_cpa_pmu_enable_counter,
+ .disable_counter = hisi_cpa_pmu_disable_counter,
+ .enable_counter_int = hisi_cpa_pmu_enable_counter_int,
+ .disable_counter_int = hisi_cpa_pmu_disable_counter_int,
+ .write_counter = hisi_cpa_pmu_write_counter,
+ .read_counter = hisi_cpa_pmu_read_counter,
+ .get_int_status = hisi_cpa_pmu_get_int_status,
+ .clear_int_status = hisi_cpa_pmu_clear_int_status,
+};
+
+static int hisi_cpa_pmu_dev_probe(struct platform_device *pdev,
+ struct hisi_pmu *cpa_pmu)
+{
+ int ret;
+
+ ret = hisi_cpa_pmu_init_data(pdev, cpa_pmu);
+ if (ret)
+ return ret;
+
+ ret = hisi_uncore_pmu_init_irq(cpa_pmu, pdev);
+ if (ret)
+ return ret;
+
+ cpa_pmu->counter_bits = CPA_COUNTER_BITS;
+ cpa_pmu->check_event = CPA_NR_EVENTS;
+ cpa_pmu->pmu_events.attr_groups = hisi_cpa_pmu_attr_groups;
+ cpa_pmu->ops = &hisi_uncore_cpa_pmu_ops;
+ cpa_pmu->num_counters = CPA_NR_COUNTERS;
+ cpa_pmu->dev = &pdev->dev;
+ cpa_pmu->on_cpu = -1;
+
+ return 0;
+}
+
+static int hisi_cpa_pmu_probe(struct platform_device *pdev)
+{
+ struct hisi_pmu *cpa_pmu;
+ char *name;
+ int ret;
+
+ cpa_pmu = devm_kzalloc(&pdev->dev, sizeof(*cpa_pmu), GFP_KERNEL);
+ if (!cpa_pmu)
+ return -ENOMEM;
+
+ ret = hisi_cpa_pmu_dev_probe(pdev, cpa_pmu);
+ if (ret)
+ return ret;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_cpa%u",
+ cpa_pmu->sicl_id, cpa_pmu->index_id);
+ if (!name)
+ return -ENOMEM;
+
+ cpa_pmu->pmu = (struct pmu) {
+ .name = name,
+ .module = THIS_MODULE,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = hisi_uncore_pmu_event_init,
+ .pmu_enable = hisi_uncore_pmu_enable,
+ .pmu_disable = hisi_uncore_pmu_disable,
+ .add = hisi_uncore_pmu_add,
+ .del = hisi_uncore_pmu_del,
+ .start = hisi_uncore_pmu_start,
+ .stop = hisi_uncore_pmu_stop,
+ .read = hisi_uncore_pmu_read,
+ .attr_groups = cpa_pmu->pmu_events.attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ /* Power Management should be disabled before using CPA PMU. */
+ hisi_cpa_pmu_disable_pm(cpa_pmu);
+ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
+ &cpa_pmu->node);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
+ hisi_cpa_pmu_enable_pm(cpa_pmu);
+ return ret;
+ }
+
+ ret = perf_pmu_register(&cpa_pmu->pmu, name, -1);
+ if (ret) {
+ dev_err(cpa_pmu->dev, "PMU register failed\n");
+ cpuhp_state_remove_instance_nocalls(
+ CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node);
+ hisi_cpa_pmu_enable_pm(cpa_pmu);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, cpa_pmu);
+ return ret;
+}
+
+static int hisi_cpa_pmu_remove(struct platform_device *pdev)
+{
+ struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&cpa_pmu->pmu);
+ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
+ &cpa_pmu->node);
+ hisi_cpa_pmu_enable_pm(cpa_pmu);
+ return 0;
+}
+
+static struct platform_driver hisi_cpa_pmu_driver = {
+ .driver = {
+ .name = "hisi_cpa_pmu",
+ .acpi_match_table = ACPI_PTR(hisi_cpa_pmu_acpi_match),
+ .suppress_bind_attrs = true,
+ },
+ .probe = hisi_cpa_pmu_probe,
+ .remove = hisi_cpa_pmu_remove,
+};
+
+static int __init hisi_cpa_pmu_module_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
+ "AP_PERF_ARM_HISI_CPA_ONLINE",
+ hisi_uncore_pmu_online_cpu,
+ hisi_uncore_pmu_offline_cpu);
+ if (ret) {
+ pr_err("setup hotplug failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = platform_driver_register(&hisi_cpa_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
+
+ return ret;
+}
+module_init(hisi_cpa_pmu_module_init);
+
+static void __exit hisi_cpa_pmu_module_exit(void)
+{
+ platform_driver_unregister(&hisi_cpa_pmu_driver);
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
+}
+module_exit(hisi_cpa_pmu_module_exit);
+
+MODULE_DESCRIPTION("HiSilicon SoC CPA PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Qi Liu <liuqi115@huawei.com>");
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index f4078abc061f..ee782c3cb7f3 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -158,6 +158,9 @@ enum cpuhp_state {
CPUHP_AP_PERF_S390_SF_ONLINE,
CPUHP_AP_PERF_ARM_CCI_ONLINE,
CPUHP_AP_PERF_ARM_CCN_ONLINE,
+ #ifndef __GENKSYMS__
+ CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
+ #endif
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
--
2.27.0

View File

@ -0,0 +1,48 @@
From b860fa9563bef6669732959cf9fc9733b40a9721 Mon Sep 17 00:00:00 2001
From: Yicong Yang <yangyicong@hisilicon.com>
Date: Thu, 17 Nov 2022 16:41:33 +0800
Subject: [PATCH 33/55] drivers/perf: hisi: Fix some event id for hisi-pcie-pmu
mainline inclusion
from mainline-v6.2-rc1
commit 6b4bb4f38dbfe85247f006f06135ba46450d5bf0
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b4bb4f38dbfe85247f006f06135ba46450d5bf0
----------------------------------------------------------------------------
Some event id of hisi-pcie-pmu is incorrect, fix them.
Fixes: 8404b0fbc7fb ("drivers/perf: hisi: Add driver for HiSilicon PCIe PMU")
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20221117084136.53572-2-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_pcie_pmu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index 1e9e841cfe95..c115f5c77acb 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -696,10 +696,10 @@ static struct attribute *hisi_pcie_pmu_events_attr[] = {
HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_cnt, 0x10210),
HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_latency, 0x0011),
HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_cnt, 0x10011),
- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x1005),
- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x11005),
- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x2004),
- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x12004),
+ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x0804),
+ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x10804),
+ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x0405),
+ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x10405),
NULL
};
--
2.27.0

View File

@ -0,0 +1,129 @@
From 73bd937d975076c3f7754919d49d2610401dcf1b Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Date: Tue, 18 Jun 2019 16:06:08 -0300
Subject: [PATCH 34/55] docs: perf: move to the admin-guide
mainline inclusion
from mainline-v5.3-rc1
commit 59809fe88224db24432ad50e62fd8d5f0df738a1
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=59809fe88224db24432ad50e62fd8d5f0df738a1
-------------------------------------------------------------
The perf infrastructure is used for userspace to track issues.
At least a good part of what's described here is related to
it.
So, add it to the admin-guide.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
Documentation/admin-guide/index.rst | 1 +
Documentation/{ => admin-guide}/perf/arm-ccn.rst | 0
Documentation/{ => admin-guide}/perf/arm_dsu_pmu.rst | 0
Documentation/{ => admin-guide}/perf/hisi-pmu.rst | 0
Documentation/{ => admin-guide}/perf/index.rst | 2 --
Documentation/{ => admin-guide}/perf/qcom_l2_pmu.rst | 0
Documentation/{ => admin-guide}/perf/qcom_l3_pmu.rst | 0
Documentation/{ => admin-guide}/perf/xgene-pmu.rst | 0
MAINTAINERS | 4 ++--
drivers/perf/qcom_l3_pmu.c | 2 +-
10 files changed, 4 insertions(+), 5 deletions(-)
rename Documentation/{ => admin-guide}/perf/arm-ccn.rst (100%)
rename Documentation/{ => admin-guide}/perf/arm_dsu_pmu.rst (100%)
rename Documentation/{ => admin-guide}/perf/hisi-pmu.rst (100%)
rename Documentation/{ => admin-guide}/perf/index.rst (95%)
rename Documentation/{ => admin-guide}/perf/qcom_l2_pmu.rst (100%)
rename Documentation/{ => admin-guide}/perf/qcom_l3_pmu.rst (100%)
rename Documentation/{ => admin-guide}/perf/xgene-pmu.rst (100%)
diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst
index 89abc5057349..b75b6ae6f662 100644
--- a/Documentation/admin-guide/index.rst
+++ b/Documentation/admin-guide/index.rst
@@ -38,6 +38,7 @@ problems and bugs in particular.
ramoops
dynamic-debug-howto
init
+ perf/index
This is the beginning of a section with information of interest to
application developers. Documents covering various aspects of the kernel
diff --git a/Documentation/perf/arm-ccn.rst b/Documentation/admin-guide/perf/arm-ccn.rst
similarity index 100%
rename from Documentation/perf/arm-ccn.rst
rename to Documentation/admin-guide/perf/arm-ccn.rst
diff --git a/Documentation/perf/arm_dsu_pmu.rst b/Documentation/admin-guide/perf/arm_dsu_pmu.rst
similarity index 100%
rename from Documentation/perf/arm_dsu_pmu.rst
rename to Documentation/admin-guide/perf/arm_dsu_pmu.rst
diff --git a/Documentation/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
similarity index 100%
rename from Documentation/perf/hisi-pmu.rst
rename to Documentation/admin-guide/perf/hisi-pmu.rst
diff --git a/Documentation/perf/index.rst b/Documentation/admin-guide/perf/index.rst
similarity index 95%
rename from Documentation/perf/index.rst
rename to Documentation/admin-guide/perf/index.rst
index 4bf848e27f26..9d445451ea18 100644
--- a/Documentation/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -1,5 +1,3 @@
-:orphan:
-
===========================
Performance monitor support
===========================
diff --git a/Documentation/perf/qcom_l2_pmu.rst b/Documentation/admin-guide/perf/qcom_l2_pmu.rst
similarity index 100%
rename from Documentation/perf/qcom_l2_pmu.rst
rename to Documentation/admin-guide/perf/qcom_l2_pmu.rst
diff --git a/Documentation/perf/qcom_l3_pmu.rst b/Documentation/admin-guide/perf/qcom_l3_pmu.rst
similarity index 100%
rename from Documentation/perf/qcom_l3_pmu.rst
rename to Documentation/admin-guide/perf/qcom_l3_pmu.rst
diff --git a/Documentation/perf/xgene-pmu.rst b/Documentation/admin-guide/perf/xgene-pmu.rst
similarity index 100%
rename from Documentation/perf/xgene-pmu.rst
rename to Documentation/admin-guide/perf/xgene-pmu.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 600f432e2e16..e9302e09600b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1040,7 +1040,7 @@ APPLIED MICRO (APM) X-GENE SOC PMU
M: Tai Nguyen <ttnguyen@apm.com>
S: Supported
F: drivers/perf/xgene_pmu.c
-F: Documentation/perf/xgene-pmu.rst
+F: Documentation/admin-guide/perf/xgene-pmu.rst
F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
APTINA CAMERA SENSOR PLL
@@ -6666,7 +6666,7 @@ W: http://www.hisilicon.com
F: Documentation/admin-guide/perf/hisi-pcie-pmu.rst
F: Documentation/admin-guide/perf/hisi-pmu.rst
F: drivers/perf/hisilicon
-F: Documentation/perf/hisi-pmu.rst
+F: Documentation/admin-guide/perf/hisi-pmu.rst
HISILICON PTT DRIVER
M: Yicong Yang <yangyicong@hisilicon.com>
diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c
index cc88dc92577e..6cefee509e57 100644
--- a/drivers/perf/qcom_l3_pmu.c
+++ b/drivers/perf/qcom_l3_pmu.c
@@ -7,7 +7,7 @@
* the slices. User space needs to aggregate to individual counts to provide
* a global picture.
*
- * See Documentation/perf/qcom_l3_pmu.rst for more details.
+ * See Documentation/admin-guide/perf/qcom_l3_pmu.rst for more details.
*
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
--
2.27.0

View File

@ -0,0 +1,96 @@
From 4f573c490bf3b2880b8c93a20d2a9ef0d0b90c90 Mon Sep 17 00:00:00 2001
From: Shaokun Zhang <zhangshaokun@hisilicon.com>
Date: Mon, 8 Mar 2021 14:50:37 +0800
Subject: [PATCH 35/55] docs: perf: Add new description on HiSilicon uncore PMU
v2
mainline inclusion
from mainline-v5.13-rc1
commit 9b86b1b41e0f48b5b25918e07aeceb00e13d1ce2
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b86b1b41e0f48b5b25918e07aeceb00e13d1ce2
--------------------------------------------------------------------
Some news functions are added on HiSilicon uncore PMUs. Document them
to provide guidance on how to use them.
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-10-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
Documentation/admin-guide/perf/hisi-pmu.rst | 49 +++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
index 404a5c3d9d00..3b3120e2dd9e 100644
--- a/Documentation/admin-guide/perf/hisi-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pmu.rst
@@ -53,6 +53,55 @@ Example usage of perf::
$# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5
+For HiSilicon uncore PMU v2 whose identifier is 0x30, the topology is the same
+as PMU v1, but some new functions are added to the hardware.
+
+(a) L3C PMU supports filtering by core/thread within the cluster which can be
+specified as a bitmap.
+ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5
+This will only count the operations from core/thread 0 and 1 in this cluster.
+
+(b) Tracetag allow the user to chose to count only read, write or atomic
+operations via the tt_req parameeter in perf. The default value counts all
+operations. tt_req is 3bits, 3'b100 represents read operations, 3'b101
+represents write operations, 3'b110 represents atomic store operations and
+3'b111 represents atomic non-store operations, other values are reserved.
+ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5
+This will only count the read operations in this cluster.
+
+(c) Datasrc allows the user to check where the data comes from. It is 5 bits.
+Some important codes are as follows:
+5'b00001: comes from L3C in this die;
+5'b01000: comes from L3C in the cross-die;
+5'b01001: comes from L3C which is in another socket;
+5'b01110: comes from the local DDR;
+5'b01111: comes from the cross-die DDR;
+5'b10000: comes from cross-socket DDR;
+etc, it is mainly helpful to find that the data source is nearest from the CPU
+cores. If datasrc_cfg is used in the multi-chips, the datasrc_skt shall be
+configured in perf command.
+ $# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/,
+ hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5
+
+(d)Some HiSilicon SoCs encapsulate multiple CPU and IO dies. Each CPU die
+contains several Compute Clusters (CCLs). The I/O dies are called Super I/O
+clusters (SICL) containing multiple I/O clusters (ICLs). Each CCL/ICL in the
+SoC has a unique ID. Each ID is 11bits, include a 6-bit SCCL-ID and 5-bit
+CCL/ICL-ID. For I/O die, the ICL-ID is followed by:
+5'b00000: I/O_MGMT_ICL;
+5'b00001: Network_ICL;
+5'b00011: HAC_ICL;
+5'b10000: PCIe_ICL;
+
+Users could configure IDs to count data come from specific CCL/ICL, by setting
+srcid_cmd & srcid_msk, and data desitined for specific CCL/ICL by setting
+tgtid_cmd & tgtid_msk. A set bit in srcid_msk/tgtid_msk means the PMU will not
+check the bit when matching against the srcid_cmd/tgtid_cmd.
+
+If all of these options are disabled, it can works by the default value that
+doesn't distinguish the filter condition and ID information and will return
+the total counter values in the PMU counters.
+
The current driver does not support sampling. So "perf record" is unsupported.
Also attach to a task is unsupported as the events are all uncore.
--
2.27.0

View File

@ -0,0 +1,145 @@
From 3f70f78b4853cac77143fe82e99e5375628f8702 Mon Sep 17 00:00:00 2001
From: Qi Liu <liuqi115@huawei.com>
Date: Thu, 2 Dec 2021 16:06:32 +0800
Subject: [PATCH 36/55] docs: perf: Add description for HiSilicon PCIe PMU
driver
mainline inclusion
from mainline-v5.17-rc1
commit c8602008e247f5603317c16f076565a96715e1ba
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c8602008e247f5603317c16f076565a96715e1ba
------------------------------------------------------------------------
PCIe PMU Root Complex Integrated End Point(RCiEP) device is supported on
HiSilicon HIP09 platform. Document it to provide guidance on how to
use it.
Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Reviewed-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Link: https://lore.kernel.org/r/20211202080633.2919-2-liuqi115@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
.../admin-guide/perf/hisi-pcie-pmu.rst | 106 ++++++++++++++++++
1 file changed, 106 insertions(+)
create mode 100644 Documentation/admin-guide/perf/hisi-pcie-pmu.rst
diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
new file mode 100644
index 000000000000..294ebbdb22af
--- /dev/null
+++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
@@ -0,0 +1,106 @@
+================================================
+HiSilicon PCIe Performance Monitoring Unit (PMU)
+================================================
+
+On Hip09, HiSilicon PCIe Performance Monitoring Unit (PMU) could monitor
+bandwidth, latency, bus utilization and buffer occupancy data of PCIe.
+
+Each PCIe Core has a PMU to monitor multi Root Ports of this PCIe Core and
+all Endpoints downstream these Root Ports.
+
+
+HiSilicon PCIe PMU driver
+=========================
+
+The PCIe PMU driver registers a perf PMU with the name of its sicl-id and PCIe
+Core id.::
+
+ /sys/bus/event_source/hisi_pcie<sicl>_<core>
+
+PMU driver provides description of available events and filter options in sysfs,
+see /sys/bus/event_source/devices/hisi_pcie<sicl>_<core>.
+
+The "format" directory describes all formats of the config (events) and config1
+(filter options) fields of the perf_event_attr structure. The "events" directory
+describes all documented events shown in perf list.
+
+The "identifier" sysfs file allows users to identify the version of the
+PMU hardware device.
+
+The "bus" sysfs file allows users to get the bus number of Root Ports
+monitored by PMU.
+
+Example usage of perf::
+
+ $# perf list
+ hisi_pcie0_0/rx_mwr_latency/ [kernel PMU event]
+ hisi_pcie0_0/rx_mwr_cnt/ [kernel PMU event]
+ ------------------------------------------
+
+ $# perf stat -e hisi_pcie0_0/rx_mwr_latency/
+ $# perf stat -e hisi_pcie0_0/rx_mwr_cnt/
+ $# perf stat -g -e hisi_pcie0_0/rx_mwr_latency/ -e hisi_pcie0_0/rx_mwr_cnt/
+
+The current driver does not support sampling. So "perf record" is unsupported.
+Also attach to a task is unsupported for PCIe PMU.
+
+Filter options
+--------------
+
+1. Target filter
+PMU could only monitor the performance of traffic downstream target Root Ports
+or downstream target Endpoint. PCIe PMU driver support "port" and "bdf"
+interfaces for users, and these two interfaces aren't supported at the same
+time.
+
+-port
+"port" filter can be used in all PCIe PMU events, target Root Port can be
+selected by configuring the 16-bits-bitmap "port". Multi ports can be selected
+for AP-layer-events, and only one port can be selected for TL/DL-layer-events.
+
+For example, if target Root Port is 0000:00:00.0 (x8 lanes), bit0 of bitmap
+should be set, port=0x1; if target Root Port is 0000:00:04.0 (x4 lanes),
+bit8 is set, port=0x100; if these two Root Ports are both monitored, port=0x101.
+
+Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_0/rx_mwr_latency,port=0x1/ sleep 5
+
+-bdf
+
+"bdf" filter can only be used in bandwidth events, target Endpoint is selected
+by configuring BDF to "bdf". Counter only counts the bandwidth of message
+requested by target Endpoint.
+
+For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0.
+
+Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,bdf=0x3900/ sleep 5
+
+2. Trigger filter
+Event statistics start when the first time TLP length is greater/smaller
+than trigger condition. You can set the trigger condition by writing "trig_len",
+and set the trigger mode by writing "trig_mode". This filter can only be used
+in bandwidth events.
+
+For example, "trig_len=4" means trigger condition is 2^4 DW, "trig_mode=0"
+means statistics start when TLP length > trigger condition, "trig_mode=1"
+means start when TLP length < condition.
+
+Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5
+
+3. Threshold filter
+Counter counts when TLP length within the specified range. You can set the
+threshold by writing "thr_len", and set the threshold mode by writing
+"thr_mode". This filter can only be used in bandwidth events.
+
+For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means
+counter counts when TLP length >= threshold, and "thr_mode=1" means counts
+when TLP length < threshold.
+
+Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
--
2.27.0

View File

@ -0,0 +1,71 @@
From d1ff276b62baa5fd8138f2432bed59773702df7a Mon Sep 17 00:00:00 2001
From: Qi Liu <liuqi115@huawei.com>
Date: Mon, 29 Mar 2021 20:32:01 +0800
Subject: [PATCH 37/55] docs: perf: Address some html build warnings
mainline inclusion
from mainline-v5.13-rc1
commit b88f5e9792cc320a511697dcba8890d032ee3ed3
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b88f5e9792cc320a511697dcba8890d032ee3ed3
----------------------------------------------------------------------------
Fix following html build warnings:
Documentation/admin-guide/perf/hisi-pmu.rst:61: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/hisi-pmu.rst:62: WARNING: Block quote ends without a blank line; unexpected unindent.
Documentation/admin-guide/perf/hisi-pmu.rst:69: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/hisi-pmu.rst:70: WARNING: Block quote ends without a blank line; unexpected unindent.
Documentation/admin-guide/perf/hisi-pmu.rst:83: WARNING: Unexpected indentation.
Fixes: 9b86b1b41e0f ("docs: perf: Add new description on HiSilicon uncore PMU v2")
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Qi Liu <liuqi115@huawei.com>
Link: https://lore.kernel.org/r/1617021121-31450-1-git-send-email-liuqi115@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
Documentation/admin-guide/perf/hisi-pmu.rst | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
index 3b3120e2dd9e..546979360513 100644
--- a/Documentation/admin-guide/perf/hisi-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pmu.rst
@@ -57,16 +57,20 @@ For HiSilicon uncore PMU v2 whose identifier is 0x30, the topology is the same
as PMU v1, but some new functions are added to the hardware.
(a) L3C PMU supports filtering by core/thread within the cluster which can be
-specified as a bitmap.
+specified as a bitmap::
+
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5
+
This will only count the operations from core/thread 0 and 1 in this cluster.
(b) Tracetag allow the user to chose to count only read, write or atomic
operations via the tt_req parameeter in perf. The default value counts all
operations. tt_req is 3bits, 3'b100 represents read operations, 3'b101
represents write operations, 3'b110 represents atomic store operations and
-3'b111 represents atomic non-store operations, other values are reserved.
+3'b111 represents atomic non-store operations, other values are reserved::
+
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5
+
This will only count the read operations in this cluster.
(c) Datasrc allows the user to check where the data comes from. It is 5 bits.
@@ -79,7 +83,8 @@ Some important codes are as follows:
5'b10000: comes from cross-socket DDR;
etc, it is mainly helpful to find that the data source is nearest from the CPU
cores. If datasrc_cfg is used in the multi-chips, the datasrc_skt shall be
-configured in perf command.
+configured in perf command::
+
$# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/,
hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5
--
2.27.0

View File

@ -0,0 +1,43 @@
From 73918c84177dc0867dafd8bb3826fead1289425f Mon Sep 17 00:00:00 2001
From: Wan Jiabing <wanjiabing@vivo.com>
Date: Mon, 28 Feb 2022 11:16:56 +0800
Subject: [PATCH 38/55] docs: fix 'make htmldocs' warning in perf
mainline inclusion
from mainline-v5.18-rc1
commit 0d6356d6cdd0afeb546f4e8ca653748a8ec3ba26
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d6356d6cdd0afeb546f4e8ca653748a8ec3ba26
-------------------------------------------------------------------
Fix following 'make htmldocs' warnings:
./Documentation/admin-guide/perf/hisi-pcie-pmu.rst: WARNING:
document isn't included in any toctree
Fixes: c8602008e247 ("docs: perf: Add description for HiSilicon PCIe PMU driver")
Signed-off-by: Wan Jiabing <wanjiabing@vivo.com>
Reviewed-by: John Garry <john.garry@huawei.com>
Link: https://lore.kernel.org/r/20220228031700.1669086-1-wanjiabing@vivo.com
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
Documentation/admin-guide/perf/index.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index 9d445451ea18..5a9afa1263f6 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -6,6 +6,7 @@ Performance monitor support
:maxdepth: 1
hisi-pmu
+ hisi-pcie-pmu
qcom_l2_pmu
qcom_l3_pmu
arm-ccn
--
2.27.0

View File

@ -0,0 +1,99 @@
From f6ad3073186b182d495dc42c48baac26cb1c16f2 Mon Sep 17 00:00:00 2001
From: Yicong Yang <yangyicong@hisilicon.com>
Date: Thu, 17 Nov 2022 16:41:34 +0800
Subject: [PATCH 39/55] docs: perf: Fix PMU instance name of hisi-pcie-pmu
mainline inclusion
from mainline-v6.2-rc1
commit eb79f12b4c41dd2403a0d16772ee72fcd6416015
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eb79f12b4c41dd2403a0d16772ee72fcd6416015
--------------------------------------------------------------------
The PMU instance will be called hisi_pcie<sicl>_core<core> rather than
hisi_pcie<sicl>_<core>. Fix this in the documentation.
Fixes: c8602008e247 ("docs: perf: Add description for HiSilicon PCIe PMU driver")
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20221117084136.53572-3-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
.../admin-guide/perf/hisi-pcie-pmu.rst | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
index 294ebbdb22af..bbe66480ff85 100644
--- a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
@@ -15,10 +15,10 @@ HiSilicon PCIe PMU driver
The PCIe PMU driver registers a perf PMU with the name of its sicl-id and PCIe
Core id.::
- /sys/bus/event_source/hisi_pcie<sicl>_<core>
+ /sys/bus/event_source/hisi_pcie<sicl>_core<core>
PMU driver provides description of available events and filter options in sysfs,
-see /sys/bus/event_source/devices/hisi_pcie<sicl>_<core>.
+see /sys/bus/event_source/devices/hisi_pcie<sicl>_core<core>.
The "format" directory describes all formats of the config (events) and config1
(filter options) fields of the perf_event_attr structure. The "events" directory
@@ -33,13 +33,13 @@ monitored by PMU.
Example usage of perf::
$# perf list
- hisi_pcie0_0/rx_mwr_latency/ [kernel PMU event]
- hisi_pcie0_0/rx_mwr_cnt/ [kernel PMU event]
+ hisi_pcie0_core0/rx_mwr_latency/ [kernel PMU event]
+ hisi_pcie0_core0/rx_mwr_cnt/ [kernel PMU event]
------------------------------------------
- $# perf stat -e hisi_pcie0_0/rx_mwr_latency/
- $# perf stat -e hisi_pcie0_0/rx_mwr_cnt/
- $# perf stat -g -e hisi_pcie0_0/rx_mwr_latency/ -e hisi_pcie0_0/rx_mwr_cnt/
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency/
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_cnt/
+ $# perf stat -g -e hisi_pcie0_core0/rx_mwr_latency/ -e hisi_pcie0_core0/rx_mwr_cnt/
The current driver does not support sampling. So "perf record" is unsupported.
Also attach to a task is unsupported for PCIe PMU.
@@ -64,7 +64,7 @@ bit8 is set, port=0x100; if these two Root Ports are both monitored, port=0x101.
Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mwr_latency,port=0x1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency,port=0x1/ sleep 5
-bdf
@@ -76,7 +76,7 @@ For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0.
Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,bdf=0x3900/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,bdf=0x3900/ sleep 5
2. Trigger filter
Event statistics start when the first time TLP length is greater/smaller
@@ -90,7 +90,7 @@ means start when TLP length < condition.
Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5
3. Threshold filter
Counter counts when TLP length within the specified range. You can set the
@@ -103,4 +103,4 @@ when TLP length < threshold.
Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
--
2.27.0

View File

@ -0,0 +1,132 @@
From 57b8735c25b887a4233ddf7930c821acc78ca3f1 Mon Sep 17 00:00:00 2001
From: Yicong Yang <yangyicong@hisilicon.com>
Date: Thu, 17 Nov 2022 16:41:36 +0800
Subject: [PATCH 40/55] drivers/perf: hisi: Add TLP filter support
mainline inclusion
from mainline-v6.2-rc1
commit 17d573984d4d5ad73c7cb5edcf2024c585475b0c
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=17d573984d4d5ad73c7cb5edcf2024c585475b0c
-----------------------------------------------------------------------
The PMU support to filter the TLP when counting the bandwidth with below
options:
- only count the TLP headers
- only count the TLP payloads
- count both TLP headers and payloads
In the current driver it's default to count the TLP payloads only, which
will have an implicity side effects that on the traffic only have header
only TLPs, we'll get no data.
Make this user configuration through "len_mode" parameter and make it
default to count both TLP headers and payloads when user not specified.
Also update the documentation for it.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20221117084136.53572-5-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
.../admin-guide/perf/hisi-pcie-pmu.rst | 22 +++++++++++++++++--
drivers/perf/hisilicon/hisi_pcie_pmu.c | 14 +++++++++++-
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
index bbe66480ff85..6bace0e24c3f 100644
--- a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
@@ -101,6 +101,24 @@ For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means
counter counts when TLP length >= threshold, and "thr_mode=1" means counts
when TLP length < threshold.
-Example usage of perf::
+ Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
+
+4. TLP Length filter
+
+ When counting bandwidth, the data can be composed of certain parts of TLP
+ packets. You can specify it through "len_mode":
+
+ - 2'b00: Reserved (Do not use this since the behaviour is undefined)
+ - 2'b01: Bandwidth of TLP payloads
+ - 2'b10: Bandwidth of TLP headers
+ - 2'b11: Bandwidth of both TLP payloads and headers
+
+ For example, "len_mode=2" means only counting the bandwidth of TLP headers
+ and "len_mode=3" means the final bandwidth data is composed of both TLP
+ headers and payloads. Default value if not specified is 2'b11.
+
+ Example usage of perf::
- $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,len_mode=0x1/ sleep 5
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index c115f5c77acb..6ded72383bb6 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -47,10 +47,14 @@
#define HISI_PCIE_EVENT_M GENMASK_ULL(15, 0)
#define HISI_PCIE_THR_MODE_M GENMASK_ULL(27, 27)
#define HISI_PCIE_THR_M GENMASK_ULL(31, 28)
+#define HISI_PCIE_LEN_M GENMASK_ULL(35, 34)
#define HISI_PCIE_TARGET_M GENMASK_ULL(52, 36)
#define HISI_PCIE_TRIG_MODE_M GENMASK_ULL(53, 53)
#define HISI_PCIE_TRIG_M GENMASK_ULL(59, 56)
+/* Default config of TLP length mode, will count both TLP headers and payloads */
+#define HISI_PCIE_LEN_M_DEFAULT 3ULL
+
#define HISI_PCIE_MAX_COUNTERS 8
#define HISI_PCIE_REG_STEP 8
#define HISI_PCIE_THR_MAX_VAL 10
@@ -91,6 +95,7 @@ HISI_PCIE_PMU_FILTER_ATTR(thr_len, config1, 3, 0);
HISI_PCIE_PMU_FILTER_ATTR(thr_mode, config1, 4, 4);
HISI_PCIE_PMU_FILTER_ATTR(trig_len, config1, 8, 5);
HISI_PCIE_PMU_FILTER_ATTR(trig_mode, config1, 9, 9);
+HISI_PCIE_PMU_FILTER_ATTR(len_mode, config1, 11, 10);
HISI_PCIE_PMU_FILTER_ATTR(port, config2, 15, 0);
HISI_PCIE_PMU_FILTER_ATTR(bdf, config2, 31, 16);
@@ -218,8 +223,8 @@ static void hisi_pcie_pmu_config_filter(struct perf_event *event)
{
struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
+ u64 port, trig_len, thr_len, len_mode;
u64 reg = HISI_PCIE_INIT_SET;
- u64 port, trig_len, thr_len;
/* Config HISI_PCIE_EVENT_CTRL according to event. */
reg |= FIELD_PREP(HISI_PCIE_EVENT_M, hisi_pcie_get_real_event(event));
@@ -248,6 +253,12 @@ static void hisi_pcie_pmu_config_filter(struct perf_event *event)
reg |= HISI_PCIE_THR_EN;
}
+ len_mode = hisi_pcie_get_len_mode(event);
+ if (len_mode)
+ reg |= FIELD_PREP(HISI_PCIE_LEN_M, len_mode);
+ else
+ reg |= FIELD_PREP(HISI_PCIE_LEN_M, HISI_PCIE_LEN_M_DEFAULT);
+
hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, reg);
}
@@ -714,6 +725,7 @@ static struct attribute *hisi_pcie_pmu_format_attr[] = {
HISI_PCIE_PMU_FORMAT_ATTR(thr_mode, "config1:4"),
HISI_PCIE_PMU_FORMAT_ATTR(trig_len, "config1:5-8"),
HISI_PCIE_PMU_FORMAT_ATTR(trig_mode, "config1:9"),
+ HISI_PCIE_PMU_FORMAT_ATTR(len_mode, "config1:10-11"),
HISI_PCIE_PMU_FORMAT_ATTR(port, "config2:0-15"),
HISI_PCIE_PMU_FORMAT_ATTR(bdf, "config2:16-31"),
NULL
--
2.27.0

View File

@ -0,0 +1,71 @@
From b6b92242583b60e26a251765356143092000674a Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Thu, 8 Jun 2023 14:07:55 +0800
Subject: [PATCH 41/55] drivers/perf: hisi: Don't migrate perf to the CPU going
to teardown
mainline inclusion
from mainline-v6.5-rc1
commit 7a6a9f1c5a0a875a421db798d4b2ee022dc1ee1a
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7a6a9f1c5a0a875a421db798d4b2ee022dc1ee1a
----------------------------------------------------------------------
The driver needs to migrate the perf context if the current using CPU going
to teardown. By the time calling the cpuhp::teardown() callback the
cpu_online_mask() hasn't updated yet and still includes the CPU going to
teardown. In current driver's implementation we may migrate the context
to the teardown CPU and leads to the below calltrace:
...
[ 368.104662][ T932] task:cpuhp/0 state:D stack: 0 pid: 15 ppid: 2 flags:0x00000008
[ 368.113699][ T932] Call trace:
[ 368.116834][ T932] __switch_to+0x7c/0xbc
[ 368.120924][ T932] __schedule+0x338/0x6f0
[ 368.125098][ T932] schedule+0x50/0xe0
[ 368.128926][ T932] schedule_preempt_disabled+0x18/0x24
[ 368.134229][ T932] __mutex_lock.constprop.0+0x1d4/0x5dc
[ 368.139617][ T932] __mutex_lock_slowpath+0x1c/0x30
[ 368.144573][ T932] mutex_lock+0x50/0x60
[ 368.148579][ T932] perf_pmu_migrate_context+0x84/0x2b0
[ 368.153884][ T932] hisi_pcie_pmu_offline_cpu+0x90/0xe0 [hisi_pcie_pmu]
[ 368.160579][ T932] cpuhp_invoke_callback+0x2a0/0x650
[ 368.165707][ T932] cpuhp_thread_fun+0xe4/0x190
[ 368.170316][ T932] smpboot_thread_fn+0x15c/0x1a0
[ 368.175099][ T932] kthread+0x108/0x13c
[ 368.179012][ T932] ret_from_fork+0x10/0x18
...
Use function cpumask_any_but() to find one correct active cpu to fixes
this issue.
Fixes: 8404b0fbc7fb ("drivers/perf: hisi: Add driver for HiSilicon PCIe PMU")
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Yicong Yang <yangyicong@hisilicon.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/r/20230608114326.27649-1-hejunhao3@huawei.com
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_pcie_pmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index 6ded72383bb6..b4335bdb3c3e 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -686,7 +686,7 @@ static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
pcie_pmu->on_cpu = -1;
/* Choose a new CPU from all online cpus. */
- target = cpumask_first(cpu_online_mask);
+ target = cpumask_any_but(cpu_online_mask, cpu);
if (target >= nr_cpu_ids) {
pci_err(pcie_pmu->pdev, "There is no CPU to set\n");
return 0;
--
2.27.0

View File

@ -0,0 +1,210 @@
From fa73221de60d9d632d6a233f0a1a99b4350e0190 Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Mon, 21 Nov 2022 22:03:05 +0800
Subject: [PATCH 42/55] drivers/perf: fixed the issue that the kabi value
changed
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5KAX7
--------------------------------------------------------------------------
Fixed the issue that the kabi value changed when the HiSilicon PMU driver
added the enum variable in "enum cpuhp_state{}".
The hisi_pcie_pmu and hisi_cpa_pmu drivers to replace the explicit specify
hotplug events with dynamic allocation hotplug events(CPUHP_AP_ONLINE_DYN).
The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are
reserved for the dynamic allocation.
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: Yicong Yang <yangyicong@huawei.com>
Reviewed-by: Yang Jihong <yangjihong1@huawei.com>
Reviewed-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_pcie_pmu.c | 22 ++++++++++---------
drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 23 ++++++++++----------
include/linux/cpuhotplug.h | 6 -----
3 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index b4335bdb3c3e..ccbe995db1e4 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -19,6 +19,9 @@
#include <linux/pci.h>
#include <linux/perf_event.h>
+/* Dynamic CPU hotplug state used by PCIe PMU */
+static enum cpuhp_state hisi_pcie_pmu_online;
+
#define DRV_NAME "hisi_pcie_pmu"
/* Define registers */
#define HISI_PCIE_GLOBAL_CTRL 0x00
@@ -830,7 +833,7 @@ static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_p
if (ret)
goto err_iounmap;
- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node);
+ ret = cpuhp_state_add_instance(hisi_pcie_pmu_online, &pcie_pmu->node);
if (ret) {
pci_err(pdev, "Failed to register hotplug: %d\n", ret);
goto err_irq_unregister;
@@ -845,8 +848,7 @@ static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_p
return ret;
err_hotplug_unregister:
- cpuhp_state_remove_instance_nocalls(
- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_pcie_pmu_online, &pcie_pmu->node);
err_irq_unregister:
hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu);
@@ -862,8 +864,7 @@ static void hisi_pcie_uninit_pmu(struct pci_dev *pdev)
struct hisi_pcie_pmu *pcie_pmu = pci_get_drvdata(pdev);
perf_pmu_unregister(&pcie_pmu->pmu);
- cpuhp_state_remove_instance_nocalls(
- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_pcie_pmu_online, &pcie_pmu->node);
hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu);
iounmap(pcie_pmu->base);
}
@@ -934,18 +935,19 @@ static int __init hisi_pcie_module_init(void)
{
int ret;
- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE,
- "AP_PERF_ARM_HISI_PCIE_PMU_ONLINE",
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "perf/hisi/pcie:online",
hisi_pcie_pmu_online_cpu,
hisi_pcie_pmu_offline_cpu);
- if (ret) {
+ if (ret < 0) {
pr_err("Failed to setup PCIe PMU hotplug: %d\n", ret);
return ret;
}
+ hisi_pcie_pmu_online = ret;
ret = pci_register_driver(&hisi_pcie_pmu_driver);
if (ret)
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE);
+ cpuhp_remove_multi_state(hisi_pcie_pmu_online);
return ret;
}
@@ -954,7 +956,7 @@ module_init(hisi_pcie_module_init);
static void __exit hisi_pcie_module_exit(void)
{
pci_unregister_driver(&hisi_pcie_pmu_driver);
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE);
+ cpuhp_remove_multi_state(hisi_pcie_pmu_online);
}
module_exit(hisi_pcie_module_exit);
diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
index a9bb73f76be4..09839dae9b7c 100644
--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
@@ -19,6 +19,9 @@
#include "hisi_uncore_pmu.h"
+/* Dynamic CPU hotplug state used by CPA PMU */
+static enum cpuhp_state hisi_cpa_pmu_online;
+
/* CPA register definition */
#define CPA_PERF_CTRL 0x1c00
#define CPA_EVENT_CTRL 0x1c04
@@ -334,8 +337,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
/* Power Management should be disabled before using CPA PMU. */
hisi_cpa_pmu_disable_pm(cpa_pmu);
- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
- &cpa_pmu->node);
+ ret = cpuhp_state_add_instance(hisi_cpa_pmu_online, &cpa_pmu->node);
if (ret) {
dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
hisi_cpa_pmu_enable_pm(cpa_pmu);
@@ -345,8 +347,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
ret = perf_pmu_register(&cpa_pmu->pmu, name, -1);
if (ret) {
dev_err(cpa_pmu->dev, "PMU register failed\n");
- cpuhp_state_remove_instance_nocalls(
- CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_cpa_pmu_online, &cpa_pmu->node);
hisi_cpa_pmu_enable_pm(cpa_pmu);
return ret;
}
@@ -360,8 +361,7 @@ static int hisi_cpa_pmu_remove(struct platform_device *pdev)
struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev);
perf_pmu_unregister(&cpa_pmu->pmu);
- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
- &cpa_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_cpa_pmu_online, &cpa_pmu->node);
hisi_cpa_pmu_enable_pm(cpa_pmu);
return 0;
}
@@ -380,18 +380,19 @@ static int __init hisi_cpa_pmu_module_init(void)
{
int ret;
- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
- "AP_PERF_ARM_HISI_CPA_ONLINE",
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "pmu/hisi/cpa:online",
hisi_uncore_pmu_online_cpu,
hisi_uncore_pmu_offline_cpu);
- if (ret) {
+ if (ret < 0) {
pr_err("setup hotplug failed: %d\n", ret);
return ret;
}
+ hisi_cpa_pmu_online = ret;
ret = platform_driver_register(&hisi_cpa_pmu_driver);
if (ret)
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
+ cpuhp_remove_multi_state(hisi_cpa_pmu_online);
return ret;
}
@@ -400,7 +401,7 @@ module_init(hisi_cpa_pmu_module_init);
static void __exit hisi_cpa_pmu_module_exit(void)
{
platform_driver_unregister(&hisi_cpa_pmu_driver);
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
+ cpuhp_remove_multi_state(hisi_cpa_pmu_online);
}
module_exit(hisi_cpa_pmu_module_exit);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index ee782c3cb7f3..225b095a96db 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -158,17 +158,11 @@ enum cpuhp_state {
CPUHP_AP_PERF_S390_SF_ONLINE,
CPUHP_AP_PERF_ARM_CCI_ONLINE,
CPUHP_AP_PERF_ARM_CCN_ONLINE,
- #ifndef __GENKSYMS__
- CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
- #endif
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
- #ifndef __GENKSYMS__
- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE,
- #endif
CPUHP_AP_PERF_ARM_L2X0_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE,
--
2.27.0

View File

@ -0,0 +1,200 @@
From ed7d3223d519f6749ef72cb295e9ce61d55d722b Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Wed, 25 Oct 2023 17:49:20 +0800
Subject: [PATCH 43/55] drivers/perf: fixed kabi broken for SLLC and PA PMU
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
------------------------------------------------------------------------
Fixed the issue that the kabi value changed when the HiSilicon PMU driver
added the enum variable in "enum cpuhp_state{}".
The hisi_sllc_pmu and hisi_pa_pmu drivers to replace the explicit specify
hotplug events with dynamic allocation hotplug events(CPUHP_AP_ONLINE_DYN).
The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are
reserved for the dynamic allocation.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 25 +++++++++++--------
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 25 +++++++++++--------
include/linux/cpuhotplug.h | 2 --
3 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index f1e6b5cee075..8bab65d50316 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -46,6 +46,9 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
+/* Dynamic CPU hotplug state used by PA PMU */
+static enum cpuhp_state hisi_pa_pmu_online;
+
static void hisi_pa_pmu_enable_tracetag(struct perf_event *event)
{
struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu);
@@ -405,8 +408,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
if (!name)
return -ENOMEM;
- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
- &pa_pmu->node);
+ ret = cpuhp_state_add_instance(hisi_pa_pmu_online, &pa_pmu->node);
if (ret) {
dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
return ret;
@@ -430,8 +432,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
if (ret) {
dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
- &pa_pmu->node);
+ cpuhp_state_remove_instance(hisi_pa_pmu_online, &pa_pmu->node);
return ret;
}
@@ -444,8 +445,8 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev)
struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev);
perf_pmu_unregister(&pa_pmu->pmu);
- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
- &pa_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_pa_pmu_online, &pa_pmu->node);
+
return 0;
}
@@ -463,18 +464,20 @@ static int __init hisi_pa_pmu_module_init(void)
{
int ret;
- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
- "AP_PERF_ARM_HISI_PA_ONLINE",
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "perf/hisi/pa:online",
hisi_uncore_pmu_online_cpu,
hisi_uncore_pmu_offline_cpu);
- if (ret) {
+ if (ret < 0) {
pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret);
return ret;
}
+ hisi_pa_pmu_online = ret;
+
ret = platform_driver_register(&hisi_pa_pmu_driver);
if (ret)
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
+ cpuhp_remove_multi_state(hisi_pa_pmu_online);
return ret;
}
@@ -483,7 +486,7 @@ module_init(hisi_pa_pmu_module_init);
static void __exit hisi_pa_pmu_module_exit(void)
{
platform_driver_unregister(&hisi_pa_pmu_driver);
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
+ cpuhp_remove_multi_state(hisi_pa_pmu_online);
}
module_exit(hisi_pa_pmu_module_exit);
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 835ec3e2178f..71b199ec447a 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -48,6 +48,9 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
+/* Dynamic CPU hotplug state used by SLLC PMU */
+static enum cpuhp_state hisi_sllc_pmu_online;
+
static bool tgtid_is_valid(u32 max, u32 min)
{
return max > 0 && max >= min;
@@ -438,8 +441,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
if (!name)
return -ENOMEM;
- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
- &sllc_pmu->node);
+ ret = cpuhp_state_add_instance(hisi_sllc_pmu_online, &sllc_pmu->node);
if (ret) {
dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
return ret;
@@ -463,8 +465,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
if (ret) {
dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
- &sllc_pmu->node);
+ cpuhp_state_remove_instance(hisi_sllc_pmu_online, &sllc_pmu->node);
return ret;
}
@@ -478,8 +479,8 @@ static int hisi_sllc_pmu_remove(struct platform_device *pdev)
struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev);
perf_pmu_unregister(&sllc_pmu->pmu);
- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
- &sllc_pmu->node);
+ cpuhp_state_remove_instance_nocalls(hisi_sllc_pmu_online, &sllc_pmu->node);
+
return 0;
}
@@ -497,18 +498,20 @@ static int __init hisi_sllc_pmu_module_init(void)
{
int ret;
- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
- "AP_PERF_ARM_HISI_SLLC_ONLINE",
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "perf/hisi/sllc:online",
hisi_uncore_pmu_online_cpu,
hisi_uncore_pmu_offline_cpu);
- if (ret) {
+ if (ret < 0) {
pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret);
return ret;
}
+ hisi_sllc_pmu_online = ret;
+
ret = platform_driver_register(&hisi_sllc_pmu_driver);
if (ret)
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
+ cpuhp_remove_multi_state(hisi_sllc_pmu_online);
return ret;
}
@@ -517,7 +520,7 @@ module_init(hisi_sllc_pmu_module_init);
static void __exit hisi_sllc_pmu_module_exit(void)
{
platform_driver_unregister(&hisi_sllc_pmu_driver);
- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
+ cpuhp_remove_multi_state(hisi_sllc_pmu_online);
}
module_exit(hisi_sllc_pmu_module_exit);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 225b095a96db..d67c0035165c 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -161,8 +161,6 @@ enum cpuhp_state {
CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
- CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
- CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
CPUHP_AP_PERF_ARM_L2X0_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE,
CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE,
--
2.27.0

View File

@ -0,0 +1,39 @@
From 2ee9d506673f6abaee074312d2ae189fd941e58c Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Wed, 4 Jan 2023 19:55:09 +0800
Subject: [PATCH 44/55] perf: hisi: Fix read sccl_id and ccl_id error in TSV200
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I68F5A
CVE: NA
--------------------------------
In TSV200 platform, SCCL is Aff3[7:0], CCL is Aff2[7:0] if mt.
Fixes: 1af26389a3 ("perf: hisi: Fix read sccl_id and ccl_id error in some platform")
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: Yang Shen <shenyang39@huawei.com>
Reviewed-by: Yang Jihong <yangjihong1@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 9aaaf9cf2b2a..91d2da895924 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -440,7 +440,6 @@ static void hisi_read_sccl_and_ccl_id(int *scclp, int *cclp)
if (mt) {
switch (read_cpuid_part_number()) {
case HISI_CPU_PART_TSV110:
- case HISI_CPU_PART_TSV200:
case ARM_CPU_PART_CORTEX_A55:
sccl = aff2 >> 3;
ccl = aff2 & 0x7;
--
2.27.0

View File

@ -0,0 +1,86 @@
From 2bbf35baac46c41879f770e2273134192a565f86 Mon Sep 17 00:00:00 2001
From: Zhang Zekun <zhangzekun11@huawei.com>
Date: Sat, 4 Mar 2023 07:24:36 +0000
Subject: [PATCH 45/55] perf: hisi: Add configs for PMU isolation
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I6HRGK
------------------------------------------
Add CONFIG_HISI_L3T_PMU and CONFIG_HISI_LPDDRC_PMU to isolate features
of hisi pmu driver.
This patch isolates commit 0edc58409e30 and 6bf896bea639.
Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
drivers/perf/hisilicon/Kconfig
drivers/perf/hisilicon/Makefile
---
arch/arm64/configs/openeuler_defconfig | 2 ++
drivers/perf/hisilicon/Kconfig | 18 ++++++++++++++++++
drivers/perf/hisilicon/Makefile | 6 +++---
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index 6a7497f2df95..db461e4c2dae 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -5108,6 +5108,8 @@ CONFIG_QCOM_L3_PMU=y
CONFIG_XGENE_PMU=y
CONFIG_ARM_SPE_PMU=y
CONFIG_HISI_PMU=m
+CONFIG_HISI_L3T_PMU=m
+CONFIG_HISI_LPDDRC_PMU=m
CONFIG_HISI_PCIE_PMU=m
CONFIG_RAS=y
diff --git a/drivers/perf/hisilicon/Kconfig b/drivers/perf/hisilicon/Kconfig
index 5546218b5598..91a6e2463180 100644
--- a/drivers/perf/hisilicon/Kconfig
+++ b/drivers/perf/hisilicon/Kconfig
@@ -14,3 +14,21 @@ config HISI_PCIE_PMU
RCiEP devices.
Adds the PCIe PMU into perf events system for monitoring latency,
bandwidth etc.
+
+config HISI_L3T_PMU
+ tristate "HiSilicon SoC L3T PMU drivers"
+ depends on HISI_PMU
+ default n
+ help
+ Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home
+ Agent performance monitor and DDR Controller performance monitor.
+ L3T is a specialized PMU driver.
+
+config HISI_LPDDRC_PMU
+ tristate "HiSilicon SoC LDPPRC PMU drivers"
+ depends on HISI_PMU
+ default n
+ help
+ Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home
+ Agent performance monitor and DDR Controller performance monitor.
+ LPDDRC is a specialize PMU driver.
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index a3522abb3975..26d678eb3250 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \
- hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o \
- hisi_uncore_l3t_pmu.o \
- hisi_uncore_lpddrc_pmu.o
+ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o
obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
+obj-$(CONFIG_HISI_L3T_PMU) += hisi_uncore_l3t_pmu.o
+obj-$(CONFIG_HISI_LPDDRC_PMU) += hisi_uncore_lpddrc_pmu.o
--
2.27.0

View File

@ -0,0 +1,208 @@
From 021c239865727a9e633d04f3fc490426b51012ad Mon Sep 17 00:00:00 2001
From: Chen Jun <chenjun102@huawei.com>
Date: Tue, 23 May 2023 14:44:24 +0800
Subject: [PATCH 46/55] perf: hisi: Extract hisi_pmu_init
mainline inclusion
from mainline-v6.0-rc1
commit e500405dd15d956790859fa532c64d8186445372
category: cleanup
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e500405dd15d956790859fa532c64d8186445372
----------------------------------------------------------------------
Extract the initialization code of hisi_pmu->pmu into a function
Signed-off-by: Chen Jun <chenjun102@huawei.com>
Link: https://lore.kernel.org/r/20220516131601.48383-1-chenjun102@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 16 +---------------
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 16 +---------------
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 16 +---------------
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 16 +---------------
drivers/perf/hisilicon/hisi_uncore_pmu.c | 18 ++++++++++++++++++
drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 ++
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 15 +--------------
7 files changed, 25 insertions(+), 74 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 457ac6a1ad64..69d2b08847e2 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -519,21 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
ddrc_pmu->index_id);
- ddrc_pmu->pmu = (struct pmu) {
- .name = name,
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = ddrc_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
+ hisi_pmu_init(&ddrc_pmu->pmu, name, ddrc_pmu->pmu_events.attr_groups, THIS_MODULE);
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 3b120fc55e01..c5f752f4ff22 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -522,21 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
hha_pmu->sccl_id, hha_pmu->index_id);
- hha_pmu->pmu = (struct pmu) {
- .name = name,
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = hha_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
+ hisi_pmu_init(&hha_pmu->pmu, name, hha_pmu->pmu_events.attr_groups, THIS_MODULE);
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index d70a01587d72..d723e008a0f9 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -560,21 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
*/
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
l3c_pmu->sccl_id, l3c_pmu->ccl_id);
- l3c_pmu->pmu = (struct pmu) {
- .name = name,
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = l3c_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
+ hisi_pmu_init(&l3c_pmu->pmu, name, l3c_pmu->pmu_events.attr_groups, THIS_MODULE);
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 8bab65d50316..99786ef708a6 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -414,21 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
return ret;
}
- pa_pmu->pmu = (struct pmu) {
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = pa_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
-
+ hisi_pmu_init(&pa_pmu->pmu, name, pa_pmu->pmu_events.attr_groups, THIS_MODULE);
ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
if (ret) {
dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 91d2da895924..41640de74072 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -540,4 +540,22 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
}
EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu);
+void hisi_pmu_init(struct pmu *pmu, const char *name,
+ const struct attribute_group **attr_groups, struct module *module)
+{
+ pmu->name = name;
+ pmu->module = module;
+ pmu->task_ctx_nr = perf_invalid_context;
+ pmu->event_init = hisi_uncore_pmu_event_init;
+ pmu->pmu_enable = hisi_uncore_pmu_enable;
+ pmu->pmu_disable = hisi_uncore_pmu_disable;
+ pmu->add = hisi_uncore_pmu_add;
+ pmu->del = hisi_uncore_pmu_del;
+ pmu->start = hisi_uncore_pmu_start;
+ pmu->stop = hisi_uncore_pmu_stop;
+ pmu->read = hisi_uncore_pmu_read;
+ pmu->attr_groups = attr_groups;
+}
+EXPORT_SYMBOL_GPL(hisi_pmu_init);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 6a78c13176c2..9818e20d36f8 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -135,4 +135,6 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
struct platform_device *pdev);
+void hisi_pmu_init(struct pmu *pmu, const char *name,
+ const struct attribute_group **attr_groups, struct module *module);
#endif /* __HISI_UNCORE_PMU_H__ */
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 71b199ec447a..b71de6597016 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -447,20 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
return ret;
}
- sllc_pmu->pmu = (struct pmu) {
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = sllc_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
+ hisi_pmu_init(&sllc_pmu->pmu, name, sllc_pmu->pmu_events.attr_groups, THIS_MODULE);
ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
if (ret) {
--
2.27.0

View File

@ -0,0 +1,48 @@
From 31854a763b417d8f751691e9e4fc81b3523c569d Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Tue, 23 May 2023 14:44:25 +0800
Subject: [PATCH 47/55] drivers/perf: hisi: Advertise the
PERF_PMU_CAP_NO_EXCLUDE capability
mainline inclusion
from mainline-v6.3-rc1
commit 7f95da9d2dc4c20bb374c281ceb8fa40b6208f4b
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7f95da9d2dc4c20bb374c281ceb8fa40b6208f4b
----------------------------------------------------------------------
Missed initialization the variable of pmu::capabilities when extract
the initialization code of hisi_pmu->pmu into a function.
HISI UNCORE PMU drivers counters that not support context exclusion.
So we have to advertise the PERF_PMU_CAP_NO_EXCLUDE capability.
This ensures that perf will prevent us from handling events where
any exclusion flags are set.
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Link: https://lore.kernel.org/r/20230119100307.3660-2-hejunhao3@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 41640de74072..c5860912d765 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -555,6 +555,7 @@ void hisi_pmu_init(struct pmu *pmu, const char *name,
pmu->stop = hisi_uncore_pmu_stop;
pmu->read = hisi_uncore_pmu_read;
pmu->attr_groups = attr_groups;
+ pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE;
}
EXPORT_SYMBOL_GPL(hisi_pmu_init);
--
2.27.0

View File

@ -0,0 +1,142 @@
From 8c346b56153744591b51dadcde8b603b8b872e2d Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Tue, 23 May 2023 14:44:26 +0800
Subject: [PATCH 48/55] drivers/perf: hisi: Simplify the parameters of
hisi_pmu_init()
mainline inclusion
from mainline-v6.3-rc1
commit 053b5579dacfc5763dda0c073ee14147421d32d7
category: cleanup
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=053b5579dacfc5763dda0c073ee14147421d32d7
----------------------------------------------------------------------
Use "hisi_pmu" to simplify the parameter list for the hisi_pmu_init()
function.
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Link: https://lore.kernel.org/r/20230119100307.3660-3-hejunhao3@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pmu.c | 8 +++++---
drivers/perf/hisilicon/hisi_uncore_pmu.h | 4 ++--
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +-
7 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 69d2b08847e2..3a1b3919c736 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -519,7 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
ddrc_pmu->index_id);
- hisi_pmu_init(&ddrc_pmu->pmu, name, ddrc_pmu->pmu_events.attr_groups, THIS_MODULE);
+ hisi_pmu_init(ddrc_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index c5f752f4ff22..9aa951bdf417 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -522,7 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
hha_pmu->sccl_id, hha_pmu->index_id);
- hisi_pmu_init(&hha_pmu->pmu, name, hha_pmu->pmu_events.attr_groups, THIS_MODULE);
+ hisi_pmu_init(hha_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index d723e008a0f9..0406c034e7c4 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -560,7 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
*/
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
l3c_pmu->sccl_id, l3c_pmu->ccl_id);
- hisi_pmu_init(&l3c_pmu->pmu, name, l3c_pmu->pmu_events.attr_groups, THIS_MODULE);
+ hisi_pmu_init(l3c_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 99786ef708a6..df8605a0b24d 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -414,7 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
return ret;
}
- hisi_pmu_init(&pa_pmu->pmu, name, pa_pmu->pmu_events.attr_groups, THIS_MODULE);
+ hisi_pmu_init(pa_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
if (ret) {
dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index c5860912d765..13e54e458f9a 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -540,9 +540,11 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
}
EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu);
-void hisi_pmu_init(struct pmu *pmu, const char *name,
- const struct attribute_group **attr_groups, struct module *module)
+void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name,
+ struct module *module)
{
+ struct pmu *pmu = &hisi_pmu->pmu;
+
pmu->name = name;
pmu->module = module;
pmu->task_ctx_nr = perf_invalid_context;
@@ -554,7 +556,7 @@ void hisi_pmu_init(struct pmu *pmu, const char *name,
pmu->start = hisi_uncore_pmu_start;
pmu->stop = hisi_uncore_pmu_stop;
pmu->read = hisi_uncore_pmu_read;
- pmu->attr_groups = attr_groups;
+ pmu->attr_groups = hisi_pmu->pmu_events.attr_groups;
pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE;
}
EXPORT_SYMBOL_GPL(hisi_pmu_init);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 9818e20d36f8..27951213c9e8 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -135,6 +135,6 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
struct platform_device *pdev);
-void hisi_pmu_init(struct pmu *pmu, const char *name,
- const struct attribute_group **attr_groups, struct module *module);
+void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name,
+ struct module *module);
#endif /* __HISI_UNCORE_PMU_H__ */
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index b71de6597016..c1b038fc534e 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -447,7 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
return ret;
}
- hisi_pmu_init(&sllc_pmu->pmu, name, sllc_pmu->pmu_events.attr_groups, THIS_MODULE);
+ hisi_pmu_init(sllc_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
if (ret) {
--
2.27.0

View File

@ -0,0 +1,57 @@
From 6a6aa532c3e4951259c5c024aa560afe4798e22a Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Tue, 23 May 2023 14:44:27 +0800
Subject: [PATCH 49/55] drivers/perf: hisi: Extract initialization of
"cpa_pmu->pmu"
mainline inclusion
from mainline-v6.3-rc1
commit e126f6f42f89baee09e088ab6bc48f83ac3a0eae
category: cleanup
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e126f6f42f89baee09e088ab6bc48f83ac3a0eae
----------------------------------------------------------------------
Use hisi_pmu_init() function to simplify initialization of "cpa_pmu->pmu".
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Link: https://lore.kernel.org/r/20230119100307.3660-4-hejunhao3@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
index 09839dae9b7c..1a75351013f1 100644
--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
@@ -319,21 +319,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
if (!name)
return -ENOMEM;
- cpa_pmu->pmu = (struct pmu) {
- .name = name,
- .module = THIS_MODULE,
- .task_ctx_nr = perf_invalid_context,
- .event_init = hisi_uncore_pmu_event_init,
- .pmu_enable = hisi_uncore_pmu_enable,
- .pmu_disable = hisi_uncore_pmu_disable,
- .add = hisi_uncore_pmu_add,
- .del = hisi_uncore_pmu_del,
- .start = hisi_uncore_pmu_start,
- .stop = hisi_uncore_pmu_stop,
- .read = hisi_uncore_pmu_read,
- .attr_groups = cpa_pmu->pmu_events.attr_groups,
- .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
- };
+ hisi_pmu_init(cpa_pmu, name, THIS_MODULE);
/* Power Management should be disabled before using CPA PMU. */
hisi_cpa_pmu_disable_pm(cpa_pmu);
--
2.27.0

View File

@ -0,0 +1,144 @@
From 2ccc10a1b9770a9205a8ababd910a08dd8512b96 Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Tue, 23 May 2023 14:44:28 +0800
Subject: [PATCH 50/55] drivers/perf: hisi: Remove redundant initialized of
pmu->name
mainline inclusion
from mainline-v6.4-rc1
commit 25d8c25025a46e7621edde2eb6d5f55c6d29ee86
category: cleanup
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=25d8c25025a46e7621edde2eb6d5f55c6d29ee86
----------------------------------------------------------------------
"pmu->name" is initialized by perf_pmu_register() function, so remove
the redundant initialized in hisi_pmu_init().
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 +---
drivers/perf/hisilicon/hisi_uncore_pmu.h | 3 +--
drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +-
8 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
index 1a75351013f1..9322fc3dac07 100644
--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
@@ -319,7 +319,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
if (!name)
return -ENOMEM;
- hisi_pmu_init(cpa_pmu, name, THIS_MODULE);
+ hisi_pmu_init(cpa_pmu, THIS_MODULE);
/* Power Management should be disabled before using CPA PMU. */
hisi_cpa_pmu_disable_pm(cpa_pmu);
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index 3a1b3919c736..eddeb76ce4c5 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -519,7 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
ddrc_pmu->index_id);
- hisi_pmu_init(ddrc_pmu, name, THIS_MODULE);
+ hisi_pmu_init(ddrc_pmu, THIS_MODULE);
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 9aa951bdf417..1b8f44dada6d 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -522,7 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
hha_pmu->sccl_id, hha_pmu->index_id);
- hisi_pmu_init(hha_pmu, name, THIS_MODULE);
+ hisi_pmu_init(hha_pmu, THIS_MODULE);
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 0406c034e7c4..b2ac90e9f2cd 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -560,7 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
*/
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
l3c_pmu->sccl_id, l3c_pmu->ccl_id);
- hisi_pmu_init(l3c_pmu, name, THIS_MODULE);
+ hisi_pmu_init(l3c_pmu, THIS_MODULE);
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
if (ret) {
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index df8605a0b24d..cf10c84ada41 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -414,7 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
return ret;
}
- hisi_pmu_init(pa_pmu, name, THIS_MODULE);
+ hisi_pmu_init(pa_pmu, THIS_MODULE);
ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
if (ret) {
dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 13e54e458f9a..aed38a8c582c 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -540,12 +540,10 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
}
EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu);
-void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name,
- struct module *module)
+void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module)
{
struct pmu *pmu = &hisi_pmu->pmu;
- pmu->name = name;
pmu->module = module;
pmu->task_ctx_nr = perf_invalid_context;
pmu->event_init = hisi_uncore_pmu_event_init;
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 27951213c9e8..93b672d9731e 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -135,6 +135,5 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
struct platform_device *pdev);
-void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name,
- struct module *module);
+void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module);
#endif /* __HISI_UNCORE_PMU_H__ */
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index c1b038fc534e..149a0d8f403f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -447,7 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
return ret;
}
- hisi_pmu_init(sllc_pmu, name, THIS_MODULE);
+ hisi_pmu_init(sllc_pmu, THIS_MODULE);
ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
if (ret) {
--
2.27.0

View File

@ -0,0 +1,127 @@
From 158cb44475a0c6d29c08716ccb3a868262388e55 Mon Sep 17 00:00:00 2001
From: Junhao He <hejunhao3@huawei.com>
Date: Tue, 23 May 2023 14:44:29 +0800
Subject: [PATCH 51/55] drivers/perf: hisi: add NULL check for name
mainline inclusion
from mainline-v6.4-rc1
commit 257aedb72e731082ab514058e57b132f0b29d707
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=257aedb72e731082ab514058e57b132f0b29d707
----------------------------------------------------------------------
When allocations fails that can be NULL now.
If the name provided is NULL, then the initialization process of the PMU
type and dev will be skipped in function perf_pmu_register().
Consequently, the PMU will not be able to register into the kernel.
Moreover, in the case of unregister the PMU, the function device_del()
will need to handle NULL pointers, which potentially can cause issues.
So move this allocation above the cpuhp_state_add_instance() and directly
return if it does fail.
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 17 ++++++++++-------
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 7 +++++--
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 11 +++++------
3 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index eddeb76ce4c5..184f2f986c98 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -502,13 +502,6 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
- &ddrc_pmu->node);
- if (ret) {
- dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret);
- return ret;
- }
-
if (ddrc_pmu->identifier >= HISI_PMU_V2)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"hisi_sccl%u_ddrc%u_%u",
@@ -519,6 +512,16 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
ddrc_pmu->index_id);
+ if (!name)
+ return -ENOMEM;
+
+ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
+ &ddrc_pmu->node);
+ if (ret) {
+ dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret);
+ return ret;
+ }
+
hisi_pmu_init(ddrc_pmu, THIS_MODULE);
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 1b8f44dada6d..16038ebf08b6 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -513,6 +513,11 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
if (ret)
return ret;
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
+ hha_pmu->sccl_id, hha_pmu->index_id);
+ if (!name)
+ return -ENOMEM;
+
ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
&hha_pmu->node);
if (ret) {
@@ -520,8 +525,6 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
return ret;
}
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
- hha_pmu->sccl_id, hha_pmu->index_id);
hisi_pmu_init(hha_pmu, THIS_MODULE);
ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index b2ac90e9f2cd..f9640dbd4095 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -547,6 +547,11 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
if (ret)
return ret;
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
+ l3c_pmu->sccl_id, l3c_pmu->ccl_id);
+ if (!name)
+ return -ENOMEM;
+
ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
&l3c_pmu->node);
if (ret) {
@@ -554,12 +559,6 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
return ret;
}
- /*
- * CCL_ID is used to identify the L3C in the same SCCL which was
- * used _UID by mistake.
- */
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
- l3c_pmu->sccl_id, l3c_pmu->ccl_id);
hisi_pmu_init(l3c_pmu, THIS_MODULE);
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
--
2.27.0

View File

@ -0,0 +1,162 @@
From 418fb2ed339c7856662bb6244ac5477cba81f80f Mon Sep 17 00:00:00 2001
From: hongrongxuan <hongrongxuan@huawei.com>
Date: Fri, 27 Oct 2023 18:49:23 +0800
Subject: [PATCH 52/55] Revert "perf/smmuv3_pmu: Enable HiSilicon Erratum
162001800 quirk"
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
-----------------------------------------------------------
This reverts commit 68088650bec0647cef4d822b31f818a094f5eead.
We inclusion it again from upstream later.
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/acpi/arm64/iort.c | 16 +-----------
drivers/perf/arm_smmuv3_pmu.c | 48 +++++------------------------------
include/linux/acpi_iort.h | 1 -
3 files changed, 8 insertions(+), 57 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 9ad4ee8884de..d507556d508f 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1476,23 +1476,9 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
ACPI_EDGE_SENSITIVE, &res[2]);
}
-static struct acpi_platform_list pmcg_plat_info[] __initdata = {
- /* HiSilicon Hip08 Platform */
- {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal, 0,
- IORT_SMMU_V3_PMCG_HISI_HIP08},
- { }
-};
-
static int __init arm_smmu_v3_pmcg_add_platdata(struct platform_device *pdev)
{
- u32 model;
- int idx;
-
- idx = acpi_match_platform_list(pmcg_plat_info);
- if (idx >= 0)
- model = pmcg_plat_info[idx].data;
- else
- model = IORT_SMMU_V3_PMCG_GENERIC;
+ u32 model = IORT_SMMU_V3_PMCG_GENERIC;
return platform_device_add_data(pdev, &model, sizeof(model));
}
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index bda901e2a5fc..e9cd120f4268 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -35,7 +35,6 @@
*/
#include <linux/acpi.h>
-#include <linux/acpi_iort.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/cpuhotplug.h>
@@ -94,8 +93,6 @@
#define SMMU_PMCG_PA_SHIFT 12
-#define SMMU_PMCG_EVCNTR_RDONLY BIT(0)
-
static int cpuhp_state_num;
struct smmu_pmu {
@@ -110,7 +107,6 @@ struct smmu_pmu {
struct device *dev;
void __iomem *reg_base;
void __iomem *reloc_base;
- u32 options;
u64 counter_mask;
bool global_filter;
};
@@ -224,27 +220,15 @@ static void smmu_pmu_set_period(struct smmu_pmu *smmu_pmu,
u32 idx = hwc->idx;
u64 new;
- if (smmu_pmu->options & SMMU_PMCG_EVCNTR_RDONLY) {
- /*
- * On platforms that require this quirk, if the counter starts
- * at < half_counter value and wraps, the current logic of
- * handling the overflow may not work. It is expected that,
- * those platforms will have full 64 counter bits implemented
- * so that such a possibility is remote(eg: HiSilicon HIP08).
- */
- new = smmu_pmu_counter_get_value(smmu_pmu, idx);
- } else {
- /*
- * We limit the max period to half the max counter value
- * of the counter size, so that even in the case of extreme
- * interrupt latency the counter will (hopefully) not wrap
- * past its initial value.
- */
- new = smmu_pmu->counter_mask >> 1;
- smmu_pmu_counter_set_value(smmu_pmu, idx, new);
- }
+ /*
+ * We limit the max period to half the max counter value of the counter
+ * size, so that even in the case of extreme interrupt latency the
+ * counter will (hopefully) not wrap past its initial value.
+ */
+ new = smmu_pmu->counter_mask >> 1;
local64_set(&hwc->prev_count, new);
+ smmu_pmu_counter_set_value(smmu_pmu, idx, new);
}
static void smmu_pmu_set_event_filter(struct perf_event *event,
@@ -718,22 +702,6 @@ static void smmu_pmu_reset(struct smmu_pmu *smmu_pmu)
smmu_pmu->reloc_base + SMMU_PMCG_OVSCLR0);
}
-static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
-{
- u32 model;
-
- model = *(u32 *)dev_get_platdata(smmu_pmu->dev);
-
- switch (model) {
- case IORT_SMMU_V3_PMCG_HISI_HIP08:
- /* HiSilicon Erratum 162001800 */
- smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
- break;
- }
-
- dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
-}
-
static int smmu_pmu_probe(struct platform_device *pdev)
{
struct smmu_pmu *smmu_pmu;
@@ -813,8 +781,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
return -EINVAL;
}
- smmu_pmu_get_acpi_options(smmu_pmu);
-
/* Pick one CPU to be the preferred one to use */
smmu_pmu->on_cpu = raw_smp_processor_id();
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index bdb69125854e..832bd6ae9ad4 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -31,7 +31,6 @@
* that, this is not part of the IORT specification.
*/
#define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
-#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */
int iort_register_domain_token(int trans_id, phys_addr_t base,
struct fwnode_handle *fw_node);
--
2.27.0

View File

@ -0,0 +1,197 @@
From b917df0a2ab2eba9cc49d2019f5222e70f42dc60 Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Date: Tue, 26 Mar 2019 15:17:53 +0000
Subject: [PATCH 53/55] perf/smmuv3: Enable HiSilicon Erratum 162001800 quirk
mainline inclusion
from mainline-v5.2-rc1
commit 24062fe85860debfdae0eeaa495f27c9971ec163
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=24062fe85860debfdae0eeaa495f27c9971ec163
----------------------------------------------------------
HiSilicon erratum 162001800 describes the limitation of
SMMUv3 PMCG implementation on HiSilicon Hip08 platforms.
On these platforms, the PMCG event counter registers
(SMMU_PMCG_EVCNTRn) are read only and as a result it
is not possible to set the initial counter period value
on event monitor start.
To work around this, the current value of the counter
is read and used for delta calculations. OEM information
from ACPI header is used to identify the affected hardware
platforms.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
[will: update silicon-errata.txt and add reason string to acpi match]
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
Documentation/arm64/silicon-errata.txt
---
Documentation/arm64/silicon-errata.txt | 1 +
drivers/acpi/arm64/iort.c | 16 ++++++++-
drivers/perf/arm_smmuv3_pmu.c | 48 ++++++++++++++++++++++----
include/linux/acpi_iort.h | 1 +
4 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 5016158f5e67..e733d13d7b98 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -79,6 +79,7 @@ stable kernels.
| Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 |
| Hisilicon | TSV{110,200} | #1980005 | HISILICON_ERRATUM_1980005 |
| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_161600801 |
+| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
| | | | |
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
| Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 |
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index d507556d508f..abc62558e818 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1476,9 +1476,23 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
ACPI_EDGE_SENSITIVE, &res[2]);
}
+static struct acpi_platform_list pmcg_plat_info[] __initdata = {
+ /* HiSilicon Hip08 Platform */
+ {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+ "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
+ { }
+};
+
static int __init arm_smmu_v3_pmcg_add_platdata(struct platform_device *pdev)
{
- u32 model = IORT_SMMU_V3_PMCG_GENERIC;
+ u32 model;
+ int idx;
+
+ idx = acpi_match_platform_list(pmcg_plat_info);
+ if (idx >= 0)
+ model = pmcg_plat_info[idx].data;
+ else
+ model = IORT_SMMU_V3_PMCG_GENERIC;
return platform_device_add_data(pdev, &model, sizeof(model));
}
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index e9cd120f4268..3df836fd2f70 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -35,6 +35,7 @@
*/
#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/cpuhotplug.h>
@@ -93,6 +94,8 @@
#define SMMU_PMCG_PA_SHIFT 12
+#define SMMU_PMCG_EVCNTR_RDONLY BIT(0)
+
static int cpuhp_state_num;
struct smmu_pmu {
@@ -108,6 +111,7 @@ struct smmu_pmu {
void __iomem *reg_base;
void __iomem *reloc_base;
u64 counter_mask;
+ u32 options;
bool global_filter;
};
@@ -220,15 +224,27 @@ static void smmu_pmu_set_period(struct smmu_pmu *smmu_pmu,
u32 idx = hwc->idx;
u64 new;
- /*
- * We limit the max period to half the max counter value of the counter
- * size, so that even in the case of extreme interrupt latency the
- * counter will (hopefully) not wrap past its initial value.
- */
- new = smmu_pmu->counter_mask >> 1;
+ if (smmu_pmu->options & SMMU_PMCG_EVCNTR_RDONLY) {
+ /*
+ * On platforms that require this quirk, if the counter starts
+ * at < half_counter value and wraps, the current logic of
+ * handling the overflow may not work. It is expected that,
+ * those platforms will have full 64 counter bits implemented
+ * so that such a possibility is remote(eg: HiSilicon HIP08).
+ */
+ new = smmu_pmu_counter_get_value(smmu_pmu, idx);
+ } else {
+ /*
+ * We limit the max period to half the max counter value
+ * of the counter size, so that even in the case of extreme
+ * interrupt latency the counter will (hopefully) not wrap
+ * past its initial value.
+ */
+ new = smmu_pmu->counter_mask >> 1;
+ smmu_pmu_counter_set_value(smmu_pmu, idx, new);
+ }
local64_set(&hwc->prev_count, new);
- smmu_pmu_counter_set_value(smmu_pmu, idx, new);
}
static void smmu_pmu_set_event_filter(struct perf_event *event,
@@ -702,6 +718,22 @@ static void smmu_pmu_reset(struct smmu_pmu *smmu_pmu)
smmu_pmu->reloc_base + SMMU_PMCG_OVSCLR0);
}
+static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
+{
+ u32 model;
+
+ model = *(u32 *)dev_get_platdata(smmu_pmu->dev);
+
+ switch (model) {
+ case IORT_SMMU_V3_PMCG_HISI_HIP08:
+ /* HiSilicon Erratum 162001800 */
+ smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
+ break;
+ }
+
+ dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options);
+}
+
static int smmu_pmu_probe(struct platform_device *pdev)
{
struct smmu_pmu *smmu_pmu;
@@ -781,6 +813,8 @@ static int smmu_pmu_probe(struct platform_device *pdev)
return -EINVAL;
}
+ smmu_pmu_get_acpi_options(smmu_pmu);
+
/* Pick one CPU to be the preferred one to use */
smmu_pmu->on_cpu = raw_smp_processor_id();
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 832bd6ae9ad4..bdb69125854e 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -31,6 +31,7 @@
* that, this is not part of the IORT specification.
*/
#define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
+#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */
int iort_register_domain_token(int trans_id, phys_addr_t base,
struct fwnode_handle *fw_node);
--
2.27.0

View File

@ -0,0 +1,170 @@
From 081bfa93450c8b4aa3f483eb14ec7a1bae34f9d4 Mon Sep 17 00:00:00 2001
From: Yicong Yang <yangyicong@hisilicon.com>
Date: Mon, 14 Aug 2023 20:40:12 +0800
Subject: [PATCH 54/55] perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk
for HIP08/09
mainline inclusion
from mainline-v6.6-rc1
commit 0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d
---------------------------------------------------------------------
Some HiSilicon SMMU PMCG suffers the erratum 162001900 that the PMU
disable control sometimes fail to disable the counters. This will lead
to error or inaccurate data since before we enable the counters the
counter's still counting for the event used in last perf session.
This patch tries to fix this by hardening the global disable process.
Before disable the PMU, writing an invalid event type (0xffff) to
focibly stop the counters. Correspondingly restore each events on
pmu::pmu_enable().
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20230814124012.58013-1-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
Conflicts:
Documentation/arch/arm64/silicon-errata.rst
---
Documentation/arm64/silicon-errata.txt | 3 ++
drivers/acpi/arm64/iort.c | 5 ++-
drivers/perf/arm_smmuv3_pmu.c | 46 +++++++++++++++++++++++++-
include/linux/acpi_iort.h | 1 +
4 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index e733d13d7b98..c5aad5509a5a 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -80,6 +80,9 @@ stable kernels.
| Hisilicon | TSV{110,200} | #1980005 | HISILICON_ERRATUM_1980005 |
| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_161600801 |
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
+| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A
+|
+| | Hip09 SMMU PMCG | |
| | | | |
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
| Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 |
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index abc62558e818..7cfbf52055f8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1479,7 +1479,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
static struct acpi_platform_list pmcg_plat_info[] __initdata = {
/* HiSilicon Hip08 Platform */
{"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
- "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
+ "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08},
+ /* HiSilicon Hip09 Platform */
+ {"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
{ }
};
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 3df836fd2f70..56e6f6773675 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -95,6 +95,7 @@
#define SMMU_PMCG_PA_SHIFT 12
#define SMMU_PMCG_EVCNTR_RDONLY BIT(0)
+#define SMMU_PMCG_HARDEN_DISABLE BIT(1)
static int cpuhp_state_num;
@@ -138,6 +139,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu)
writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR);
}
+static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
+ struct perf_event *event, int idx);
+
+static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu)
+{
+ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+ unsigned int idx;
+
+ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
+ smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx);
+
+ smmu_pmu_enable(pmu);
+}
+
static inline void smmu_pmu_disable(struct pmu *pmu)
{
struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
@@ -146,6 +161,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu)
writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL);
}
+static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu)
+{
+ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+ unsigned int idx;
+
+ /*
+ * The global disable of PMU sometimes fail to stop the counting.
+ * Harden this by writing an invalid event type to each used counter
+ * to forcibly stop counting.
+ */
+ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
+ writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx));
+
+ smmu_pmu_disable(pmu);
+}
+
static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu,
u32 idx, u64 value)
{
@@ -727,7 +758,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
switch (model) {
case IORT_SMMU_V3_PMCG_HISI_HIP08:
/* HiSilicon Erratum 162001800 */
- smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
+ smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE;
+ break;
+ case IORT_SMMU_V3_PMCG_HISI_HIP09:
+ smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE;
break;
}
@@ -815,6 +849,16 @@ static int smmu_pmu_probe(struct platform_device *pdev)
smmu_pmu_get_acpi_options(smmu_pmu);
+ /*
+ * For platforms suffer this quirk, the PMU disable sometimes fails to
+ * stop the counters. This will leads to inaccurate or error counting.
+ * Forcibly disable the counters with these quirk handler.
+ */
+ if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) {
+ smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09;
+ smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09;
+ }
+
/* Pick one CPU to be the preferred one to use */
smmu_pmu->on_cpu = raw_smp_processor_id();
WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index bdb69125854e..b1c1c84a422e 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -32,6 +32,7 @@
*/
#define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */
+#define IORT_SMMU_V3_PMCG_HISI_HIP09 0x00000002 /* HiSilicon HIP09 PMCG */
int iort_register_domain_token(int trans_id, phys_addr_t base,
struct fwnode_handle *fw_node);
--
2.27.0

View File

@ -0,0 +1,57 @@
From 381dea7a1598760dcffcbce4f819bbe7035a3b13 Mon Sep 17 00:00:00 2001
From: Yicong Yang <yangyicong@hisilicon.com>
Date: Mon, 14 Aug 2023 21:16:42 +0800
Subject: [PATCH 55/55] perf/smmuv3: Add MODULE_ALIAS for module auto loading
mainline inclusion
from mainline-v6.6-rc1
commit 1b0e3ea9301a422003d385cda8f8dee6c878ad05
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b0e3ea9301a422003d385cda8f8dee6c878ad05
------------------------------------------------------------------
On my ACPI based arm64 server, if the SMMUv3 PMU is configured as
module it won't be loaded automatically after booting even if the
device has already been scanned and added. It's because the module
lacks a platform alias, the uevent mechanism and userspace tools
like udevd make use of this to find the target driver module of the
device. This patch adds the missing platform alias of the module,
then module will be loaded automatically if device exists.
Before this patch:
[root@localhost tmp]# modinfo arm_smmuv3_pmu | grep alias
alias: of:N*T*Carm,smmu-v3-pmcgC*
alias: of:N*T*Carm,smmu-v3-pmcg
After this patch:
[root@localhost tmp]# modinfo arm_smmuv3_pmu | grep alias
alias: platform:arm-smmu-v3-pmcg
alias: of:N*T*Carm,smmu-v3-pmcgC*
alias: of:N*T*Carm,smmu-v3-pmcg
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20230814131642.65263-1-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
---
drivers/perf/arm_smmuv3_pmu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 56e6f6773675..1fae44c24ff9 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -941,6 +941,7 @@ static void __exit arm_smmu_pmu_exit(void)
module_exit(arm_smmu_pmu_exit);
+MODULE_ALIAS("platform:arm-smmu-v3-pmcg");
MODULE_DESCRIPTION("PMU driver for ARM SMMUv3 Performance Monitors Extension");
MODULE_AUTHOR("Neil Leeder <nleeder@codeaurora.org>");
MODULE_AUTHOR("Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>");
--
2.27.0

View File

@ -43,3 +43,58 @@ patches/0038-perf-arm-spe-Add-more-sub-classes-for-operation-pack.patch
patches/0039-perf-arm_spe-Decode-memory-tagging-properties.patch
patches/0040-perf-arm-spe-Add-support-for-ARMv8.3-SPE.patch
patches/0041-drivers-perf-Add-support-for-ARMv8.3-SPE.patch
patches/0042-Revert-perf-hisi-Fix-compile-error-if-defined-MODULE.patch
patches/0043-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-P.patch
patches/0044-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDR.patch
patches/0045-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-PMU-d.patch
patches/0046-Revert-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-.patch
patches/0047-Revert-perf-hisi-remove-duplicated-code.patch
patches/0048-docs-perf-convert-to-ReST.patch
patches/0049-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-modules.patch
patches/0050-For-drivers-that-do-not-support-context-exclusion-le.patch
patches/0051-drivers-provide-devm_platform_ioremap_resource.patch
patches/0052-perf-hisi-use-devm_platform_ioremap_resource-to-simp.patch
patches/0053-drivers-perf-hisi-Add-identifier-sysfs-file.patch
patches/0054-drivers-perf-hisi-Remove-unnecessary-check-of-counte.patch
patches/0055-drivers-perf-hisi-Refactor-code-for-more-uncore-PMUs.patch
patches/0056-drivers-perf-hisi-Add-PMU-version-for-uncore-PMU-dri.patch
patches/0057-drivers-perf-hisi-Add-new-functions-for-L3C-PMU.patch
patches/0058-drivers-perf-hisi-Add-new-functions-for-HHA-PMU.patch
patches/0059-drivers-perf-hisi-Update-DDRC-PMU-for-programmable-c.patch
patches/0060-drivers-perf-hisi-Add-support-for-HiSilicon-SLLC-PMU.patch
patches/0061-drivers-perf-hisi-Add-support-for-HiSilicon-PA-PMU-d.patch
patches/0062-perf-hisi-Use-irq_set_affinity.patch
patches/0063-drivers-perf-hisi-Fix-data-source-control.patch
patches/0064-perf-hisi-Make-irq-shared.patch
patches/0065-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-some-.patch
patches/0066-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-PMU.patch
patches/0067-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDRC-PMU.patch
patches/0068-perf-hisi-Fix-unexpected-modifications-in-hisi_uncor.patch
patches/0069-PCI-Add-pci_dev_id-helper.patch
patches/0070-drivers-perf-hisi-Add-driver-for-HiSilicon-PCIe-PMU.patch
patches/0071-drivers-perf-hisi-Associate-PMUs-in-SICL-with-CPUs-o.patch
patches/0072-driver-perf-hisi-fix-kabi-broken-for-struct-hisi_pmu.patch
patches/0073-drivers-perf-hisi-Add-Support-for-CPA-PMU.patch
patches/0074-drivers-perf-hisi-Fix-some-event-id-for-hisi-pcie-pm.patch
patches/0075-docs-perf-move-to-the-admin-guide.patch
patches/0076-docs-perf-Add-new-description-on-HiSilicon-uncore-PM.patch
patches/0077-docs-perf-Add-description-for-HiSilicon-PCIe-PMU-dri.patch
patches/0078-docs-perf-Address-some-html-build-warnings.patch
patches/0079-docs-fix-make-htmldocs-warning-in-perf.patch
patches/0080-docs-perf-Fix-PMU-instance-name-of-hisi-pcie-pmu.patch
patches/0081-drivers-perf-hisi-Add-TLP-filter-support.patch
patches/0082-drivers-perf-hisi-Don-t-migrate-perf-to-the-CPU-goin.patch
patches/0083-drivers-perf-fixed-the-issue-that-the-kabi-value-cha.patch
patches/0084-drivers-perf-fixed-kabi-broken-for-SLLC-and-PA-PMU.patch
patches/0085-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-TSV20.patch
patches/0086-perf-hisi-Add-configs-for-PMU-isolation.patch
patches/0087-perf-hisi-Extract-hisi_pmu_init.patch
patches/0088-drivers-perf-hisi-Advertise-the-PERF_PMU_CAP_NO_EXCL.patch
patches/0089-drivers-perf-hisi-Simplify-the-parameters-of-hisi_pm.patch
patches/0090-drivers-perf-hisi-Extract-initialization-of-cpa_pmu-.patch
patches/0091-drivers-perf-hisi-Remove-redundant-initialized-of-pm.patch
patches/0092-drivers-perf-hisi-add-NULL-check-for-name.patch
patches/0093-Revert-perf-smmuv3_pmu-Enable-HiSilicon-Erratum-1620.patch
patches/0094-perf-smmuv3-Enable-HiSilicon-Erratum-162001800-quirk.patch
patches/0095-perf-smmuv3-Enable-HiSilicon-Erratum-162001900-quirk.patch
patches/0096-perf-smmuv3-Add-MODULE_ALIAS-for-module-auto-loading.patch