[PATCH v3 14/31] coresight: Register CPU PM notifier in core layer
Mike Leach
mike.leach at linaro.org
Thu Oct 2 04:12:08 PDT 2025
Hi Leo,
This could be made more generic from the start - as multiple devices
will eventually come under PM control.
Improve naming by explicitly mentioning _pm_ in function names.
On Mon, 15 Sept 2025 at 11:34, Leo Yan <leo.yan at arm.com> wrote:
>
> The current implementation only saves and restores the context for ETM
> sources while ignoring the context of links. However, if funnels or
> replicators on a linked path resides in a CPU or cluster power domain,
> the hardware context for the link will be lost after resuming from low
> power states.
>
> To support context management for links during CPU low power modes, a
> better way is to implement CPU PM callbacks in the Arm CoreSight core
> layer. As the core layer has sufficient information for linked paths,
> from tracers to links, which can be used for power management.
>
> As a first step, this patch registers CPU PM notifier in the core layer.
> If a source driver provides callbacks for saving and restoring context,
> these callbacks will be invoked in CPU suspend and resume.
>
> Further changes will extend for controlling path.
>
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
> drivers/hwtracing/coresight/coresight-core.c | 62 ++++++++++++++++++++++++++++
> include/linux/coresight.h | 4 ++
> 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 25a530cde8938b366bbb144fdcc107271ebae276..f944a610c85e9e3fce43497543ccc48ab7c2c0d9 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -6,6 +6,7 @@
> #include <linux/acpi.h>
> #include <linux/bitfield.h>
> #include <linux/build_bug.h>
> +#include <linux/cpu_pm.h>
> #include <linux/kernel.h>
> #include <linux/init.h>
> #include <linux/types.h>
> @@ -422,6 +423,21 @@ int coresight_resume_source(struct coresight_device *csdev)
> }
> EXPORT_SYMBOL_GPL(coresight_resume_source);
>
> +static int coresight_save_source(struct coresight_device *csdev)
See comments below & make this a generic coresight_pm_save() fn.
> +{
> + if (csdev && source_ops(csdev)->save)
and this could become
if(csdev && coresight_ops(csdev)->pm_save_disable)
> + return source_ops(csdev)->save(csdev);
> +
> + /* Return success if callback is not supported */
> + return 0;
> +}
> +
> +static void coresight_restore_source(struct coresight_device *csdev)
As above
> +{
> + if (csdev && source_ops(csdev)->restore)
> + source_ops(csdev)->restore(csdev);
> +}
> +
> /*
> * 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
> @@ -1575,6 +1591,45 @@ char *coresight_alloc_device_name(struct coresight_dev_list *dict,
> }
> EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
>
> +static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> + void *v)
> +{
> + unsigned int cpu = smp_processor_id();
> + struct coresight_device *source = per_cpu(csdev_source, cpu);
> +
> + if (!source)
> + return NOTIFY_OK;
> +
> + switch (cmd) {
> + case CPU_PM_ENTER:
> + if (coresight_save_source(source))
> + return NOTIFY_BAD;
> + break;
> + case CPU_PM_EXIT:
> + case CPU_PM_ENTER_FAILED:
> + coresight_restore_source(source);
> + break;
> + default:
> + return NOTIFY_DONE;
> + }
> +
> + return NOTIFY_OK;
> +}
> +
> +static struct notifier_block coresight_cpu_pm_nb = {
> + .notifier_call = coresight_cpu_pm_notify,
> +};
> +
> +static int __init coresight_pm_setup(void)
> +{
> + return cpu_pm_register_notifier(&coresight_cpu_pm_nb);
> +}
> +
> +static void coresight_pm_cleanup(void)
> +{
> + cpu_pm_unregister_notifier(&coresight_cpu_pm_nb);
> +}
> +
> const struct bus_type coresight_bustype = {
> .name = "coresight",
> };
> @@ -1629,9 +1684,15 @@ static int __init coresight_init(void)
>
> /* initialise the coresight syscfg API */
> ret = cscfg_init();
> + if (ret)
> + goto exit_notifier;
> +
> + ret = coresight_pm_setup();
> if (!ret)
> return 0;
>
> + cscfg_exit();
> +exit_notifier:
> atomic_notifier_chain_unregister(&panic_notifier_list,
> &coresight_notifier);
> exit_perf:
> @@ -1643,6 +1704,7 @@ static int __init coresight_init(void)
>
> static void __exit coresight_exit(void)
> {
> + coresight_pm_cleanup();
> cscfg_exit();
> atomic_notifier_chain_unregister(&panic_notifier_list,
> &coresight_notifier);
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 222597ec7a089e10ad763df206917e90f34bb5c2..d0764a9c7692181d2619c277acb83701c6b0115e 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -400,6 +400,8 @@ struct coresight_ops_link {
> * @disable: disables tracing for a source.
> * @resume_perf: resumes tracing for a source in perf session.
> * @pause_perf: pauses tracing for a source in perf session.
> + * @save: save context for a source.
> + * @restore: restore context for a source.
> */
> struct coresight_ops_source {
> int (*cpu_id)(struct coresight_device *csdev);
> @@ -409,6 +411,8 @@ struct coresight_ops_source {
> struct perf_event *event);
> int (*resume_perf)(struct coresight_device *csdev);
> void (*pause_perf)(struct coresight_device *csdev);
> + int (*save)(struct coresight_device *csdev);
> + void (*restore)(struct coresight_device *csdev);
These functions should have more explicit names - better describe what
they do and prevent a future developer thinking they are a benign
states save/restore set (as they used to be!)
e.g.:
pm_save_disable / pm_restore_enable.
Further, since the only parameter is the csdev being acted on, the
functions could be part of the generic coresight_ops structure (as per
trace_id) rather than repeat the addition for each coresight type
variant. Should simplify the handling code too.
Regards
Mike
> };
>
> /**
>
> --
> 2.34.1
>
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
More information about the linux-arm-kernel
mailing list