drivers/perf: hisi: Add a common function to retrieve topology from firmware

Currently each type of uncore PMU driver uses almost the same routine
and the same firmware interface (or properties) to retrieve the topology
information, then reset the unused IDs to -1. Extract the common parts
to the framework in hisi_uncore_pmu_init_topology().

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20241210141525.37788-7-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Yicong Yang 2024-12-10 22:15:21 +08:00 committed by Will Deacon
parent c192026cee
commit 32528b165e
9 changed files with 60 additions and 43 deletions

View File

@ -180,20 +180,18 @@ 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->topo.sicl_id)) {
hisi_uncore_pmu_init_topology(cpa_pmu, &pdev->dev);
if (cpa_pmu->topo.sicl_id < 0) {
dev_err(&pdev->dev, "Can not read sicl-id\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
&cpa_pmu->topo.index_id)) {
if (cpa_pmu->topo.index_id < 0) {
dev_err(&pdev->dev, "Cannot read idx-id\n");
return -EINVAL;
}
cpa_pmu->topo.ccl_id = -1;
cpa_pmu->topo.sccl_id = -1;
cpa_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cpa_pmu->base))
return PTR_ERR(cpa_pmu->base);

View File

@ -297,6 +297,8 @@ 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)
{
hisi_uncore_pmu_init_topology(ddrc_pmu, &pdev->dev);
/*
* Use the SCCL_ID and DDRC channel ID to identify the
* DDRC PMU, while SCCL_ID is in MPIDR[aff2].
@ -307,13 +309,10 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
&ddrc_pmu->topo.sccl_id)) {
if (ddrc_pmu->topo.sccl_id < 0) {
dev_err(&pdev->dev, "Can not read ddrc sccl-id!\n");
return -EINVAL;
}
/* DDRC PMUs only share the same SCCL */
ddrc_pmu->topo.ccl_id = -1;
ddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ddrc_pmu->base)) {
@ -323,8 +322,7 @@ 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->topo.sub_id)) {
if (ddrc_pmu->topo.sub_id < 0) {
dev_err(&pdev->dev, "Can not read sub-id!\n");
return -EINVAL;
}

View File

@ -295,12 +295,13 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
unsigned long long id;
acpi_status status;
hisi_uncore_pmu_init_topology(hha_pmu, &pdev->dev);
/*
* Use SCCL_ID and UID to identify the HHA PMU, while
* SCCL_ID is in MPIDR[aff2].
*/
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
&hha_pmu->topo.sccl_id)) {
if (hha_pmu->topo.sccl_id < 0) {
dev_err(&pdev->dev, "Can not read hha sccl-id!\n");
return -EINVAL;
}
@ -309,8 +310,7 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
* 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->topo.index_id)) {
if (hha_pmu->topo.index_id < 0) {
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
"_UID", NULL, &id);
if (ACPI_FAILURE(status)) {
@ -320,8 +320,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
hha_pmu->topo.index_id = id;
}
/* HHA PMUs only share the same SCCL */
hha_pmu->topo.ccl_id = -1;
hha_pmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hha_pmu->base)) {

View File

@ -355,18 +355,18 @@ 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)
{
hisi_uncore_pmu_init_topology(l3c_pmu, &pdev->dev);
/*
* 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].
*/
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
&l3c_pmu->topo.sccl_id)) {
if (l3c_pmu->topo.sccl_id < 0) {
dev_err(&pdev->dev, "Can not read l3c sccl-id!\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
&l3c_pmu->topo.ccl_id)) {
if (l3c_pmu->topo.ccl_id < 0) {
dev_err(&pdev->dev, "Can not read l3c ccl-id!\n");
return -EINVAL;
}

View File

@ -269,25 +269,22 @@ static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx)
static int hisi_pa_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *pa_pmu)
{
hisi_uncore_pmu_init_topology(pa_pmu, &pdev->dev);
/*
* 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->topo.sicl_id)) {
if (pa_pmu->topo.sicl_id < 0) {
dev_err(&pdev->dev, "Cannot read sicl-id!\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
&pa_pmu->topo.index_id)) {
if (pa_pmu->topo.index_id < 0) {
dev_err(&pdev->dev, "Cannot read idx-id!\n");
return -EINVAL;
}
pa_pmu->topo.ccl_id = -1;
pa_pmu->topo.sccl_id = -1;
pa_pmu->dev_info = device_get_match_data(&pdev->dev);
if (!pa_pmu->dev_info)
return -ENODEV;

View File

@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/property.h>
#include <asm/cputype.h>
#include <asm/local64.h>
@ -530,6 +531,35 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
}
EXPORT_SYMBOL_NS_GPL(hisi_uncore_pmu_offline_cpu, "HISI_PMU");
/*
* Retrieve the topology information from the firmware for the hisi_pmu device.
* The topology ID will be -1 if we cannot initialize it, it may either due to
* the PMU doesn't locate on this certain topology or the firmware needs to be
* fixed.
*/
void hisi_uncore_pmu_init_topology(struct hisi_pmu *hisi_pmu, struct device *dev)
{
struct hisi_pmu_topology *topo = &hisi_pmu->topo;
topo->sccl_id = -1;
topo->ccl_id = -1;
topo->index_id = -1;
topo->sub_id = -1;
if (device_property_read_u32(dev, "hisilicon,scl-id", &topo->sccl_id))
dev_dbg(dev, "no scl-id present\n");
if (device_property_read_u32(dev, "hisilicon,ccl-id", &topo->ccl_id))
dev_dbg(dev, "no ccl-id present\n");
if (device_property_read_u32(dev, "hisilicon,idx-id", &topo->index_id))
dev_dbg(dev, "no idx-id present\n");
if (device_property_read_u32(dev, "hisilicon,sub-id", &topo->sub_id))
dev_dbg(dev, "no sub-id present\n");
}
EXPORT_SYMBOL_NS_GPL(hisi_uncore_pmu_init_topology, "HISI_PMU");
void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module)
{
struct pmu *pmu = &hisi_pmu->pmu;

View File

@ -160,6 +160,7 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
char *page);
int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
struct platform_device *pdev);
void hisi_uncore_pmu_init_topology(struct hisi_pmu *hisi_pmu, struct device *dev);
void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module);
#endif /* __HISI_UNCORE_PMU_H__ */

