]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drivers/perf: hisi: Refactor the detection of associated CPUs
authorYicong Yang <yangyicong@hisilicon.com>
Tue, 10 Dec 2024 14:15:19 +0000 (22:15 +0800)
committerWill Deacon <will@kernel.org>
Tue, 10 Dec 2024 15:57:24 +0000 (15:57 +0000)
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>
drivers/perf/hisilicon/hisi_uncore_pmu.c
drivers/perf/hisilicon/hisi_uncore_pmu.h

index c775e4722dac48738779c5574e505f220eac52c4..e0f5fefcfee955efdf61549327beae44efd74993 100644 (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 */
index 25b2d43b72bf91b1be7bbf12b1705e36af498e6e..bd48338ce937cc0fe12a044b2791e2b8b7cf661e 100644 (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;