]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
coresight: Move per-CPU source pointer to core layer
authorLeo Yan <leo.yan@arm.com>
Fri, 15 May 2026 20:08:16 +0000 (21:08 +0100)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 18 May 2026 09:18:45 +0000 (10:18 +0100)
Move the per-CPU source pointer from ETM perf to the core layer, as this
will be used for not only perf session and also for CPU PM notifiers.

Provides coresight_{set|clear|get}_percpu_source() helpers to access the
per-CPU source pointer. Add a raw spinlock to protect exclusive access.

Device registration and unregistration call the set and clear helpers
for init and teardown the pointers.

Update callers to invoke coresight_get_percpu_source() for retrieving
the pointer.

Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-9-f88c4a3ecfe9@arm.com
drivers/hwtracing/coresight/coresight-core.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/coresight/coresight-priv.h

index 6b098c3cab0b8a710863bceb2c5f9584ad0bd8af..995a4a1bab3d983141237f453b6f630e73e69e5e 100644 (file)
@@ -35,6 +35,9 @@
 DEFINE_MUTEX(coresight_mutex);
 static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
 
+static DEFINE_RAW_SPINLOCK(coresight_dev_lock);
+static DEFINE_PER_CPU(struct coresight_device *, csdev_source);
+
 /**
  * struct coresight_node - elements of a path, from source to sink
  * @csdev:     Address of an element.
@@ -82,6 +85,39 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
 }
 EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
 
+static void coresight_set_percpu_source(struct coresight_device *csdev)
+{
+       if (!csdev || !coresight_is_percpu_source(csdev))
+               return;
+
+       guard(raw_spinlock_irqsave)(&coresight_dev_lock);
+
+       /* Expect no device to be set yet */
+       WARN_ON(per_cpu(csdev_source, csdev->cpu));
+       per_cpu(csdev_source, csdev->cpu) = csdev;
+}
+
+static void coresight_clear_percpu_source(struct coresight_device *csdev)
+{
+       if (!csdev || !coresight_is_percpu_source(csdev))
+               return;
+
+       guard(raw_spinlock_irqsave)(&coresight_dev_lock);
+
+       /* The per-CPU pointer should contain the same csdev */
+       WARN_ON(per_cpu(csdev_source, csdev->cpu) != csdev);
+       per_cpu(csdev_source, csdev->cpu) = NULL;
+}
+
+struct coresight_device *coresight_get_percpu_source(int cpu)
+{
+       if (WARN_ON(cpu < 0))
+               return NULL;
+
+       guard(raw_spinlock_irqsave)(&coresight_dev_lock);
+       return per_cpu(csdev_source, cpu);
+}
+
 struct coresight_device *coresight_get_source(struct coresight_path *path)
 {
        struct coresight_device *csdev;
@@ -1452,6 +1488,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
        if (ret)
                goto out_unlock;
 
+       coresight_set_percpu_source(csdev);
        mutex_unlock(&coresight_mutex);
 
        if (cti_assoc_ops && cti_assoc_ops->add)
@@ -1481,6 +1518,7 @@ void coresight_unregister(struct coresight_device *csdev)
                cti_assoc_ops->remove(csdev);
 
        mutex_lock(&coresight_mutex);
+       coresight_clear_percpu_source(csdev);
        etm_perf_del_symlink_sink(csdev);
        coresight_remove_conns(csdev);
        coresight_clear_default_sink(csdev);
index bab85f7dac4757173912639ea016cdc32e5616fb..b9e556818c3c6873ed53e5a1b8052443dd7740d0 100644 (file)
@@ -49,7 +49,6 @@ struct etm_ctxt {
 };
 
 static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt);
-static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
 
 GEN_PMU_FORMAT_ATTR(cycacc);
 GEN_PMU_FORMAT_ATTR(timestamp);
@@ -386,7 +385,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
                struct coresight_path *path;
                struct coresight_device *csdev;
 
-               csdev = per_cpu(csdev_src, cpu);
+               csdev = coresight_get_percpu_source(cpu);
                /*
                 * If there is no ETM associated with this CPU clear it from
                 * the mask and continue with the rest. If ever we try to trace
@@ -864,17 +863,12 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link)
        if (!etm_perf_up)
                return -EPROBE_DEFER;
 
-       if (link) {
+       if (link)
                ret = sysfs_create_link(&pmu_dev->kobj, &cs_dev->kobj, entry);
-               if (ret)
-                       return ret;
-               per_cpu(csdev_src, cpu) = csdev;
-       } else {
+       else
                sysfs_remove_link(&pmu_dev->kobj, entry);
-               per_cpu(csdev_src, cpu) = NULL;
-       }
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(etm_perf_symlink);
 
index 75029744561f7744225c7b866eee60e0f7cf9e10..4d6f5bc1df9cc5dfd974a8b27820328e7916f169 100644 (file)
@@ -249,6 +249,7 @@ void coresight_add_helper(struct coresight_device *csdev,
 void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
 struct coresight_device *coresight_get_percpu_sink(int cpu);
 struct coresight_device *coresight_get_source(struct coresight_path *path);
+struct coresight_device *coresight_get_percpu_source(int cpu);
 void coresight_disable_source(struct coresight_device *csdev, void *data);
 void coresight_pause_source(struct coresight_device *csdev);
 int coresight_resume_source(struct coresight_device *csdev);