View File

@ -288,25 +288,22 @@ 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)
{
hisi_uncore_pmu_init_topology(sllc_pmu, &pdev->dev);
/*
* 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->topo.sccl_id)) {
if (sllc_pmu->topo.sccl_id < 0) {
dev_err(&pdev->dev, "Cannot read sccl-id!\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
&sllc_pmu->topo.index_id)) {
if (sllc_pmu->topo.index_id < 0) {
dev_err(&pdev->dev, "Cannot read idx-id!\n");
return -EINVAL;
}
/* SLLC PMUs only share the same SCCL */
sllc_pmu->topo.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");

View File

@ -11,7 +11,6 @@
#include <linux/irq.h>
#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include "hisi_uncore_pmu.h"
@ -366,25 +365,24 @@ static void hisi_uc_pmu_clear_int_status(struct hisi_pmu *uc_pmu, int idx)
static int hisi_uc_pmu_init_data(struct platform_device *pdev,
struct hisi_pmu *uc_pmu)
{
hisi_uncore_pmu_init_topology(uc_pmu, &pdev->dev);
/*
* 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->topo.sccl_id)) {
if (uc_pmu->topo.sccl_id < 0) {
dev_err(&pdev->dev, "Can not read uc sccl-id!\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id",
&uc_pmu->topo.ccl_id)) {
if (uc_pmu->topo.ccl_id < 0) {
dev_err(&pdev->dev, "Can not read uc ccl-id!\n");
return -EINVAL;
}
if (device_property_read_u32(&pdev->dev, "hisilicon,sub-id",
&uc_pmu->topo.sub_id)) {
if (uc_pmu->topo.sub_id < 0) {
dev_err(&pdev->dev, "Can not read sub-id!\n");
return -EINVAL;
}