Hi Leo,
Since we are now passing in_idle to enable/disable path would if not be easier to choose the correct callback in there?
e,g,
in enable path something like
case CORESIGHT_DEV_TYPE_SINK: if (in_idle && cs_ops(csdev)->pm_restore_enable) cs_ops->pm_restore_enable(csdev) else sink_ops(csdev)->enable(csdev, mode,data)
This would remove the need for new functions and replicating the enable / disable helpers logic
Regards
Mike
On Mon, 15 Sept 2025 at 11:34, Leo Yan leo.yan@arm.com wrote:
Unlike a system level's sink, the per-CPU sink may lose power during CPU idle states. Currently, this refers specifically to TRBE as the sink. This commit registers save and restore callbacks for the per-CPU sink via the PM notifier.
There are no changes to the coresight_enable_helpers() function; the code movement is solely for compilation purposes.
Signed-off-by: Leo Yan leo.yan@arm.com
drivers/hwtracing/coresight/coresight-core.c | 101 +++++++++++++++++++++------ include/linux/coresight.h | 4 ++ 2 files changed, 82 insertions(+), 23 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 04e8c3b862494abb2a5a46d385f0ff4cad93b71f..ef9dbba285710fe508580ee2726e22bcc654014e 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -393,6 +393,25 @@ static void coresight_disable_helper(struct coresight_device *csdev, void *data) helper_ops(csdev)->disable(csdev, data); }
+static int coresight_enable_helpers(struct coresight_device *csdev,
enum cs_mode mode, void *data)
+{
int i, ret = 0;
struct coresight_device *helper;
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
helper = csdev->pdata->out_conns[i]->dest_dev;
if (!helper || !coresight_is_helper(helper))
continue;
ret = coresight_enable_helper(helper, mode, data);
if (ret)
return ret;
}
return 0;
+}
static void coresight_disable_helpers(struct coresight_device *csdev, void *data) { int i; @@ -480,6 +499,43 @@ static void coresight_restore_source(struct coresight_device *csdev) source_ops(csdev)->restore(csdev); }
+static int coresight_save_percpu_sink(struct coresight_device *csdev) +{
int ret;
if (csdev && sink_ops(csdev)->save) {
ret = sink_ops(csdev)->save(csdev);
if (ret)
return ret;
coresight_disable_helpers(csdev, NULL);
}
/* Return success if callback is not supported */
return 0;
+}
+static int coresight_restore_percpu_sink(struct coresight_device *csdev,
struct coresight_path *path,
enum cs_mode mode)
+{
int ret = 0;
if (csdev && sink_ops(csdev)->restore) {
ret = coresight_enable_helpers(csdev, mode, path);
if (ret)
return ret;
ret = sink_ops(csdev)->restore(csdev);
if (ret) {
coresight_disable_helpers(csdev, path);
return ret;
}
}
return ret;
+}
/*
- coresight_disable_path_from : Disable components in the given path beyond
- @nd in the list. If @nd is NULL, all the components, except the SOURCE are
@@ -553,25 +609,6 @@ void coresight_disable_path(struct coresight_path *path) } EXPORT_SYMBOL_GPL(coresight_disable_path);
-static int coresight_enable_helpers(struct coresight_device *csdev,
enum cs_mode mode, void *data)
-{
int i, ret = 0;
struct coresight_device *helper;
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
helper = csdev->pdata->out_conns[i]->dest_dev;
if (!helper || !coresight_is_helper(helper))
continue;
ret = coresight_enable_helper(helper, mode, data);
if (ret)
return ret;
}
return 0;
-}
static int _coresight_enable_path(struct coresight_path *path, enum cs_mode mode, void *sink_data, bool in_idle) @@ -1670,9 +1707,12 @@ EXPORT_SYMBOL_GPL(coresight_alloc_device_name); static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, void *v) {
int ret; unsigned int cpu = smp_processor_id(); struct coresight_device *source = per_cpu(csdev_source, cpu); struct coresight_path *path;
struct coresight_device *sink;
enum cs_mode mode; if (!coresight_need_save_restore_source(source)) return NOTIFY_OK;
@@ -1685,18 +1725,33 @@ static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, if (WARN_ON(!path)) return NOTIFY_BAD;
sink = coresight_get_sink(path);
mode = coresight_get_mode(source);
switch (cmd) { case CPU_PM_ENTER: if (coresight_save_source(source)) return NOTIFY_BAD;
coresight_disable_path_from(path, NULL, true);
ret = 0;
if (coresight_is_percpu_sink(sink))
ret = coresight_save_percpu_sink(sink);
else
coresight_disable_path_from(path, NULL, true);
if (ret) {
coresight_restore_source(source);
return NOTIFY_BAD;
} break; case CPU_PM_EXIT: case CPU_PM_ENTER_FAILED:
if (_coresight_enable_path(path,
coresight_get_mode(source),
NULL, true))
if (coresight_is_percpu_sink(sink))
ret = coresight_restore_percpu_sink(sink, path, mode);
else
ret = _coresight_enable_path(path, mode, NULL, true);
if (ret) return NOTIFY_BAD; coresight_restore_source(source);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 462876b5a870f3e93ad2a1807a9045d5eb115ccd..21bb99f9684747d7a610aa7185e1ba5f987248d9 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -363,6 +363,8 @@ enum cs_mode {
- @alloc_buffer: initialises perf's ring buffer for trace collection.
- @free_buffer: release memory allocated in @get_config.
- @update_buffer: update buffer pointers after a trace session.
- @save: save context for a sink.
*/
- @restore: restore context for a sink.
struct coresight_ops_sink { int (*enable)(struct coresight_device *csdev, enum cs_mode mode, @@ -375,6 +377,8 @@ struct coresight_ops_sink { unsigned long (*update_buffer)(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config);
int (*save)(struct coresight_device *csdev);
int (*restore)(struct coresight_device *csdev);
};
/**
-- 2.34.1