[PATCH v2 21/28] coresight: Add per-CPU path pointer

From: Leo Yan
Date: Tue Jul 01 2025 - 10:59:11 EST


Introduce per-CPU path pointers, save activated paths into the
structure. This will be used by later changes for controlling the path
during CPU idle.

The path pointer is assigned before setting the source device mode to
active, and it is cleared after the device is changed to an inactive
mode. So safe access to path pointers is guaranteed when the device is
in an active mode.

The path enabling has been refactored: a new _coresight_enable_path()
function is introduced to enable components in the path. The existing
coresight_enable_path() function now calls this new helper and updates
the per-CPU pointers accordingly.

Signed-off-by: Leo Yan <leo.yan@xxxxxxx>
---
drivers/hwtracing/coresight/coresight-core.c | 48 ++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 45f15a1f51295b298073551cb328d20cc2c36cdb..ef2a0de366d9b12b4f609027c8b67f690cf84558 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -35,6 +35,27 @@ DEFINE_MUTEX(coresight_mutex);
static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
static DEFINE_PER_CPU(struct coresight_device *, csdev_source);

+/*
+ * Activated path pointer for a per-CPU source device. When enabling a path,
+ * the path pointer is first assigned, followed by a synchronous SMP call on
+ * the target CPU to transition the device mode from DISABLED to an enabled
+ * state. Conversely, during the disable flow, an SMP call on the target CPU
+ * transitions the device mode to DISABLED, after which the path pointer is
+ * cleared.
+ *
+ * per_cpu(csdev_cpu_path, csdev->cpu) = path
+ * coresight_take_mode(csdev, CS_MODE_SYSFS or CS_MODE_PERF)
+ *
+ * // Safe to access per_cpu(csdev_cpu_path, cpu);
+ *
+ * coresight_set_mode(csdev, CS_MODE_DISABLED)
+ * per_cpu(csdev_cpu_path, csdev->cpu) = NULL
+ *
+ * As a result, the device mode is used to determine whether it is safe
+ * to access the path pointer.
+ */
+static DEFINE_PER_CPU(struct coresight_path *, csdev_cpu_path);
+
/**
* struct coresight_node - elements of a path, from source to sink
* @csdev: Address of an element.
@@ -508,6 +529,12 @@ static void coresight_disable_path_from(struct coresight_path *path,

void coresight_disable_path(struct coresight_path *path)
{
+ struct coresight_device *source;
+
+ source = coresight_get_source(path);
+ if (coresight_is_percpu_source(source))
+ per_cpu(csdev_cpu_path, source->cpu) = NULL;
+
coresight_disable_path_from(path, NULL);
}
EXPORT_SYMBOL_GPL(coresight_disable_path);
@@ -531,8 +558,8 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
return 0;
}

-int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
- void *sink_data)
+static int _coresight_enable_path(struct coresight_path *path,
+ enum cs_mode mode, void *sink_data)
{
int ret = 0;
u32 type;
@@ -599,6 +626,23 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
goto out;
}

+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
+ void *sink_data)
+{
+ int ret;
+ struct coresight_device *source;
+
+ ret = _coresight_enable_path(path, mode, sink_data);
+ if (ret)
+ return ret;
+
+ source = coresight_get_source(path);
+ if (coresight_is_percpu_source(source))
+ per_cpu(csdev_cpu_path, source->cpu) = path;
+
+ return 0;
+}
+
struct coresight_device *coresight_get_sink(struct coresight_path *path)
{
struct coresight_device *csdev;

--
2.34.1