Unverified Commit 7ed9c0d2 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1872 Synchronizing mainline HiSilicon uncore PMU patches

Merge Pull Request from: @ci-robot 
 
PR sync from: Junhao He <hejunhao3@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/5UJLTJ2WQPM246Y3VHBQBBT7SNCSRSLN/ 
Synchronizing mainline HiSilicon uncore PMU patches

The HISI uncore UC PMU and uncore H60PA/PAv3 PMU drivers have been
integrated into the main line. Compared with OLK-5.10, some
modifications are made.

Add support for HiSilicon UC/H60PA/PAv3 PMU driver.

PAv3 PMU: Compared with the PAv2 PMU, the PAv3 PMU has different event.
The PAv3 PMU removed some events which are supported by PAv2 PMU. The
older PA PMU driver will probe v3 as v2. Add the HISI0275 HID for PAv3
PMU to distinguish different.

H60PA PMU: The H60PA PMU and PA are two different devices. The H60PA PMU
supports higher bandwidth, and the PA PMU delay is relatively low.
Different HIDs are used to distinguish the delay.

UC PMU: Each cluster is integrated with a unified cache (UC) PMU, which
provides consistency between NUMA and UMA domains. It sits between
L2 and the memory system.

Junhao He (4):
  Revert "drivers/perf: hisi: Add support for HiSilicon UC PMU driver"
  Revert "drivers/perf: hisi: Add support for HiSilicon H60PA and PAv3
    PMU driver"
  drivers/perf: hisi: Add support for HiSilicon H60PA and PAv3 PMU
    driver
  drivers/perf: hisi: Add support for HiSilicon UC PMU driver


-- 
2.33.0
 
https://gitee.com/openeuler/kernel/issues/I7VP5K 
 
Link:https://gitee.com/openeuler/kernel/pulls/1872

 

Reviewed-by: default avatarYang Shen <shenyang39@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents bdde34c2 a746da11
Loading
Loading
Loading
Loading
+48 −59
Original line number Diff line number Diff line
@@ -22,14 +22,15 @@
#define PA_TT_CTRL			0x1c08
#define PA_TGTID_CTRL			0x1c14
#define PA_SRCID_CTRL			0x1c18

/* H32 PA interrupt registers */
#define PA_INT_MASK			0x1c70
#define PA_INT_STATUS			0x1c78
#define PA_INT_CLEAR			0x1c7c
/* H60 PA interrupt registers */

#define H60PA_INT_STATUS		0x1c70
#define H60PA_INT_MASK			0x1c74
/* End interrupt registers */

#define PA_EVENT_TYPE0			0x1c80
#define PA_PMU_VERSION			0x1cf0
#define PA_EVENT_CNT0_L			0x1d00
@@ -52,9 +53,9 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);

struct hisi_pa_pmu_int_regs {
	u32 mask;
	u32 clear;
	u32 status;
	u32 mask_offset;
	u32 clear_offset;
	u32 status_offset;
};

static void hisi_pa_pmu_enable_tracetag(struct perf_event *event)
@@ -230,51 +231,44 @@ static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu,
static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu,
					   struct hw_perf_event *hwc)
{
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->present;
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
	u32 val;

	/* Write 0 to enable interrupt */
	val = readl(pa_pmu->base + regs->mask);
	val = readl(pa_pmu->base + regs->mask_offset);
	val &= ~(1 << hwc->idx);
	writel(val, pa_pmu->base + regs->mask);
	writel(val, pa_pmu->base + regs->mask_offset);
}

static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu,
					    struct hw_perf_event *hwc)
{
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->present;
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;
	u32 val;

	/* Write 1 to mask interrupt */
	val = readl(pa_pmu->base + regs->mask);
	val = readl(pa_pmu->base + regs->mask_offset);
	val |= 1 << hwc->idx;
	writel(val, pa_pmu->base + regs->mask);
	writel(val, pa_pmu->base + regs->mask_offset);
}

static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu)
{
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->present;
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;

	return readl(pa_pmu->base + regs->status);
	return readl(pa_pmu->base + regs->status_offset);
}

static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx)
{
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->present;
	struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private;

	writel(1 << idx, pa_pmu->base + regs->clear);
	writel(1 << idx, pa_pmu->base + regs->clear_offset);
}

