[PATCH v3 27/31] coresight: Add PM callbacks for percpu sink

Mike Leach mike.leach at linaro.org
Fri Oct 3 04:42:30 PDT 2025


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 at 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 at 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
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK



More information about the linux-arm-kernel mailing list