[PATCH v8 18/23] coresight: Control path during CPU idle
Leo Yan
leo.yan at arm.com
Wed Mar 25 07:26:55 PDT 2026
Control links and helpers on an active path during CPU idle.
The helper coresight_get_local_cpu_path() uses coresight_dev_lock to
exclusive access to the per-CPU source pointer, then retrieves the path
pointer (csdev->path). The path pointer is only set via an SMP
call on the local CPU, which is serialized with CPU PM notifiers.
If the CPU PM notifier retrieves a non-NULL path pointer, it is safe to
iterate over the path and control it up to the node before the sink to
avoid latency.
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
drivers/hwtracing/coresight/coresight-core.c | 70 ++++++++++++++++++++++++----
1 file changed, 61 insertions(+), 9 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index a74a595dd61f1a004ee0ebc9600127c928ee9f16..5060ccbc8f4c82eb14ec081ec05709391a585a11 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -131,6 +131,29 @@ struct coresight_device *coresight_get_percpu_source(int cpu)
return per_cpu(csdev_source, cpu);
}
+/*
+ * The source device's csdev->path is always set on the local CPU.
+ * CPU PM notifiers also run on the same CPU, so accesses to
+ * csdev->path are serialized.
+ *
+ * When the path is constructed, each component on the path takes module
+ * reference counts, and the source's csdev->path is set last. Therefore,
+ * when the CPU PM notifier retrieves the path on the local CPU, a non-NULL
+ * csdev->path guarantees that the path is safe to iterate over.
+ */
+static struct coresight_path *coresight_get_local_cpu_path(void)
+{
+ struct coresight_device *csdev;
+
+ guard(raw_spinlock_irqsave)(&coresight_dev_lock);
+
+ csdev = this_cpu_read(csdev_source);
+ if (!csdev)
+ return NULL;
+
+ return csdev->path;
+}
+
static struct coresight_device *coresight_get_source(struct coresight_path *path)
{
struct coresight_device *csdev;
@@ -1768,8 +1791,14 @@ static void coresight_release_device_list(void)
}
}
-static bool coresight_pm_is_needed(struct coresight_device *csdev)
+static bool coresight_pm_is_needed(struct coresight_path *path)
{
+ struct coresight_device *csdev;
+
+ if (!path)
+ return false;
+
+ csdev = coresight_get_source(path);
if (!csdev)
return false;
@@ -1795,33 +1824,56 @@ static void coresight_pm_device_restore(struct coresight_device *csdev)
coresight_ops(csdev)->pm_restore_enable(csdev);
}
-static int coresight_pm_save(struct coresight_device *source)
+static int coresight_pm_save(struct coresight_path *path)
{
- return coresight_pm_device_save(source);
+ struct coresight_device *source;
+ struct coresight_node *from, *to;
+ int ret;
+
+ source = coresight_get_source(path);
+ ret = coresight_pm_device_save(source);
+ if (ret)
+ return ret;
+
+ from = coresight_path_first_node(path);
+ /* Up to the node before sink to avoid latency */
+ to = list_prev_entry(coresight_path_last_node(path), link);
+ coresight_disable_path_from_to(path, from, to);
+
+ return 0;
}
-static void coresight_pm_restore(struct coresight_device *source)
+static void coresight_pm_restore(struct coresight_path *path)
{
+ struct coresight_device *source;
+ struct coresight_node *from, *to;
+
+ source = coresight_get_source(path);
+ from = coresight_path_first_node(path);
+ /* Up to the node before sink to avoid latency */
+ to = list_prev_entry(coresight_path_last_node(path), link);
+ coresight_enable_path_from_to(path, coresight_get_mode(source),
+ from, to);
+
coresight_pm_device_restore(source);
}
static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
void *v)
{
- struct coresight_device *source =
- coresight_get_percpu_source(smp_processor_id());
+ struct coresight_path *path = coresight_get_local_cpu_path();
- if (!coresight_pm_is_needed(source))
+ if (!coresight_pm_is_needed(path))
return NOTIFY_OK;
switch (cmd) {
case CPU_PM_ENTER:
- if (coresight_pm_save(source))
+ if (coresight_pm_save(path))
return NOTIFY_BAD;
break;
case CPU_PM_EXIT:
case CPU_PM_ENTER_FAILED:
- coresight_pm_restore(source);
+ coresight_pm_restore(path);
break;
default:
return NOTIFY_DONE;
--
2.34.1
More information about the linux-arm-kernel
mailing list