[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