drivers/perf: hisi: Refactor the detection of associated CPUs

There are two type of PMUs supported currently:
1) PMUs locate on SCCL (Super CPU Cluster [1]), associated with certain
   CCL (CPU cluster [1])(e.g. L3C PMU) or not (e.g. DDRC PMU)
2) PMUs locate on the SICL (Super IO Cluster [1]), which has no
   association with certain CPU topology (e.g. CPA PMU)

Currently the associated CPUs of the PMU is detected in the cpuhp online
callback as below:
- for type 1) the CPUs match PMU's sccl_id and ccl_id
- for type 2) PMU's sccl_id is -1 and all online CPUs will be associated

Since uncore PMUs are not bound to certain CPU context and event could be
counting started by any online CPU, the associated CPUs are just a
preference. Below disadvantages are observed in current implementation:
- the PMU cannot be used if its associated CPUs are offline
- SICL PMUs are associated to all the online CPUs implicitly without
  the consideration of locality

So refactor the way we detect the associated CPUs in below aspects:
- add a clear definition of hisi_pmu::associated_cpus
- initialize hisi_pmu::on_cpu based on locality if no associated CPU
  found, otherwise update it from associated CPUs
- drop the detection with a sccl_id of -1 for SICL PMUs

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/perf/hisi-pmu.rst?h=v6.12-rc1

Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Link: https://lore.kernel.org/r/20241210141525.37788-5-yangyicong@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Yicong Yang 2024-12-10 22:15:19 +08:00 committed by Will Deacon
parent 83037a47d3
commit 6cd137088f
2 changed files with 20 additions and 8 deletions

View file

@ -446,10 +446,6 @@ static bool hisi_pmu_cpu_is_associated_pmu(struct hisi_pmu *hisi_pmu)
{
int sccl_id, ccl_id;
/* If SCCL_ID is -1, the PMU is in a SICL and has no CPU affinity */
if (hisi_pmu->sccl_id == -1)
return true;
if (hisi_pmu->ccl_id == -1) {
/* If CCL_ID is -1, the PMU only shares the same SCCL */
hisi_read_sccl_and_ccl_id(&sccl_id, NULL);
@ -467,13 +463,25 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
struct hisi_pmu *hisi_pmu = hlist_entry_safe(node, struct hisi_pmu,
node);
if (!hisi_pmu_cpu_is_associated_pmu(hisi_pmu))
/*
* If the CPU is not associated to PMU, initialize the hisi_pmu->on_cpu
* based on the locality if it hasn't been initialized yet. For PMUs
* do have associated CPUs, it'll be updated later.
*/
if (!hisi_pmu_cpu_is_associated_pmu(hisi_pmu)) {
if (hisi_pmu->on_cpu != -1)
return 0;
hisi_pmu->on_cpu = cpumask_local_spread(0, dev_to_node(hisi_pmu->dev));
WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu)));
return 0;
}
cpumask_set_cpu(cpu, &hisi_pmu->associated_cpus);
/* If another CPU is already managing this PMU, simply return. */
if (hisi_pmu->on_cpu != -1)
/* If another associated CPU is already managing this PMU, simply return. */
if (hisi_pmu->on_cpu != -1 &&
cpumask_test_cpu(hisi_pmu->on_cpu, &hisi_pmu->associated_cpus))
return 0;
/* Use this CPU in cpumask for event counting */

View file

@ -87,7 +87,11 @@ struct hisi_pmu {
const struct hisi_uncore_ops *ops;
const struct hisi_pmu_dev_info *dev_info;
struct hisi_pmu_hwevents pmu_events;
/* associated_cpus: All CPUs associated with the PMU */
/*
* 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
* which case any online CPU will be used.
*/
cpumask_t associated_cpus;
/* CPU used for counting */
int on_cpu;