mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
drivers/perf: hisi: Extract topology information to a separate structure
HiSilicon Uncore PMUs are identified by the IDs of the topology element on which the PMUs are located. Add a new separate struct hisi_pmu_toplogy to encapsulate this information. Add additional documentation on the meaning of each ID. - make sccl_id and sicl_id into a union since they're exclusive. It can also be accessed by scl_id if the SICL/SCCL distinction is not relevant - make index_id and sub_id signed so -1 may be used to indicate the PMU doesn't have this topology element or it could not be retrieved. This patch should have no functional changes. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Link: https://lore.kernel.org/r/20241210141525.37788-6-yangyicong@huawei.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
6cd137088f
commit
c192026cee
|
|
@ -181,19 +181,19 @@ 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)) {
|
||||
&cpa_pmu->topo.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)) {
|
||||
&cpa_pmu->topo.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->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);
|
||||
|
|
@ -311,8 +311,8 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_cpa%u",
|
||||
cpa_pmu->sicl_id, cpa_pmu->index_id);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_cpa%d",
|
||||
cpa_pmu->topo.sicl_id, cpa_pmu->topo.index_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -302,18 +302,18 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev,
|
|||
* DDRC PMU, while SCCL_ID is in MPIDR[aff2].
|
||||
*/
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,ch-id",
|
||||
&ddrc_pmu->index_id)) {
|
||||
&ddrc_pmu->topo.index_id)) {
|
||||
dev_err(&pdev->dev, "Can not read ddrc channel-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
|
||||
&ddrc_pmu->sccl_id)) {
|
||||
&ddrc_pmu->topo.sccl_id)) {
|
||||
dev_err(&pdev->dev, "Can not read ddrc sccl-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* DDRC PMUs only share the same SCCL */
|
||||
ddrc_pmu->ccl_id = -1;
|
||||
ddrc_pmu->topo.ccl_id = -1;
|
||||
|
||||
ddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ddrc_pmu->base)) {
|
||||
|
|
@ -324,7 +324,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->sub_id)) {
|
||||
&ddrc_pmu->topo.sub_id)) {
|
||||
dev_err(&pdev->dev, "Can not read sub-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -501,13 +501,13 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
|
|||
|
||||
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);
|
||||
"hisi_sccl%d_ddrc%d_%d",
|
||||
ddrc_pmu->topo.sccl_id, ddrc_pmu->topo.index_id,
|
||||
ddrc_pmu->topo.sub_id);
|
||||
else
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
||||
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
|
||||
ddrc_pmu->index_id);
|
||||
"hisi_sccl%d_ddrc%d", ddrc_pmu->topo.sccl_id,
|
||||
ddrc_pmu->topo.index_id);
|
||||
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
|
|||
* SCCL_ID is in MPIDR[aff2].
|
||||
*/
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
|
||||
&hha_pmu->sccl_id)) {
|
||||
&hha_pmu->topo.sccl_id)) {
|
||||
dev_err(&pdev->dev, "Can not read hha sccl-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -310,7 +310,7 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
|
|||
* both "hisilicon, idx-id" as preference, if available.
|
||||
*/
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
|
||||
&hha_pmu->index_id)) {
|
||||
&hha_pmu->topo.index_id)) {
|
||||
status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
|
||||
"_UID", NULL, &id);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
|
@ -318,10 +318,10 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
hha_pmu->index_id = id;
|
||||
hha_pmu->topo.index_id = id;
|
||||
}
|
||||
/* HHA PMUs only share the same SCCL */
|
||||
hha_pmu->ccl_id = -1;
|
||||
hha_pmu->topo.ccl_id = -1;
|
||||
|
||||
hha_pmu->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hha_pmu->base)) {
|
||||
|
|
@ -510,8 +510,8 @@ 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);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_hha%d",
|
||||
hha_pmu->topo.sccl_id, hha_pmu->topo.index_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -360,13 +360,13 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev,
|
|||
* 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->sccl_id)) {
|
||||
&l3c_pmu->topo.sccl_id)) {
|
||||
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->ccl_id)) {
|
||||
&l3c_pmu->topo.ccl_id)) {
|
||||
dev_err(&pdev->dev, "Can not read l3c ccl-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -544,8 +544,8 @@ 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);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_l3c%d",
|
||||
l3c_pmu->topo.sccl_id, l3c_pmu->topo.ccl_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -274,19 +274,19 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev,
|
|||
* to identify the PA PMU.
|
||||
*/
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
|
||||
&pa_pmu->sicl_id)) {
|
||||
&pa_pmu->topo.sicl_id)) {
|
||||
dev_err(&pdev->dev, "Cannot read sicl-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id",
|
||||
&pa_pmu->index_id)) {
|
||||
&pa_pmu->topo.index_id)) {
|
||||
dev_err(&pdev->dev, "Cannot read idx-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pa_pmu->ccl_id = -1;
|
||||
pa_pmu->sccl_id = -1;
|
||||
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)
|
||||
|
|
@ -488,9 +488,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_%s%u",
|
||||
pa_pmu->sicl_id, pa_pmu->dev_info->name,
|
||||
pa_pmu->index_id);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_%s%d",
|
||||
pa_pmu->topo.sicl_id, pa_pmu->dev_info->name,
|
||||
pa_pmu->topo.index_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -444,18 +444,19 @@ static void hisi_read_sccl_and_ccl_id(int *scclp, int *cclp)
|
|||
*/
|
||||
static bool hisi_pmu_cpu_is_associated_pmu(struct hisi_pmu *hisi_pmu)
|
||||
{
|
||||
struct hisi_pmu_topology *topo = &hisi_pmu->topo;
|
||||
int sccl_id, ccl_id;
|
||||
|
||||
if (hisi_pmu->ccl_id == -1) {
|
||||
if (topo->ccl_id == -1) {
|
||||
/* If CCL_ID is -1, the PMU only shares the same SCCL */
|
||||
hisi_read_sccl_and_ccl_id(&sccl_id, NULL);
|
||||
|
||||
return sccl_id == hisi_pmu->sccl_id;
|
||||
return sccl_id == topo->sccl_id;
|
||||
}
|
||||
|
||||
hisi_read_sccl_and_ccl_id(&sccl_id, &ccl_id);
|
||||
|
||||
return sccl_id == hisi_pmu->sccl_id && ccl_id == hisi_pmu->ccl_id;
|
||||
return sccl_id == topo->sccl_id && ccl_id == topo->ccl_id;
|
||||
}
|
||||
|
||||
int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
|
||||
|
|
|
|||
|
|
@ -81,12 +81,43 @@ struct hisi_pmu_hwevents {
|
|||
const struct attribute_group **attr_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hisi_pmu_topology - Describe the topology hierarchy on which the PMU
|
||||
* is located.
|
||||
* @sccl_id: ID of the SCCL on which the PMU locate is located.
|
||||
* @sicl_id: ID of the SICL on which the PMU locate is located.
|
||||
* @scl_id: ID used by the core which is unaware of the SCCL/SICL.
|
||||
* @ccl_id: ID of the CCL (CPU cluster) on which the PMU is located.
|
||||
* @index_id: the ID of the PMU module if there're several PMUs at a
|
||||
* particularly location in the topology.
|
||||
* @sub_id: submodule ID of the PMU. For example we use this for DDRC PMU v2
|
||||
* since each DDRC has more than one DMC
|
||||
*
|
||||
* The ID will be -1 if the PMU isn't located on a certain topology.
|
||||
*/
|
||||
struct hisi_pmu_topology {
|
||||
/*
|
||||
* SCCL (Super CPU CLuster) and SICL (Super I/O Cluster) are parallel
|
||||
* so a PMU cannot locate on a SCCL and a SICL. If the SCCL/SICL
|
||||
* distinction is not relevant, use scl_id instead.
|
||||
*/
|
||||
union {
|
||||
int sccl_id;
|
||||
int sicl_id;
|
||||
int scl_id;
|
||||
};
|
||||
int ccl_id;
|
||||
int index_id;
|
||||
int sub_id;
|
||||
};
|
||||
|
||||
/* Generic pmu struct for different pmu types */
|
||||
struct hisi_pmu {
|
||||
struct pmu pmu;
|
||||
const struct hisi_uncore_ops *ops;
|
||||
const struct hisi_pmu_dev_info *dev_info;
|
||||
struct hisi_pmu_hwevents pmu_events;
|
||||
struct hisi_pmu_topology topo;
|
||||
/*
|
||||
* CPUs associated to the PMU and are preferred to use for counting.
|
||||
* Could be empty if PMU has no association (e.g. PMU on SICL), in
|
||||
|
|
@ -98,14 +129,7 @@ struct hisi_pmu {
|
|||
int irq;
|
||||
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 */
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -293,19 +293,19 @@ static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
|
|||
* while SCCL_ID is from MPIDR_EL1 by CPU.
|
||||
*/
|
||||
if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id",
|
||||
&sllc_pmu->sccl_id)) {
|
||||
&sllc_pmu->topo.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)) {
|
||||
&sllc_pmu->topo.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->topo.ccl_id = -1;
|
||||
|
||||
sllc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(sllc_pmu->base)) {
|
||||
|
|
@ -433,8 +433,8 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_sllc%u",
|
||||
sllc_pmu->sccl_id, sllc_pmu->index_id);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_sllc%d",
|
||||
sllc_pmu->topo.sccl_id, sllc_pmu->topo.index_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -372,19 +372,19 @@ static int hisi_uc_pmu_init_data(struct platform_device *pdev,
|
|||
* 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)) {
|
||||
&uc_pmu->topo.sccl_id)) {
|
||||
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->ccl_id)) {
|
||||
&uc_pmu->topo.ccl_id)) {
|
||||
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->sub_id)) {
|
||||
&uc_pmu->topo.sub_id)) {
|
||||
dev_err(&pdev->dev, "Can not read sub-id!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -538,8 +538,9 @@ static int hisi_uc_pmu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_uc%d_%u",
|
||||
uc_pmu->sccl_id, uc_pmu->ccl_id, uc_pmu->sub_id);
|
||||
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_uc%d_%d",
|
||||
uc_pmu->topo.sccl_id, uc_pmu->topo.ccl_id,
|
||||
uc_pmu->topo.sub_id);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user