Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] drivers/perf: hisi: Updates for HiSilicon uncore PMUs
@ 2026-07-13 12:56 Yushan Wang
  2026-07-13 12:56 ` [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU Yushan Wang
  2026-07-13 12:56 ` [PATCH v3 2/2] drivers/perf: hisi: Add new function for HiSilicon MN PMU driver Yushan Wang
  0 siblings, 2 replies; 7+ messages in thread
From: Yushan Wang @ 2026-07-13 12:56 UTC (permalink / raw)
  To: will, mark.rutland, robin.murphy, linux-arm-kernel, linux-kernel
  Cc: fanghao11, linuxarm, liuyonglong, prime.zeng, wangzhou1,
	wangyushan12

This patchset added support of ITS PMU, and new version of MN PMU.

ITS PMU supports counting number and latency of interrupts by
category, and statistics of micro-ops of ITS.

The new version of MN PMU added cycles event, to be used for MN
metric computing.

Changes:
v3:
- Added check_filter callback to refuse new filtered events when there
  are already filtered ones running as per Sashiko.
Link to v2: https://lore.kernel.org/all/20260612093812.1249049-1-wangyushan12@huawei.com/
Link to Sashiko review report: https://sashiko.dev/#/message/20260612093812.1249049-1-wangyushan12%40huawei.com

v2:
- Added int_en filter to tell if int_id is used, enabling filtering
  interrupt with 0 int_id per Sashiko.
- Changed event format width to align with register width per Sashiko.
Link to v1: https://lore.kernel.org/all/20260423152959.1458563-1-wangyushan12@huawei.com/
Link to Sashiko review report: https://sashiko.dev/#/patchset/20260423152959.1458563-1-wangyushan12%40huawei.com

Yifan Wu (1):
  drivers/perf: hisi: Add new function for HiSilicon MN PMU driver