static int hisi_pa_pmu_init_data(struct platform_device *pdev,
				   struct hisi_pmu *pa_pmu)
{
	const struct hisi_pmu_dev_info *pa_pmu_info;
	int idx;

	pa_pmu_info = device_get_match_data(&pdev->dev);
	if (!pa_pmu_info)
		return -ENODEV;

	/*
	 * As PA PMU is in a SICL, use the SICL_ID and the index ID
	 * to identify the PA PMU.
@@ -294,6 +288,10 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
	pa_pmu->ccl_id = -1;
	pa_pmu->sccl_id = -1;

	pa_pmu->dev_info = device_get_match_data(&pdev->dev);
	if (!pa_pmu->dev_info)
		return -ENODEV;

	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");
@@ -302,11 +300,6 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,

	pa_pmu->identifier = readl(pa_pmu->base + PA_PMU_VERSION);

	idx = hisi_uncore_pmu_ver2idx(pa_pmu);
	pa_pmu->dev_info = &pa_pmu_info[idx];
	if (!pa_pmu->dev_info || !pa_pmu->dev_info->name)
		return -EINVAL;

	return 0;
}

@@ -382,10 +375,16 @@ static struct attribute *hisi_pa_pmu_identifier_attrs[] = {
	NULL
};

static const struct attribute_group hisi_pa_pmu_identifier_group = {
static struct attribute_group hisi_pa_pmu_identifier_group = {
	.attrs = hisi_pa_pmu_identifier_attrs,
};

static struct hisi_pa_pmu_int_regs hisi_pa_pmu_regs = {
	.mask_offset = PA_INT_MASK,
	.clear_offset = PA_INT_CLEAR,
	.status_offset = PA_INT_STATUS,
};

static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
	&hisi_pa_pmu_v2_format_group,
	&hisi_pa_pmu_v2_events_group,
@@ -394,6 +393,12 @@ static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = {
	NULL
};

static const struct hisi_pmu_dev_info hisi_h32pa_v2 = {
	.name = "pa",
	.attr_groups = hisi_pa_pmu_v2_attr_groups,
	.private = &hisi_pa_pmu_regs,
};

static const struct attribute_group *hisi_pa_pmu_v3_attr_groups[] = {
	&hisi_pa_pmu_v2_format_group,
	&hisi_pa_pmu_v3_events_group,
@@ -402,24 +407,16 @@ static const struct attribute_group *hisi_pa_pmu_v3_attr_groups[] = {
	NULL
};

static struct hisi_pa_pmu_int_regs hisi_pa_pmu_regs = {
	.mask = PA_INT_MASK,
	.clear = PA_INT_CLEAR,
	.status = PA_INT_STATUS,
};

static const struct hisi_pmu_dev_info hisi_h32pa[] = {
	[1] = {
		.name = "pa",
		.attr_groups = hisi_pa_pmu_v2_attr_groups,
		.present = &hisi_pa_pmu_regs,
	},
	[2] = {
static const struct hisi_pmu_dev_info hisi_h32pa_v3 = {
	.name = "pa",
	.attr_groups = hisi_pa_pmu_v3_attr_groups,
		.present = &hisi_pa_pmu_regs,
	},
	{}
	.private = &hisi_pa_pmu_regs,
};

static struct hisi_pa_pmu_int_regs hisi_h60pa_pmu_regs = {
	.mask_offset = H60PA_INT_MASK,
	.clear_offset = H60PA_INT_STATUS, /* Clear on write */
	.status_offset = H60PA_INT_STATUS,
};

