[PATCH v4 03/15] coresight: Register CPU PM notifier in core layer
Suzuki K Poulose
suzuki.poulose at arm.com
Tue Nov 11 04:13:38 PST 2025
On 04/11/2025 15:21, Leo Yan 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 device 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 | 70 ++++++++++++++++++++++++++++
> include/linux/coresight.h | 2 +
> 2 files changed, 72 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 25a530cde8938b366bbb144fdcc107271ebae276..f642190740b93555084584abbc1d9426cc87ec7c 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>
> @@ -1575,6 +1576,68 @@ char *coresight_alloc_device_name(struct coresight_dev_list *dict,
> }
> EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
>
> +static bool coresight_pm_is_needed(struct coresight_device *csdev)
> +{
> + if (!csdev)
> + return false;
> +
> + /* pm_save_disable() and pm_restore_enable() must be paired */
> + if (!coresight_ops(csdev)->pm_save_disable ||
> + !coresight_ops(csdev)->pm_restore_enable)
> + return false;
> +
> + return true;
> +}
> +
> +static int coresight_pm_save(struct coresight_device *csdev)
> +{
> + return coresight_ops(csdev)->pm_save_disable(csdev);
> +}
> +
> +static void coresight_pm_restore(struct coresight_device *csdev)
> +{
> + coresight_ops(csdev)->pm_restore_enable(csdev);
> +}
> +
> +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 (!coresight_pm_is_needed(source))
> + return NOTIFY_OK;
> +
> + switch (cmd) {
> + case CPU_PM_ENTER:
> + if (coresight_pm_save(source))
Unless we do the "set_per_cpu_source" *ON the CPU*, what guarantees that
this will vanish while we do the PM save ? e.g., UNLOAD coresight_etm4x
driver
Rest looks fine to me.
Suzuki
> + return NOTIFY_BAD;
> + break;
> + case CPU_PM_EXIT:
> + case CPU_PM_ENTER_FAILED:
> + coresight_pm_restore(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 +1692,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 +1712,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..b10ef4fa17a76b4d11223cc8fd43e5544b6ea8b9 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -439,6 +439,8 @@ struct coresight_ops_panic {
> struct coresight_ops {
> int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode,
> struct coresight_device *sink);
> + int (*pm_save_disable)(struct coresight_device *csdev);
> + void (*pm_restore_enable)(struct coresight_device *csdev);
> const struct coresight_ops_sink *sink_ops;
> const struct coresight_ops_link *link_ops;
> const struct coresight_ops_source *source_ops;
>
More information about the linux-arm-kernel
mailing list