[PATCH v11 08/27] coresight: Move per-CPU source pointer to core layer

Leo Yan
2026-05-01T16:48:40Z

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.

Signed-off-by: Leo Yan <leo.yan@arm.com>
---
drivers/hwtracing/coresight/coresight-core.c | 38 ++++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-etm-perf.c | 14 +++------
drivers/hwtracing/coresight/coresight-priv.h | 1 +
3 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 1a389f63ed006e054dc6bc9764f8be8c1def9da1..6da15f2ef9dc9770e7aa79cc94a7ed3d2f3ad871 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -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;
@@ -1436,6 +1472,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)
@@ -1465,6 +1502,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);
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index ca250d626db8ff89682fcb78e35a246cbd0ae367..d3b13ef130439fd501f88395d0de9dd21b84b827 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -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);
@@ -380,7 +379,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
@@ -856,17 +855,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);

diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index a0cd1a0ad2a182f762cc9721fd93725f2d4ef688..7ce79fa36232bb1b0af768423777bab27cacee95 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -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);

--
2.34.1