static const struct attribute_group *hisi_h60pa_pmu_attr_groups[] = {
@@ -430,19 +427,10 @@ static const struct attribute_group *hisi_h60pa_pmu_attr_groups[] = {
	NULL
};

static struct hisi_pa_pmu_int_regs hisi_h60pa_pmu_regs = {
	.mask = H60PA_INT_MASK,
	.clear = H60PA_INT_STATUS, /* Clear on write */
	.status = H60PA_INT_STATUS,
};

static const struct hisi_pmu_dev_info hisi_h60pa[] = {
	[1] = {
static const struct hisi_pmu_dev_info hisi_h60pa = {
	.name = "h60pa",
	.attr_groups = hisi_h60pa_pmu_attr_groups,
		.present = &hisi_h60pa_pmu_regs,
	},
	{}
	.private = &hisi_h60pa_pmu_regs,
};

static const struct hisi_uncore_ops hisi_uncore_pa_ops = {
@@ -537,8 +525,9 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev)
}

static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = {
	{ "HISI0273", (kernel_ulong_t)hisi_h32pa },
	{ "HISI0274", (kernel_ulong_t)hisi_h60pa },
	{ "HISI0273", (kernel_ulong_t)&hisi_h32pa_v2 },
	{ "HISI0275", (kernel_ulong_t)&hisi_h32pa_v3 },
	{ "HISI0274", (kernel_ulong_t)&hisi_h60pa },
	{}
};
MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match);
+2 −3
Original line number Diff line number Diff line
@@ -225,8 +225,7 @@ int hisi_uncore_pmu_event_init(struct perf_event *event)
	hwc->idx		= -1;
	hwc->config_base	= event->attr.config;

	if (hisi_pmu->ops->check_format)
		if (hisi_pmu->ops->check_format(event))
	if (hisi_pmu->ops->check_filter && hisi_pmu->ops->check_filter(event))
		return -EINVAL;

	/* Enforce to use the same CPU for all events in this PMU */
+4 −28
Original line number Diff line number Diff line
@@ -23,6 +23,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))

@@ -42,13 +43,6 @@
		return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config);  \
	}

enum hisi_pmu_version {
	HISI_PMU_V1,
	HISI_PMU_V2 = 0x30,
	HISI_PMU_V3 = 0x40,
	HISI_PMU_MAX
};

#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff)

#define HISI_PMU_EVTYPE_BITS		8
@@ -57,7 +51,7 @@ enum hisi_pmu_version {
struct hisi_pmu;

struct hisi_uncore_ops {
	int (*check_format)(struct perf_event *event);
	int (*check_filter)(struct perf_event *event);
	void (*write_evtype)(struct hisi_pmu *, int, u32);
	int (*get_event_idx)(struct perf_event *);
	u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *);
@@ -78,7 +72,7 @@ struct hisi_uncore_ops {
struct hisi_pmu_dev_info {
	const char *name;
	const struct attribute_group **attr_groups;
	void *present;
	void *private;
};

struct hisi_pmu_hwevents {
@@ -112,7 +106,7 @@ struct hisi_pmu {
	int counter_bits;
	/* check event code range */
	int check_event;
	enum hisi_pmu_version identifier;
	u32 identifier;
};

int hisi_uncore_pmu_get_event_idx(struct perf_event *event);
@@ -142,22 +136,4 @@ int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
			     struct platform_device *pdev);

void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module);

int hisi_uncore_pmu_ver2idx(struct hisi_pmu *pmu)
{
	int idx;

	switch (pmu->identifier) {
	case HISI_PMU_V1:
		idx = 0; break;
	case HISI_PMU_V2:
		idx = 1; break;
	case HISI_PMU_V3:
	/* When running on later version, returns the largest supported version */
	default:
		idx = 2;
	}

	return idx;
}
#endif /* __HISI_UNCORE_PMU_H__ */
+18 −17
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
 *
 * Copyright (C) 2023 HiSilicon Limited
 *
 * This code is based on the uncore PMUs like arm-cci and arm-ccn.
 * This code is based on the uncore PMUs like hisi_uncore_l3c_pmu.
 */
#include <linux/cpuhotplug.h>
#include <linux/interrupt.h>
@@ -34,11 +34,9 @@ static enum cpuhp_state hisi_uc_pmu_online;
#define HISI_UC_EVENT_URING_MSK		GENMASK(28, 27)
#define HISI_UC_EVENT_GLB_EN		BIT(26)
#define HISI_UC_VERSION_REG		0x1cf0
#define HISI_UC_EVTYPE0_REG		0x1d00
#define HISI_UC_EVTYPE_REG(n)		(HISI_UC_EVTYPE0_REG + (n) * 4)
#define HISI_UC_EVTYPE_REGn(n)		(0x1d00 + (n) * 4)
#define HISI_UC_EVTYPE_MASK		GENMASK(7, 0)
#define HISI_UC_CNTR0_REG		0x1e00
#define HISI_UC_CNTR_REG(n)		(HISI_UC_CNTR0_REG + (n) * 8)
#define HISI_UC_CNTR_REGn(n)		(0x1e00 + (n) * 8)

#define HISI_UC_NR_COUNTERS		0x8
#define HISI_UC_V2_NR_EVENTS		0xFF
@@ -53,13 +51,13 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(uring_channel, config1, 5, 4);
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid, config1, 19, 6);
HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_en, config1, 20, 20);

