[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