[PATCH v4 15/15] coresight: Move CPU hotplug callbacks to core layer

James Clark james.clark at linaro.org
Mon Nov 10 04:20:06 PST 2025



On 04/11/2025 3:21 pm, Leo Yan wrote:
> This commit moves CPU hotplug callbacks from ETMv4 driver to core layer.
> The motivation is the core layer can control all components on an
> activated path rather but not only managing tracer in ETMv4 driver.
> 
> The perf event layer will disable CoreSight PMU event 'cs_etm' when
> hotplug off a CPU.  That means a perf mode will be always converted to
> disabled mode in CPU hotplug.  Arm CoreSight CPU hotplug callbacks only
> need to handle the Sysfs mode and ignore the perf mode.
> 
> The core layer disables a source and the path when hotplug-off a CPU.
> 
> When hotplug-in a CPU, it does not re-enable even the trace was enabled
> before hotplug-off, in this case, users are asked to re-enable the trace
> via Sysfs interface.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c       | 41 +++++++++++++++++++++-
>   drivers/hwtracing/coresight/coresight-etm4x-core.c | 37 -------------------
>   2 files changed, 40 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 7095f9befa98c7d638f857466351ef7cd960fde7..9149f028031808dc2b7285f621b97f3631a02b01 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -1726,6 +1726,32 @@ static void coresight_pm_restore(struct coresight_device *csdev)
>   	coresight_ops(csdev)->pm_restore_enable(csdev);
>   }
>   
> +static int coresight_dying_cpu(unsigned int cpu)
> +{
> +	struct coresight_device *source = per_cpu(csdev_source, cpu);
> +	struct coresight_path *path;
> +
> +	if (!source || !source->path)
> +		return 0;
> +
> +	/*
> +	 * The perf event layer will disable PMU events in the CPU hotplug.
> +	 * CoreSight driver should never handle the CS_MODE_PERF case.
> +	 */
> +	if (coresight_get_mode(source) != CS_MODE_SYSFS)
> +		return 0;
> +
> +	/*
> +	 * Save 'source->path' here, as it will be cleared in
> +	 * coresight_disable_source().
> +	 */
> +	path = source->path;
> +
> +	coresight_disable_source(source, NULL);
> +	coresight_disable_path(path);
> +	return 0;

If the user is expected to re-enable and this new state is visible, 
don't you need to use the regular coresight_disable_sysfs() function? It 
calls coresight_disable_source_sysfs() which updates a refcount.

Maybe you didn't do it because it has a mutex in it? It would be easier 
to change that to a spinlock or take the mutex in a wrapper function and 
share the core disabling code with the hotplug path.

> +}
> +
>   static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
>   				   void *v)
>   {
> @@ -1757,11 +1783,24 @@ static struct notifier_block coresight_cpu_pm_nb = {
>   
>   static int __init coresight_pm_setup(void)
>   {
> -	return cpu_pm_register_notifier(&coresight_cpu_pm_nb);
> +	int ret;
> +
> +	ret = cpu_pm_register_notifier(&coresight_cpu_pm_nb);
> +	if (ret)
> +		return ret;
> +
> +	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
> +					"arm/coresight-core:starting",
> +					NULL, coresight_dying_cpu);
> +	if (ret)
> +		cpu_pm_unregister_notifier(&coresight_cpu_pm_nb);
> +
> +	return ret;
>   }
>   
>   static void coresight_pm_cleanup(void)
>   {
> +	cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
>   	cpu_pm_unregister_notifier(&coresight_cpu_pm_nb);
>   }
>   
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 7bea3d2c6f49a2169b8e3de1cb07cc22147aae3a..1730cee3c3e1845efb2be815553085aba1246cca 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -1802,33 +1802,6 @@ static int etm4_online_cpu(unsigned int cpu)
>   	return 0;
>   }
>   
> -static int etm4_starting_cpu(unsigned int cpu)
> -{
> -	if (!etmdrvdata[cpu])
> -		return 0;
> -
> -	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
> -	if (!etmdrvdata[cpu]->os_unlock)
> -		etm4_os_unlock(etmdrvdata[cpu]);
> -
> -	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
> -		etm4_enable_hw(etmdrvdata[cpu], true);
> -	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
> -	return 0;
> -}
> -
> -static int etm4_dying_cpu(unsigned int cpu)
> -{
> -	if (!etmdrvdata[cpu])
> -		return 0;
> -
> -	raw_spin_lock(&etmdrvdata[cpu]->spinlock);
> -	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
> -		etm4_disable_hw(etmdrvdata[cpu]);
> -	raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
> -	return 0;
> -}
> -
>   static bool etm4_need_save_restore_context(struct coresight_device *csdev)
>   {
>   	if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED)
> @@ -1915,13 +1888,6 @@ static int __init etm4_pm_setup(void)
>   {
>   	int ret;
>   
> -	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
> -					"arm/coresight4:starting",
> -					etm4_starting_cpu, etm4_dying_cpu);
> -
> -	if (ret)
> -		return ret;
> -
>   	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
>   					"arm/coresight4:online",
>   					etm4_online_cpu, NULL);
> @@ -1932,14 +1898,11 @@ static int __init etm4_pm_setup(void)
>   		return 0;
>   	}
>   
> -	/* failed dyn state - remove others */
> -	cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
>   	return ret;
>   }
>   
>   static void etm4_pm_clear(void)
>   {
> -	cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
>   	if (hp_online) {
>   		cpuhp_remove_state_nocalls(hp_online);
>   		hp_online = 0;
> 




More information about the linux-arm-kernel mailing list