static int hisi_uc_pmu_check_format(struct perf_event *event)
static int hisi_uc_pmu_check_filter(struct perf_event *event)
{
	struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu);

	if (hisi_get_srcid_en(event) && !hisi_get_rd_req_en(event)) {
		dev_err(uc_pmu->dev,
			"Failed to set srcid: depending on read request enabled!\n");
			"rcid_en depends on rd_req_en being enabled!\n");
		return -EINVAL;
	}

@@ -237,10 +235,10 @@ static void hisi_uc_pmu_write_evtype(struct hisi_pmu *uc_pmu, int idx, u32 type)
	 * There are 2 32-bit event select registers for the
	 * 8 hardware counters, each event code is 8-bit wide.
	 */
	val = readl(uc_pmu->base + HISI_UC_EVTYPE_REG(idx / 4));
	val = readl(uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4));
	val &= ~(HISI_UC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx));
	val |= (type << HISI_PMU_EVTYPE_SHIFT(idx));
	writel(val, uc_pmu->base + HISI_UC_EVTYPE_REG(idx / 4));
	writel(val, uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4));
}

static void hisi_uc_pmu_start_counters(struct hisi_pmu *uc_pmu)
@@ -286,14 +284,13 @@ static void hisi_uc_pmu_disable_counter(struct hisi_pmu *uc_pmu,
static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu,
				    struct hw_perf_event *hwc)
{
	return readq(uc_pmu->base + HISI_UC_CNTR_REG(hwc->idx));
	return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
}

static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
				      struct hw_perf_event *hwc, u64 val)
{
	hisi_uc_pmu_start_counters(uc_pmu);
	writeq(val, uc_pmu->base + HISI_UC_CNTR_REG(hwc->idx));
	writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
}

static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
@@ -302,7 +299,6 @@ static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
	u32 val;

	val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG);
	/* Write 0 to enable interrupt */
	val &= ~(1 << hwc->idx);
	writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG);
}
@@ -313,7 +309,6 @@ static void hisi_uc_pmu_disable_counter_int(struct hisi_pmu *uc_pmu,
	u32 val;

	val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG);
	/* Write 1 to mask interrupt */
	val |= (1 << hwc->idx);
	writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG);
}
@@ -332,8 +327,9 @@ static int hisi_uc_pmu_init_data(struct platform_device *pdev,
				 struct hisi_pmu *uc_pmu)
{
	/*
	 * Use the SCCL_ID and CCL_ID to identify the UC PMU, while
	 * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1].
	 * Use SCCL (Super CPU Cluster) ID and CCL (CPU Cluster) ID to
	 * identify the topology information of UC PMU devices in the chip.
	 * They have some CCLs per SCCL and then 4 UC PMU per CCL.
	 */
	if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
				     &uc_pmu->sccl_id)) {
@@ -435,7 +431,7 @@ static const struct attribute_group *hisi_uc_pmu_attr_groups[] = {
};

static const struct hisi_uncore_ops hisi_uncore_uc_pmu_ops = {
	.check_format		= hisi_uc_pmu_check_format,
	.check_filter		= hisi_uc_pmu_check_filter,
	.write_evtype		= hisi_uc_pmu_write_evtype,
	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
	.start_counters		= hisi_uc_pmu_start_counters,
@@ -538,6 +534,11 @@ static struct platform_driver hisi_uc_pmu_driver = {
	.driver = {
		.name = "hisi_uc_pmu",
		.acpi_match_table = hisi_uc_pmu_acpi_match,
		/*
		 * We have not worked out a safe bind/unbind process,
		 * Forcefully unbinding during sampling will lead to a
		 * kernel panic, so this is not supported yet.
		 */
		.suppress_bind_attrs = true,
	},
	.probe = hisi_uc_pmu_probe,