Yushan Wang (1):
  drivers/perf: hisi: Support uncore ITS PMU

 Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
 drivers/perf/hisilicon/Makefile              |   2 +-
 drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c  |  63 ++-
 4 files changed, 463 insertions(+), 8 deletions(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c

-- 
2.33.0



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU
  2026-07-13 12:56 [PATCH v3 0/2] drivers/perf: hisi: Updates for HiSilicon uncore PMUs Yushan Wang
@ 2026-07-13 12:56 ` Yushan Wang
  2026-07-14 12:32   ` Uwe Kleine-König
  2026-07-13 12:56 ` [PATCH v3 2/2] drivers/perf: hisi: Add new function for HiSilicon MN PMU driver Yushan Wang
  1 sibling, 1 reply; 7+ messages in thread
From: Yushan Wang @ 2026-07-13 12:56 UTC (permalink / raw)
  To: will, mark.rutland, robin.murphy, linux-arm-kernel, linux-kernel
  Cc: fanghao11, linuxarm, liuyonglong, prime.zeng, wangzhou1,
	wangyushan12

Support uncore ITS PMU, which provides the capability of counting
the number of interrupts routed to ITS by interrupt catagories, and the
latency. It also supports collecting statistics of micro-ops of ITS.

The driver adapts to HiSilicon uncore PMU framework. It does not support
overflow interruption, which is the same as NoC PMU, so a few dummy
functions or handling interrupts are left empty.

Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
---
 Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
 drivers/perf/hisilicon/Makefile              |   2 +-
 drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
 3 files changed, 407 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c

diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
index d56b2d690709..278bd7e0ae60 100644
--- a/Documentation/admin-guide/perf/hisi-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pmu.rst
@@ -128,6 +128,19 @@ channel with this option. The current supported channels are as follows:
 7. tt_en: NoC PMU supports counting only transactions that have tracetag set
 if this option is set. See the 2nd list for more information about tracetag.
 
+8. int_id: ITS PMU supports filtering by interrupt id, which is defined by
+hardware. Interrupt id takes up to 32 bits, and can be divided into 2 parts:
+
+- Upper 16 bits: DeviceID if counting LPI, PEID if counting SGI/PPI.
+- Lower 16 bits: EventID if counting LPI, IntID if counting SGI/PPI.
+
+int_id is a global configuration for each PMU instance. If multiple different
+int_id's are specified, the last came in will be effective. And if there are
+already filtered events running, new filtered events came in will be refused.
+
+9. int_en: A one-bit flag to tell if int_id is used to filter the statistics. It
+allows filtering 0 DeviceID and EventID.
+
 For HiSilicon uncore PMU v3 whose identifier is 0x40, some uncore PMUs are
 further divided into parts for finer granularity of tracing, each part has its
 own dedicated PMU, and all such PMUs together cover the monitoring job of events
diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index 186be3d02238..5f28cfdb8a72 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -2,7 +2,7 @@
 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_uc_pmu.o \
-			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
+			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o hisi_uncore_its_pmu.o
 
 obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
 obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_its_pmu.c b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
new file mode 100644
index 000000000000..430e2b06cf4d
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for HiSilicon Uncore ITS PMU device
+ *
+ * Copyright (c) 2026 HiSilicon Technologies Co., Ltd.
+ * Author: Yushan Wang <wangyushan12@huawei.com>
+ */
+#include <linux/bitops.h>
+#include <linux/cpuhotplug.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/sysfs.h>
+
+#include "hisi_uncore_pmu.h"
+
+#define ITS_PMU_VERSION			0x21000
+#define ITS_PMU_GLOBAL_CTRL		0x21004
+#define ITS_PMU_GLOBAL_CTRL_PMU_EN	BIT(0)
+#define ITS_PMU_COUNTER_CTRL		0x21008
+#define ITS_PMU_EVENT_CTRL		0x2100c
+#define ITS_PMU_COUNTER0		0x21010
+
+#define ITS_PMU_INT_ID_MASK		0x20008
+#define ITS_PMU_INT_ID_CTRL		0x20084
+
+#define ITS_PMU_NR_COUNTERS		4
+
+#define ITS_PMU_EVENT_CNTRn(cntr0, n)	((cntr0) + 8 * (n))
+#define ITS_PMU_CNTR_CTRL_MASK(n)	GENMASK(8 * ((n) + 1) - 1, 8 * (n))
+#define ITS_PMU_CNTR_EVENT_CFG(n, e)	((e) << ((n) * 8))
+#define ITS_PMU_EVENT_CTRL_TYPE		GENMASK(12, 0)
+
+HISI_PMU_EVENT_ATTR_EXTRACTOR(int_id, config1, 31, 0);
+HISI_PMU_EVENT_ATTR_EXTRACTOR(int_en, config1, 32, 32);
+
+/* Dynamic CPU hotplug state used by this PMU driver */
+static enum cpuhp_state hisi_its_pmu_cpuhp_state;
+
+struct hisi_its_pmu_regs {
+	u32 version;
+	u32 pmu_ctrl;
+	u32 event_ctrl0;
+	u32 event_cntr0;
+	u32 cntr_ctrl;
+};
+
+struct hisi_its_pmu {
+	struct hisi_pmu pmu;
+	atomic_t filter_user;
+};
+
+static void hisi_its_pmu_write_evtype(struct hisi_pmu *pmu, int idx, u32 type)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+	u32 reg;
+
+	reg = readl(pmu->base + reg_info->event_ctrl0);
+	reg &= ~ITS_PMU_CNTR_CTRL_MASK(idx);
+	reg |= ITS_PMU_CNTR_EVENT_CFG(idx, type);
+	writel(reg, pmu->base + reg_info->event_ctrl0);
+}
+
+static u64 hisi_its_pmu_read_counter(struct hisi_pmu *pmu,
+				     struct hw_perf_event *hwc)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+
+	return readq(pmu->base + ITS_PMU_EVENT_CNTRn(reg_info->event_cntr0, hwc->idx));
+}
+
+static void hisi_its_pmu_write_counter(struct hisi_pmu *pmu,
+				       struct hw_perf_event *hwc, u64 val)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+
+	writeq(val, pmu->base + ITS_PMU_EVENT_CNTRn(reg_info->event_cntr0, hwc->idx));
+}
+
+static void hisi_its_pmu_enable_counter(struct hisi_pmu *pmu,
+					struct hw_perf_event *hwc)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+	u32 reg;
+
+	reg = readl(pmu->base + reg_info->cntr_ctrl);
+	reg |= BIT(hwc->idx);
+	writel(reg, pmu->base + reg_info->cntr_ctrl);
+}
+
+static void hisi_its_pmu_disable_counter(struct hisi_pmu *pmu,
+					 struct hw_perf_event *hwc)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+	u32 reg;
+
+	reg = readl(pmu->base + reg_info->cntr_ctrl);
+	reg &= ~BIT(hwc->idx);
+	writel(reg, pmu->base + reg_info->cntr_ctrl);
+}
+
+static void hisi_its_pmu_enable_counter_int(struct hisi_pmu *pmu,
+					    struct hw_perf_event *hwc)
+{
+	/* We don't support interrupt, so a stub here. */
+}
+
+static void hisi_its_pmu_disable_counter_int(struct hisi_pmu *pmu,
+					     struct hw_perf_event *hwc)
+{
+}
+
+static void hisi_its_pmu_start_counters(struct hisi_pmu *pmu)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+	u32 reg;
+
+	reg = readl(pmu->base + reg_info->pmu_ctrl);
+	reg |= ITS_PMU_GLOBAL_CTRL_PMU_EN;
+	writel(reg, pmu->base + reg_info->pmu_ctrl);
+}
+
+static void hisi_its_pmu_stop_counters(struct hisi_pmu *pmu)
+{
+	struct hisi_its_pmu_regs *reg_info = pmu->dev_info->private;
+	u32 reg;
+
+	reg = readl(pmu->base + reg_info->pmu_ctrl);
+	reg &= ~ITS_PMU_GLOBAL_CTRL_PMU_EN;
+	writel(reg, pmu->base + reg_info->pmu_ctrl);
+}
+
+static void hisi_its_pmu_enable_filter(struct perf_event *event)
+{
+	struct hisi_pmu *pmu = to_hisi_pmu(event->pmu);
+	struct hisi_its_pmu *its_pmu = container_of(pmu, struct hisi_its_pmu, pmu);
+	u32 int_id = hisi_get_int_id(event);
+	u32 int_en = hisi_get_int_en(event);
+
+	if (int_en) {
+		writel(int_id, pmu->base + ITS_PMU_INT_ID_CTRL);
+		/* Write 0 to this register to enable filtering with int_id. */
+		writel(0, pmu->base + ITS_PMU_INT_ID_MASK);
+		atomic_inc(&its_pmu->filter_user);
+	}
+}
+
+static void hisi_its_pmu_disable_filter(struct perf_event *event)
+{
+	struct hisi_pmu *pmu = to_hisi_pmu(event->pmu);
+	struct hisi_its_pmu *its_pmu = container_of(pmu, struct hisi_its_pmu, pmu);
+
+	/* Don't touch global filtering config if this is not the last counter. */
+	if (bitmap_weight(pmu->pmu_events.used_mask, pmu->num_counters) > 1)
+		return;
+
+	if (atomic_read(&its_pmu->filter_user)) {
+		writel(0, pmu->base + ITS_PMU_INT_ID_CTRL);
+		writel(-1U, pmu->base + ITS_PMU_INT_ID_MASK);
+		atomic_dec(&its_pmu->filter_user);
+	}
+}
+
+static int hisi_its_pmu_check_filter(struct perf_event *event)
+{
+	struct hisi_pmu *pmu = to_hisi_pmu(event->pmu);
+	struct hisi_its_pmu *its_pmu = container_of(pmu, struct hisi_its_pmu, pmu);
+	u32 int_en = hisi_get_int_en(event);
+
+	/* Refuse filtered event if there's already filtered one running. */
+	return atomic_read(&its_pmu->filter_user) && int_en;
+}
+
+static const struct hisi_uncore_ops hisi_uncore_its_ops = {
+	.write_evtype		= hisi_its_pmu_write_evtype,
+	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
+	.read_counter		= hisi_its_pmu_read_counter,
+	.write_counter		= hisi_its_pmu_write_counter,
+	.enable_counter		= hisi_its_pmu_enable_counter,
+	.disable_counter	= hisi_its_pmu_disable_counter,
+	.enable_counter_int	= hisi_its_pmu_enable_counter_int,
+	.disable_counter_int	= hisi_its_pmu_disable_counter_int,
+	.start_counters		= hisi_its_pmu_start_counters,
+	.stop_counters		= hisi_its_pmu_stop_counters,
+	.enable_filter		= hisi_its_pmu_enable_filter,
+	.disable_filter		= hisi_its_pmu_disable_filter,
+	.check_filter		= hisi_its_pmu_check_filter
+};
+
+static struct attribute *hisi_its_pmu_format_attrs[] = {
+	HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
+	HISI_PMU_FORMAT_ATTR(int_id, "config1:0-31"),
+	HISI_PMU_FORMAT_ATTR(int_en, "config1:32-32"),
+	NULL
+};
+
+static const struct attribute_group hisi_its_pmu_format_group = {
+	.name = "format",
+	.attrs = hisi_its_pmu_format_attrs,
+};
+
+static struct attribute *hisi_its_pmu_events_attrs[] = {
+	HISI_PMU_EVENT_ATTR(lpi_num, 0xc0),
+	HISI_PMU_EVENT_ATTR(lpi_time, 0x80),
+	HISI_PMU_EVENT_ATTR(sgi_num, 0xc1),
+	HISI_PMU_EVENT_ATTR(sgi_time, 0x81),
+	HISI_PMU_EVENT_ATTR(ppi_num, 0xc2),
+	HISI_PMU_EVENT_ATTR(ppi_time, 0x82),
+	HISI_PMU_EVENT_ATTR(sl3_lpi_num, 0xc3),
+	HISI_PMU_EVENT_ATTR(sl3_sgi_num, 0xc4),
+	HISI_PMU_EVENT_ATTR(sl3_ppi_num, 0xc5),
+	HISI_PMU_EVENT_ATTR(sl0_ddr_read, 0xc9),
+	HISI_PMU_EVENT_ATTR(sl0_ddr_time, 0x89),
+	HISI_PMU_EVENT_ATTR(sl1_ddr_read, 0xca),
+	HISI_PMU_EVENT_ATTR(sl1_ddr_time, 0x8a),
+	HISI_PMU_EVENT_ATTR(sl2_ddr_read, 0xcb),
+	HISI_PMU_EVENT_ATTR(sl2_ddr_time, 0x8b),
+	HISI_PMU_EVENT_ATTR(cycles, 0xcc),
+	NULL
+};
+
+static const struct attribute_group hisi_its_pmu_events_group = {
+	.name = "events",
+	.attrs = hisi_its_pmu_events_attrs,
+};
+
+static const struct attribute_group *hisi_its_pmu_attr_groups[] = {
+	&hisi_its_pmu_format_group,
+	&hisi_its_pmu_events_group,
+	&hisi_pmu_cpumask_attr_group,
+	&hisi_pmu_identifier_group,
+	NULL
+};
+
+static int hisi_its_pmu_dev_init(struct platform_device *pdev,
+				 struct hisi_its_pmu *its_pmu)
+{
+	struct hisi_its_pmu_regs *reg_info;
+	struct hisi_pmu *pmu = &its_pmu->pmu;
+
+	hisi_uncore_pmu_init_topology(pmu, &pdev->dev);
+
+	if (pmu->topo.scl_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL, "failed to get scl-id\n");
+
+	if (pmu->topo.index_id < 0)
+		return dev_err_probe(&pdev->dev, -EINVAL, "failed to get idx-id\n");
+
+	pmu->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pmu->base))
+		return dev_err_probe(&pdev->dev, PTR_ERR(pmu->base),
+				     "fail to remap io memory\n");
+
+	pmu->dev_info = device_get_match_data(&pdev->dev);
+	if (!pmu->dev_info)
+		return -ENODEV;
+
+	pmu->pmu_events.attr_groups = pmu->dev_info->attr_groups;
+	pmu->counter_bits = pmu->dev_info->counter_bits;
+	pmu->check_event = pmu->dev_info->check_event;
+	pmu->num_counters = ITS_PMU_NR_COUNTERS;
+	pmu->ops = &hisi_uncore_its_ops;
+	pmu->dev = &pdev->dev;
+	pmu->on_cpu = -1;
+
+	reg_info = pmu->dev_info->private;
+	pmu->identifier = readl(pmu->base + reg_info->version);
+
+	return 0;
+}
+
+static void hisi_its_pmu_remove_cpuhp_instance(void *hotplug_node)
+{
+	cpuhp_state_remove_instance_nocalls(hisi_its_pmu_cpuhp_state, hotplug_node);
+}
+
+static void hisi_its_pmu_unregister_pmu(void *pmu)
+{
+	perf_pmu_unregister(pmu);
+}
+
+static int hisi_its_pmu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hisi_its_pmu *its_pmu;
+	struct hisi_pmu *pmu;
+	char *name;
+	int ret;
+
+	its_pmu = devm_kzalloc(dev, sizeof(*its_pmu), GFP_KERNEL);
+	if (!its_pmu)
+		return -ENOMEM;
+
+	pmu = &its_pmu->pmu;
+
+	/*
+	 * HiSilicon Uncore PMU framework needs to get common hisi_pmu device
+	 * from device's drvdata.
+	 */
+	platform_set_drvdata(pdev, its_pmu);
+
+	ret = hisi_its_pmu_dev_init(pdev, its_pmu);
+	if (ret)
+		return ret;
+
+	ret = cpuhp_state_add_instance(hisi_its_pmu_cpuhp_state, &pmu->node);
+	if (ret)
+		return dev_err_probe(dev, ret, "Fail to register cpuhp instance\n");
+
+	ret = devm_add_action_or_reset(dev, hisi_its_pmu_remove_cpuhp_instance,
+				       &pmu->node);
+	if (ret)
+		return ret;
+
+	hisi_pmu_init(pmu, THIS_MODULE);
+
+	name = devm_kasprintf(dev, GFP_KERNEL, "hisi_scl%d_its%d",
+			      pmu->topo.scl_id, pmu->topo.index_id);
+	if (!name)
+		return -ENOMEM;
+
+	ret = perf_pmu_register(&pmu->pmu, name, -1);
+	if (ret)
+		return dev_err_probe(dev, ret, "Fail to register PMU\n");
+
+	return devm_add_action_or_reset(dev, hisi_its_pmu_unregister_pmu,
+					&pmu->pmu);
+}
+
+static struct hisi_its_pmu_regs hisi_its_v1_pmu_regs = {
+	.version = ITS_PMU_VERSION,
+	.pmu_ctrl = ITS_PMU_GLOBAL_CTRL,
+	.event_ctrl0 = ITS_PMU_EVENT_CTRL,
+	.event_cntr0 = ITS_PMU_COUNTER0,
+	.cntr_ctrl = ITS_PMU_COUNTER_CTRL,
+};
+
+static const struct hisi_pmu_dev_info hisi_its_v1 = {
+	.attr_groups = hisi_its_pmu_attr_groups,
+	.counter_bits = 48,
+	.check_event = ITS_PMU_EVENT_CTRL_TYPE,
+	.private = &hisi_its_v1_pmu_regs,
+};
+
+static const struct acpi_device_id hisi_its_pmu_ids[] = {
+	{ "HISI0591", (kernel_ulong_t)&hisi_its_v1 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_its_pmu_ids);
+
+static struct platform_driver hisi_its_pmu_driver = {
+	.driver = {
+		.name = "hisi_its_pmu",
+		.acpi_match_table = hisi_its_pmu_ids,
+		.suppress_bind_attrs = true,
+	},
+	.probe = hisi_its_pmu_probe,
+};
+
+static int __init hisi_its_pmu_module_init(void)
+{
+	int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+					  "perf/hisi/its:online",
+					  hisi_uncore_pmu_online_cpu,
+					  hisi_uncore_pmu_offline_cpu);
+	if (ret < 0) {
+		pr_err("hisi_its_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
+		return ret;
+	}
+	hisi_its_pmu_cpuhp_state = ret;
+
+	ret = platform_driver_register(&hisi_its_pmu_driver);
+	if (ret)
+		cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
+
+	return ret;
+}
+module_init(hisi_its_pmu_module_init);
+
+static void __exit hisi_its_pmu_module_exit(void)
+{
+	platform_driver_unregister(&hisi_its_pmu_driver);
+	cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
+}
+module_exit(hisi_its_pmu_module_exit);
+
+MODULE_IMPORT_NS("HISI_PMU");
+MODULE_DESCRIPTION("HiSilicon SoC Uncore ITS PMU driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yushan Wang <wangyushan12@huawei.com>");
-- 
2.33.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/2] drivers/perf: hisi: Add new function for HiSilicon MN PMU driver
  2026-07-13 12:56 [PATCH v3 0/2] drivers/perf: hisi: Updates for HiSilicon uncore PMUs Yushan Wang
  2026-07-13 12:56 ` [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU Yushan Wang
@ 2026-07-13 12:56 ` Yushan Wang
  1 sibling, 0 replies; 7+ messages in thread
From: Yushan Wang @ 2026-07-13 12:56 UTC (permalink / raw)
  To: will, mark.rutland, robin.murphy, linux-arm-kernel, linux-kernel
  Cc: fanghao11, linuxarm, liuyonglong, prime.zeng, wangzhou1,
	wangyushan12

From: Yifan Wu <wuyifan50@huawei.com>

MN (Miscellaneous Node) is a hybrid node in ARM CHI. The MN PMU driver
using the HiSilicon uncore PMU framework.

On HiSilicon HIP13 platform, cycle event is supported on MN PMU. The
cycle event is exposed directly in driver and some variables shall be
added suffix to distinguish the version.

Signed-off-by: Yifan Wu <wuyifan50@huawei.com>
Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
---
 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c | 63 ++++++++++++++++++---
 1 file changed, 56 insertions(+), 7 deletions(-)

diff --git a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
index 246cc0333099..f38a5880ca18 100644
--- a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
@@ -191,7 +191,7 @@ static const struct attribute_group hisi_mn_pmu_format_group = {
 	.attrs = hisi_mn_pmu_format_attr,
 };
 
-static struct attribute *hisi_mn_pmu_events_attr[] = {
+static struct attribute *hisi_mn_pmu_events_attr_v1[] = {
 	HISI_PMU_EVENT_ATTR(req_eobarrier_num,		0x00),
 	HISI_PMU_EVENT_ATTR(req_ecbarrier_num,		0x01),
 	HISI_PMU_EVENT_ATTR(req_dvmop_num,		0x02),
@@ -218,14 +218,55 @@ static struct attribute *hisi_mn_pmu_events_attr[] = {
 	NULL
 };
 
-static const struct attribute_group hisi_mn_pmu_events_group = {
+static const struct attribute_group hisi_mn_pmu_events_group_v1 = {
 	.name = "events",
-	.attrs = hisi_mn_pmu_events_attr,
+	.attrs = hisi_mn_pmu_events_attr_v1,
 };
 
-static const struct attribute_group *hisi_mn_pmu_attr_groups[] = {
+static const struct attribute_group *hisi_mn_pmu_attr_groups_v1[] = {
 	&hisi_mn_pmu_format_group,
-	&hisi_mn_pmu_events_group,
+	&hisi_mn_pmu_events_group_v1,
+	&hisi_pmu_cpumask_attr_group,
+	&hisi_pmu_identifier_group,
+	NULL
+};
+
+static struct attribute *hisi_mn_pmu_events_attr_v2[] = {
+	HISI_PMU_EVENT_ATTR(req_eobarrier_num,		0x00),
+	HISI_PMU_EVENT_ATTR(req_ecbarrier_num,		0x01),
+	HISI_PMU_EVENT_ATTR(req_dvmop_num,		0x02),
+	HISI_PMU_EVENT_ATTR(req_dvmsync_num,		0x03),
+	HISI_PMU_EVENT_ATTR(req_retry_num,		0x04),
+	HISI_PMU_EVENT_ATTR(req_writenosnp_num,		0x05),
+	HISI_PMU_EVENT_ATTR(req_readnosnp_num,		0x06),
+	HISI_PMU_EVENT_ATTR(snp_dvm_num,		0x07),
+	HISI_PMU_EVENT_ATTR(snp_dvmsync_num,		0x08),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvm_num,		0x09),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_num,	0x0A),
+	HISI_PMU_EVENT_ATTR(mn_req_dvm_num,		0x0B),
+	HISI_PMU_EVENT_ATTR(mn_req_dvmsync_num,		0x0C),
+	HISI_PMU_EVENT_ATTR(pa_req_dvm_num,		0x0D),
+	HISI_PMU_EVENT_ATTR(pa_req_dvmsync_num,		0x0E),
+	HISI_PMU_EVENT_ATTR(cycles,					0x0F),
+	HISI_PMU_EVENT_ATTR(snp_dvm_latency,		0x80),
+	HISI_PMU_EVENT_ATTR(snp_dvmsync_latency,	0x81),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvm_latency,	0x82),
+	HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_latency,	0x83),
+	HISI_PMU_EVENT_ATTR(mn_req_dvm_latency,		0x84),
+	HISI_PMU_EVENT_ATTR(mn_req_dvmsync_latency,	0x85),
+	HISI_PMU_EVENT_ATTR(pa_req_dvm_latency,		0x86),
+	HISI_PMU_EVENT_ATTR(pa_req_dvmsync_latency,	0x87),
+	NULL
+};
+
+static const struct attribute_group hisi_mn_pmu_events_group_v2 = {
+	.name = "events",
+	.attrs = hisi_mn_pmu_events_attr_v2,
+};
+
+static const struct attribute_group *hisi_mn_pmu_attr_groups_v2[] = {
+	&hisi_mn_pmu_format_group,
+	&hisi_mn_pmu_events_group_v2,
 	&hisi_pmu_cpumask_attr_group,
 	&hisi_pmu_identifier_group,
 	NULL
@@ -350,14 +391,22 @@ static struct hisi_mn_pmu_regs hisi_mn_v1_pmu_regs = {
 };
 
 static const struct hisi_pmu_dev_info hisi_mn_v1 = {
-	.attr_groups = hisi_mn_pmu_attr_groups,
+	.attr_groups = hisi_mn_pmu_attr_groups_v1,
+	.counter_bits = 48,
+	.check_event = HISI_MN_EVTYPE_MASK,
+	.private = &hisi_mn_v1_pmu_regs,
+};
+
+static const struct hisi_pmu_dev_info hisi_mn_v2 = {
+	.attr_groups = hisi_mn_pmu_attr_groups_v2,
 	.counter_bits = 48,
 	.check_event = HISI_MN_EVTYPE_MASK,
 	.private = &hisi_mn_v1_pmu_regs,
 };
 
 static const struct acpi_device_id hisi_mn_pmu_acpi_match[] = {
-	{ "HISI0222", (kernel_ulong_t) &hisi_mn_v1 },
+	{ "HISI0222", (kernel_ulong_t)&hisi_mn_v1 },
+	{ "HISI0224", (kernel_ulong_t)&hisi_mn_v2 },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, hisi_mn_pmu_acpi_match);
-- 
2.33.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU
  2026-07-13 12:56 ` [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU Yushan Wang
@ 2026-07-14 12:32   ` Uwe Kleine-König
  2026-07-14 12:56     ` Robin Murphy
  2026-07-14 13:51     ` Yushan Wang
  0 siblings, 2 replies; 7+ messages in thread
From: Uwe Kleine-König @ 2026-07-14 12:32 UTC (permalink / raw)
  To: Yushan Wang
  Cc: will, mark.rutland, robin.murphy, linux-arm-kernel, linux-kernel,
	fanghao11, linuxarm, liuyonglong, prime.zeng, wangzhou1

[-- Attachment #1: Type: text/plain, Size: 4611 bytes --]

Hello,

On Mon, Jul 13, 2026 at 08:56:46PM +0800, Yushan Wang wrote:
> Support uncore ITS PMU, which provides the capability of counting
> the number of interrupts routed to ITS by interrupt catagories, and the
> latency. It also supports collecting statistics of micro-ops of ITS.
> 
> The driver adapts to HiSilicon uncore PMU framework. It does not support
> overflow interruption, which is the same as NoC PMU, so a few dummy
> functions or handling interrupts are left empty.
> 
> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
> ---
>  Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
>  drivers/perf/hisilicon/Makefile              |   2 +-
>  drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
>  3 files changed, 407 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c
> 
> diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
> index d56b2d690709..278bd7e0ae60 100644
> --- a/Documentation/admin-guide/perf/hisi-pmu.rst
> +++ b/Documentation/admin-guide/perf/hisi-pmu.rst
> @@ -128,6 +128,19 @@ channel with this option. The current supported channels are as follows:
>  7. tt_en: NoC PMU supports counting only transactions that have tracetag set
>  if this option is set. See the 2nd list for more information about tracetag.
>  
> +8. int_id: ITS PMU supports filtering by interrupt id, which is defined by
> +hardware. Interrupt id takes up to 32 bits, and can be divided into 2 parts:
> +
> +- Upper 16 bits: DeviceID if counting LPI, PEID if counting SGI/PPI.
> +- Lower 16 bits: EventID if counting LPI, IntID if counting SGI/PPI.
> +
> +int_id is a global configuration for each PMU instance. If multiple different
> +int_id's are specified, the last came in will be effective. And if there are
> +already filtered events running, new filtered events came in will be refused.
> +
> +9. int_en: A one-bit flag to tell if int_id is used to filter the statistics. It
> +allows filtering 0 DeviceID and EventID.
> +
>  For HiSilicon uncore PMU v3 whose identifier is 0x40, some uncore PMUs are
>  further divided into parts for finer granularity of tracing, each part has its
>  own dedicated PMU, and all such PMUs together cover the monitoring job of events
> diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
> index 186be3d02238..5f28cfdb8a72 100644
> --- a/drivers/perf/hisilicon/Makefile
> +++ b/drivers/perf/hisilicon/Makefile
> @@ -2,7 +2,7 @@
>  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_uc_pmu.o \
> -			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
> +			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o hisi_uncore_its_pmu.o
>  
>  obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
>  obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
> diff --git a/drivers/perf/hisilicon/hisi_uncore_its_pmu.c b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
> new file mode 100644
> index 000000000000..430e2b06cf4d
> --- /dev/null
> +++ b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
> @@ -0,0 +1,393 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for HiSilicon Uncore ITS PMU device
> + *
> + * Copyright (c) 2026 HiSilicon Technologies Co., Ltd.
> + * Author: Yushan Wang <wangyushan12@huawei.com>
> + */
> +#include <linux/bitops.h>
> +#include <linux/cpuhotplug.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/mod_devicetable.h>

Please rely on linux/platform_device.h to provice acpi_device_id and
drop the include for <linux/mod_devicetable.h>.

> +static int __init hisi_its_pmu_module_init(void)
> +{
> +	int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
> +					  "perf/hisi/its:online",
> +					  hisi_uncore_pmu_online_cpu,
> +					  hisi_uncore_pmu_offline_cpu);

<disclaimer>I don't know anything about the functions involved
here</disclaimer>

This looks fishy. The module might be loaded on any machine, is it right
to call hisilicon specific functions then?

> +	if (ret < 0) {
> +		pr_err("hisi_its_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
> +		return ret;
> +	}
> +	hisi_its_pmu_cpuhp_state = ret;
> +
> +	ret = platform_driver_register(&hisi_its_pmu_driver);
> +	if (ret)
> +		cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
> +
> +	return ret;
> +}
> +module_init(hisi_its_pmu_module_init);

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU
  2026-07-14 12:32   ` Uwe Kleine-König
@ 2026-07-14 12:56     ` Robin Murphy
  2026-07-14 13:42       ` Yushan Wang
  2026-07-14 13:51     ` Yushan Wang
  1 sibling, 1 reply; 7+ messages in thread
From: Robin Murphy @ 2026-07-14 12:56 UTC (permalink / raw)
  To: Uwe Kleine-König, Yushan Wang
  Cc: will, mark.rutland, linux-arm-kernel, linux-kernel, fanghao11,
	linuxarm, liuyonglong, prime.zeng, wangzhou1

On 14/07/2026 1:32 pm, Uwe Kleine-König wrote:
> Hello,
> 
> On Mon, Jul 13, 2026 at 08:56:46PM +0800, Yushan Wang wrote:
>> Support uncore ITS PMU, which provides the capability of counting
>> the number of interrupts routed to ITS by interrupt catagories, and the
>> latency. It also supports collecting statistics of micro-ops of ITS.
>>
>> The driver adapts to HiSilicon uncore PMU framework. It does not support
>> overflow interruption, which is the same as NoC PMU, so a few dummy
>> functions or handling interrupts are left empty.
>>
>> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
>> ---
>>   Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
>>   drivers/perf/hisilicon/Makefile              |   2 +-
>>   drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
>>   3 files changed, 407 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>>
>> diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
>> index d56b2d690709..278bd7e0ae60 100644
>> --- a/Documentation/admin-guide/perf/hisi-pmu.rst
>> +++ b/Documentation/admin-guide/perf/hisi-pmu.rst
>> @@ -128,6 +128,19 @@ channel with this option. The current supported channels are as follows:
>>   7. tt_en: NoC PMU supports counting only transactions that have tracetag set
>>   if this option is set. See the 2nd list for more information about tracetag.
>>   
>> +8. int_id: ITS PMU supports filtering by interrupt id, which is defined by
>> +hardware. Interrupt id takes up to 32 bits, and can be divided into 2 parts:
>> +
>> +- Upper 16 bits: DeviceID if counting LPI, PEID if counting SGI/PPI.
>> +- Lower 16 bits: EventID if counting LPI, IntID if counting SGI/PPI.
>> +
>> +int_id is a global configuration for each PMU instance. If multiple different
>> +int_id's are specified, the last came in will be effective. And if there are
>> +already filtered events running, new filtered events came in will be refused.
>> +
>> +9. int_en: A one-bit flag to tell if int_id is used to filter the statistics. It
>> +allows filtering 0 DeviceID and EventID.
>> +
>>   For HiSilicon uncore PMU v3 whose identifier is 0x40, some uncore PMUs are
>>   further divided into parts for finer granularity of tracing, each part has its
>>   own dedicated PMU, and all such PMUs together cover the monitoring job of events
>> diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
>> index 186be3d02238..5f28cfdb8a72 100644
>> --- a/drivers/perf/hisilicon/Makefile
>> +++ b/drivers/perf/hisilicon/Makefile
>> @@ -2,7 +2,7 @@
>>   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_uc_pmu.o \
>> -			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
>> +			  hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o hisi_uncore_its_pmu.o
>>   
>>   obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
>>   obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_its_pmu.c b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>> new file mode 100644
>> index 000000000000..430e2b06cf4d
>> --- /dev/null
>> +++ b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>> @@ -0,0 +1,393 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Driver for HiSilicon Uncore ITS PMU device
>> + *
>> + * Copyright (c) 2026 HiSilicon Technologies Co., Ltd.
>> + * Author: Yushan Wang <wangyushan12@huawei.com>
>> + */
>> +#include <linux/bitops.h>
>> +#include <linux/cpuhotplug.h>
>> +#include <linux/device.h>
>> +#include <linux/io.h>
>> +#include <linux/mod_devicetable.h>
> 
> Please rely on linux/platform_device.h to provice acpi_device_id and
> drop the include for <linux/mod_devicetable.h>.
> 
>> +static int __init hisi_its_pmu_module_init(void)
>> +{
>> +	int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
>> +					  "perf/hisi/its:online",
>> +					  hisi_uncore_pmu_online_cpu,
>> +					  hisi_uncore_pmu_offline_cpu);
> 
> <disclaimer>I don't know anything about the functions involved
> here</disclaimer>
> 
> This looks fishy. The module might be loaded on any machine, is it right
> to call hisilicon specific functions then?

This only registers the state with the hotplug mechanism - the callbacks 
themselves won't ever be invoked until the driver binds to something and 
calls cpuhp_state_add_instance() from probe.

It is true that the dynamic hotplug states are somewhat limited, so at 
worst it might consume one unnecessarily if the driver is built-in, but 
this is the status quo for system PMU drivers, and TBH there are enough 
*other* issues with this whole perf hotplug mess anyway that I wouldn't 
see this one as a major concern. (FWIW I have started another 
side-project to make it all go away, which is beginning to look 
promising...)

That said, in this particular case, HISI_PMU could seemingly do better 
than registering *multiple* states with the same exact callbacks - 
registering a single state from the common hisi_uncore_pmu.c framework, 
then just having all the subdrivers add their instances to that, would 
be something of an improvement for now.

Thanks,
Robin.

> 
>> +	if (ret < 0) {
>> +		pr_err("hisi_its_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
>> +		return ret;
>> +	}
>> +	hisi_its_pmu_cpuhp_state = ret;
>> +
>> +	ret = platform_driver_register(&hisi_its_pmu_driver);
>> +	if (ret)
>> +		cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
>> +
>> +	return ret;
>> +}
>> +module_init(hisi_its_pmu_module_init);
> 
> Best regards
> Uwe



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU
  2026-07-14 12:56     ` Robin Murphy
@ 2026-07-14 13:42       ` Yushan Wang
  0 siblings, 0 replies; 7+ messages in thread
From: Yushan Wang @ 2026-07-14 13:42 UTC (permalink / raw)
  To: Robin Murphy, Uwe Kleine-König
  Cc: will, mark.rutland, linux-arm-kernel, linux-kernel, fanghao11,
	linuxarm, liuyonglong, prime.zeng, wangzhou1, Yushan Wang

On 7/14/2026 8:56 PM, Robin Murphy wrote:
> On 14/07/2026 1:32 pm, Uwe Kleine-König wrote:
>> Hello,
>>
>> On Mon, Jul 13, 2026 at 08:56:46PM +0800, Yushan Wang wrote:
>>> Support uncore ITS PMU, which provides the capability of counting
>>> the number of interrupts routed to ITS by interrupt catagories, and the
>>> latency. It also supports collecting statistics of micro-ops of ITS.
>>>
>>> The driver adapts to HiSilicon uncore PMU framework. It does not support
>>> overflow interruption, which is the same as NoC PMU, so a few dummy
>>> functions or handling interrupts are left empty.
>>>
>>> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
>>> ---
>>>   Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
>>>   drivers/perf/hisilicon/Makefile              |   2 +-
>>>   drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
>>>   3 files changed, 407 insertions(+), 1 deletion(-)
>>>   create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>>>
>>> diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
>>> index d56b2d690709..278bd7e0ae60 100644
>>> --- a/Documentation/admin-guide/perf/hisi-pmu.rst
>>> +++ b/Documentation/admin-guide/perf/hisi-pmu.rst
>>> @@ -128,6 +128,19 @@ channel with this option. The current supported channels are as follows:
>>>   7. tt_en: NoC PMU supports counting only transactions that have tracetag set
>>>   if this option is set. See the 2nd list for more information about tracetag.
>>>   +8. int_id: ITS PMU supports filtering by interrupt id, which is defined by
>>> +hardware. Interrupt id takes up to 32 bits, and can be divided into 2 parts:
>>> +
>>> +- Upper 16 bits: DeviceID if counting LPI, PEID if counting SGI/PPI.
>>> +- Lower 16 bits: EventID if counting LPI, IntID if counting SGI/PPI.
>>> +
>>> +int_id is a global configuration for each PMU instance. If multiple different
>>> +int_id's are specified, the last came in will be effective. And if there are
>>> +already filtered events running, new filtered events came in will be refused.
>>> +
>>> +9. int_en: A one-bit flag to tell if int_id is used to filter the statistics. It
>>> +allows filtering 0 DeviceID and EventID.
>>> +
>>>   For HiSilicon uncore PMU v3 whose identifier is 0x40, some uncore PMUs are
>>>   further divided into parts for finer granularity of tracing, each part has its
>>>   own dedicated PMU, and all such PMUs together cover the monitoring job of events
>>> diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
>>> index 186be3d02238..5f28cfdb8a72 100644
>>> --- a/drivers/perf/hisilicon/Makefile
>>> +++ b/drivers/perf/hisilicon/Makefile
>>> @@ -2,7 +2,7 @@
>>>   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_uc_pmu.o \
>>> -              hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
>>> +              hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o hisi_uncore_its_pmu.o
>>>     obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
>>>   obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
>>> diff --git a/drivers/perf/hisilicon/hisi_uncore_its_pmu.c b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>>> new file mode 100644
>>> index 000000000000..430e2b06cf4d
>>> --- /dev/null
>>> +++ b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>>> @@ -0,0 +1,393 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Driver for HiSilicon Uncore ITS PMU device
>>> + *
>>> + * Copyright (c) 2026 HiSilicon Technologies Co., Ltd.
>>> + * Author: Yushan Wang <wangyushan12@huawei.com>
>>> + */
>>> +#include <linux/bitops.h>
>>> +#include <linux/cpuhotplug.h>
>>> +#include <linux/device.h>
>>> +#include <linux/io.h>
>>> +#include <linux/mod_devicetable.h>
>>
>> Please rely on linux/platform_device.h to provice acpi_device_id and
>> drop the include for <linux/mod_devicetable.h>.
>>
>>> +static int __init hisi_its_pmu_module_init(void)
>>> +{
>>> +    int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
>>> +                      "perf/hisi/its:online",
>>> +                      hisi_uncore_pmu_online_cpu,
>>> +                      hisi_uncore_pmu_offline_cpu);
>>
>> <disclaimer>I don't know anything about the functions involved
>> here</disclaimer>
>>
>> This looks fishy. The module might be loaded on any machine, is it right
>> to call hisilicon specific functions then?
>
> This only registers the state with the hotplug mechanism - the callbacks themselves won't ever be invoked until the driver binds to something and calls cpuhp_state_add_instance() from probe.

Thanks for the explanation.

>
> It is true that the dynamic hotplug states are somewhat limited, so at worst it might consume one unnecessarily if the driver is built-in, but this is the status quo for system PMU drivers, and TBH there are enough *other* issues with this whole perf hotplug mess anyway that I wouldn't see this one as a major concern. (FWIW I have started another side-project to make it all go away, which is beginning to look promising...)
>
> That said, in this particular case, HISI_PMU could seemingly do better than registering *multiple* states with the same exact callbacks - registering a single state from the common hisi_uncore_pmu.c framework, then just having all the subdrivers add their instances to that, would be something of an improvement for now.

It's true that in current implementations, the hotplug callbacks are exactly the
same. hisi_uncore_pmu.c mainly serves to provide public functions for other
actual PMU drivers, I can move this dynamic-state planting code into that module
and export the state to other drivers.

There are also some historic static states for HiSilicon PMUs that could migrate
to dynamic ones for better consistency. I will try to do that refactor in the
next version.

Thanks for the suggestions!
Yushan

>
> Thanks,
> Robin.
>
>>
>>> +    if (ret < 0) {
>>> +        pr_err("hisi_its_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
>>> +        return ret;
>>> +    }
>>> +    hisi_its_pmu_cpuhp_state = ret;
>>> +
>>> +    ret = platform_driver_register(&hisi_its_pmu_driver);
>>> +    if (ret)
>>> +        cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
>>> +
>>> +    return ret;
>>> +}
>>> +module_init(hisi_its_pmu_module_init);
>>
>> Best regards
>> Uwe
>
>



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU
  2026-07-14 12:32   ` Uwe Kleine-König
  2026-07-14 12:56     ` Robin Murphy
@ 2026-07-14 13:51     ` Yushan Wang
  1 sibling, 0 replies; 7+ messages in thread
From: Yushan Wang @ 2026-07-14 13:51 UTC (permalink / raw)
  To: Uwe Kleine-König, robin.murphy
  Cc: will, mark.rutland, linux-arm-kernel, linux-kernel, fanghao11,
	linuxarm, liuyonglong, prime.zeng, wangzhou1, Yushan Wang


On 7/14/2026 8:32 PM, Uwe Kleine-König wrote:
> Hello,
>
> On Mon, Jul 13, 2026 at 08:56:46PM +0800, Yushan Wang wrote:
>> Support uncore ITS PMU, which provides the capability of counting
>> the number of interrupts routed to ITS by interrupt catagories, and the
>> latency. It also supports collecting statistics of micro-ops of ITS.
>>
>> The driver adapts to HiSilicon uncore PMU framework. It does not support
>> overflow interruption, which is the same as NoC PMU, so a few dummy
>> functions or handling interrupts are left empty.
>>
>> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
>> ---
>>  Documentation/admin-guide/perf/hisi-pmu.rst  |  13 +
>>  drivers/perf/hisilicon/Makefile              |   2 +-
>>  drivers/perf/hisilicon/hisi_uncore_its_pmu.c | 393 +++++++++++++++++++
>>  3 files changed, 407 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>>
>> diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst
>> index d56b2d690709..278bd7e0ae60 100644
>> --- a/Documentation/admin-guide/perf/hisi-pmu.rst
>> +++ b/Documentation/admin-guide/perf/hisi-pmu.rst
>> @@ -128,6 +128,19 @@ channel with this option. The current supported channels are as follows:
>>  7. tt_en: NoC PMU supports counting only transactions that have tracetag set
>>  if this option is set. See the 2nd list for more information about tracetag.
>>
>> +8. int_id: ITS PMU supports filtering by interrupt id, which is defined by
>> +hardware. Interrupt id takes up to 32 bits, and can be divided into 2 parts:
>> +
>> +- Upper 16 bits: DeviceID if counting LPI, PEID if counting SGI/PPI.
>> +- Lower 16 bits: EventID if counting LPI, IntID if counting SGI/PPI.
>> +
>> +int_id is a global configuration for each PMU instance. If multiple different
>> +int_id's are specified, the last came in will be effective. And if there are
>> +already filtered events running, new filtered events came in will be refused.
>> +
>> +9. int_en: A one-bit flag to tell if int_id is used to filter the statistics. It
>> +allows filtering 0 DeviceID and EventID.
>> +
>>  For HiSilicon uncore PMU v3 whose identifier is 0x40, some uncore PMUs are
>>  further divided into parts for finer granularity of tracing, each part has its
>>  own dedicated PMU, and all such PMUs together cover the monitoring job of events
>> diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
>> index 186be3d02238..5f28cfdb8a72 100644
>> --- a/drivers/perf/hisilicon/Makefile
>> +++ b/drivers/perf/hisilicon/Makefile
>> @@ -2,7 +2,7 @@
>>  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_uc_pmu.o \
>> -                      hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o
>> +                      hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o hisi_uncore_its_pmu.o
>>
>>  obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o
>>  obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_its_pmu.c b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>> new file mode 100644
>> index 000000000000..430e2b06cf4d
>> --- /dev/null
>> +++ b/drivers/perf/hisilicon/hisi_uncore_its_pmu.c
>> @@ -0,0 +1,393 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Driver for HiSilicon Uncore ITS PMU device
>> + *
>> + * Copyright (c) 2026 HiSilicon Technologies Co., Ltd.
>> + * Author: Yushan Wang <wangyushan12@huawei.com>
>> + */
>> +#include <linux/bitops.h>
>> +#include <linux/cpuhotplug.h>
>> +#include <linux/device.h>
>> +#include <linux/io.h>
>> +#include <linux/mod_devicetable.h>
> Please rely on linux/platform_device.h to provice acpi_device_id and
> drop the include for <linux/mod_devicetable.h>.

This is a redundant header file, thanks for pointing out.

linux/platform_device.h is already imported below, I will drop this header
file in the next version.

>
>
>> +static int __init hisi_its_pmu_module_init(void)
>> +{
>> +    int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
>> +                                      "perf/hisi/its:online",
>> +                                      hisi_uncore_pmu_online_cpu,
>> +                                      hisi_uncore_pmu_offline_cpu);
> <disclaimer>I don't know anything about the functions involved
> here</disclaimer>
>
> This looks fishy. The module might be loaded on any machine, is it right
> to call hisilicon specific functions then?

As discussion with Robin, this is correct but not necessary.

I will propose a refactor in the next version to eliminate redundant
cpuhp_setup_state_multi for HISI PMUs.

But to fully achieve a better form of cpuhp callback registration, we can be
counting on Robin's work! :)

Thanks,
Yushan

>
>> +    if (ret < 0) {
>> +            pr_err("hisi_its_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
>> +            return ret;
>> +    }
>> +    hisi_its_pmu_cpuhp_state = ret;
>> +
>> +    ret = platform_driver_register(&hisi_its_pmu_driver);
>> +    if (ret)
>> +            cpuhp_remove_multi_state(hisi_its_pmu_cpuhp_state);
>> +
>> +    return ret;
>> +}
>> +module_init(hisi_its_pmu_module_init);
> Best regards
> Uwe




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-14 13:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13 12:56 [PATCH v3 0/2] drivers/perf: hisi: Updates for HiSilicon uncore PMUs Yushan Wang
2026-07-13 12:56 ` [PATCH v3 1/2] drivers/perf: hisi: Support uncore ITS PMU Yushan Wang
2026-07-14 12:32   ` Uwe Kleine-König
2026-07-14 12:56     ` Robin Murphy
2026-07-14 13:42       ` Yushan Wang
2026-07-14 13:51     ` Yushan Wang
2026-07-13 12:56 ` [PATCH v3 2/2] drivers/perf: hisi: Add new function for HiSilicon MN PMU driver Yushan Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox