mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	drivers/perf: hisi: Add new functions for HHA PMU
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>
This commit is contained in:
		
							parent
							
								
									486a7f46b9
								
							
						
					
					
						commit
						932f6a99f9
					
				| @ -25,19 +25,136 @@ | |||||||
| #define HHA_VERSION		0x1cf0 | #define HHA_VERSION		0x1cf0 | ||||||
| #define HHA_PERF_CTRL		0x1E00 | #define HHA_PERF_CTRL		0x1E00 | ||||||
| #define HHA_EVENT_CTRL		0x1E04 | #define HHA_EVENT_CTRL		0x1E04 | ||||||
|  | #define HHA_SRCID_CTRL		0x1E08 | ||||||
|  | #define HHA_DATSRC_CTRL		0x1BF0 | ||||||
| #define HHA_EVENT_TYPE0		0x1E80 | #define HHA_EVENT_TYPE0		0x1E80 | ||||||
| /*
 | /*
 | ||||||
|  * Each counter is 48-bits and [48:63] are reserved |  * If the HW version only supports a 48-bit counter, then | ||||||
|  * which are Read-As-Zero and Writes-Ignored. |  * bits [63:48] are reserved, which are Read-As-Zero and | ||||||
|  |  * Writes-Ignored. | ||||||
|  */ |  */ | ||||||
| #define HHA_CNT0_LOWER		0x1F00 | #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_V1_NR_COUNTERS	0x10 | ||||||
|  | #define HHA_V2_NR_COUNTERS	0x8 | ||||||
| 
 | 
 | ||||||
| #define HHA_PERF_CTRL_EN	0x1 | #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_EVTYPE_NONE		0xff | ||||||
| #define HHA_V1_NR_EVENT		0x65 | #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 |  * Select the counter register offset using the counter index | ||||||
| @ -167,7 +284,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[] = { | static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = { | ||||||
| 	{ "HISI0243", }, | 	{ "HISI0243", }, | ||||||
| 	{}, | 	{ "HISI0244", }, | ||||||
|  | 	{} | ||||||
| }; | }; | ||||||
| MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match); | MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match); | ||||||
| 
 | 
 | ||||||
| @ -177,13 +295,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, | |||||||
| 	unsigned long long id; | 	unsigned long long id; | ||||||
| 	acpi_status status; | 	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 | 	 * Use SCCL_ID and UID to identify the HHA PMU, while | ||||||
| 	 * SCCL_ID is in MPIDR[aff2]. | 	 * SCCL_ID is in MPIDR[aff2]. | ||||||
| @ -193,6 +304,22 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, | |||||||
| 		dev_err(&pdev->dev, "Can not read hha sccl-id!\n"); | 		dev_err(&pdev->dev, "Can not read hha sccl-id!\n"); | ||||||
| 		return -EINVAL; | 		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 PMUs only share the same SCCL */ | ||||||
| 	hha_pmu->ccl_id = -1; | 	hha_pmu->ccl_id = -1; | ||||||
| 
 | 
 | ||||||
| @ -217,6 +344,20 @@ static const struct attribute_group hisi_hha_pmu_v1_format_group = { | |||||||
| 	.attrs = hisi_hha_pmu_v1_format_attr, | 	.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[] = { | static struct attribute *hisi_hha_pmu_v1_events_attr[] = { | ||||||
| 	HISI_PMU_EVENT_ATTR(rx_ops_num,		0x00), | 	HISI_PMU_EVENT_ATTR(rx_ops_num,		0x00), | ||||||
| 	HISI_PMU_EVENT_ATTR(rx_outer,		0x01), | 	HISI_PMU_EVENT_ATTR(rx_outer,		0x01), | ||||||
| @ -252,6 +393,20 @@ static const struct attribute_group hisi_hha_pmu_v1_events_group = { | |||||||
| 	.attrs = hisi_hha_pmu_v1_events_attr, | 	.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 DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); | ||||||
| 
 | 
 | ||||||
| static struct attribute *hisi_hha_pmu_cpumask_attrs[] = { | static struct attribute *hisi_hha_pmu_cpumask_attrs[] = { | ||||||
| @ -283,6 +438,14 @@ static const struct attribute_group *hisi_hha_pmu_v1_attr_groups[] = { | |||||||
| 	NULL, | 	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 = { | static const struct hisi_uncore_ops hisi_uncore_hha_ops = { | ||||||
| 	.write_evtype		= hisi_hha_pmu_write_evtype, | 	.write_evtype		= hisi_hha_pmu_write_evtype, | ||||||
| 	.get_event_idx		= hisi_uncore_pmu_get_event_idx, | 	.get_event_idx		= hisi_uncore_pmu_get_event_idx, | ||||||
| @ -296,6 +459,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = { | |||||||
| 	.read_counter		= hisi_hha_pmu_read_counter, | 	.read_counter		= hisi_hha_pmu_read_counter, | ||||||
| 	.get_int_status		= hisi_hha_pmu_get_int_status, | 	.get_int_status		= hisi_hha_pmu_get_int_status, | ||||||
| 	.clear_int_status	= hisi_hha_pmu_clear_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, | static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, | ||||||
| @ -311,12 +476,20 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, | |||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	hha_pmu->num_counters = HHA_V1_NR_COUNTERS; | 	if (hha_pmu->identifier >= HISI_PMU_V2) { | ||||||
| 	hha_pmu->counter_bits = 48; | 		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->ops = &hisi_uncore_hha_ops; | ||||||
| 	hha_pmu->dev = &pdev->dev; | 	hha_pmu->dev = &pdev->dev; | ||||||
| 	hha_pmu->on_cpu = -1; | 	hha_pmu->on_cpu = -1; | ||||||
| 	hha_pmu->check_event = HHA_V1_NR_EVENT; |  | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -358,7 +531,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) | |||||||
| 		.start		= hisi_uncore_pmu_start, | 		.start		= hisi_uncore_pmu_start, | ||||||
| 		.stop		= hisi_uncore_pmu_stop, | 		.stop		= hisi_uncore_pmu_stop, | ||||||
| 		.read		= hisi_uncore_pmu_read, | 		.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, | 		.capabilities	= PERF_PMU_CAP_NO_EXCLUDE, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Shaokun Zhang
						Shaokun Zhang