[PATCH v6 02/19] coresight: Set per-CPU source pointer

Suzuki K Poulose suzuki.poulose at arm.com
Fri Mar 13 04:18:20 PDT 2026


On 05/03/2026 10:17, Leo Yan wrote:
> Add coresight_{set|clear}_percpu_source() helpers to set and clear the
> per-CPU source device.  These helpers are called during device
> registration and unregistration.
> 
> If the helper is called from a CPU hotplug notifier (see
> etm4_probe_cpu()), it sets the pointer directly since it is already
> running on the local CPU.
> 
> Otherwise, to avoid races with CPU hotplug and CPU idle, it acquires the
> CPU lock and issues an SMP call to update the per-CPU pointer on the
> target CPU.  If that fails, it sets the pointer as a last resort.
> 
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
>   drivers/hwtracing/coresight/coresight-core.c | 54 ++++++++++++++++++++++++++++
>   1 file changed, 54 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index f191a0fe802ac6ae1342872e01fff463775c8a20..cda1e9b065a056e57030e52e07502554c71014ca 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -34,6 +34,7 @@
>    */
>   DEFINE_MUTEX(coresight_mutex);
>   static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
> +static DEFINE_PER_CPU(struct coresight_device *, csdev_source);
>   
>   /**
>    * struct coresight_node - elements of a path, from source to sink
> @@ -82,6 +83,56 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
>   }
>   EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
>   
> +static void coresight_set_percpu_source_local(void *csdev)
> +{
> +	this_cpu_write(csdev_source, csdev);
> +}
> +
> +static void _coresight_set_percpu_source(int cpu, struct coresight_device *csdev)
> +{
> +	/*
> +	 * Directly set per CPU pointer if running on the local CPU.  This
> +	 * avoids to acquire CPU lock duplicately if it is called from CPU
> +	 * hotplug notifier, see etm4_probe_cpu().
> +	 */
> +	if (get_cpu() == cpu) {
> +		this_cpu_write(csdev_source, csdev);
> +		put_cpu();
> +		return;
> +	}
> +
> +	put_cpu();
> +
> +	/* Avoid race condition with CPU hotplug */
> +	guard(cpus_read_lock)();
> +
> +	if (!smp_call_function_single(cpu, coresight_set_percpu_source_local,
> +				      csdev, 1))
> +		return;
> +
> +	/*
> +	 * If SMP call fails (e.g., the CPU is offline), directly update the
> +	 * per CPU pointer as last resort.
> +	 */
> +	per_cpu(csdev_source, cpu) = csdev;
> +}
> +
> +static void coresight_set_percpu_source(struct coresight_device *csdev)
> +{
> +	if (!coresight_is_percpu_source(csdev))
> +		return;
> +
> +	_coresight_set_percpu_source(csdev->cpu, csdev);
> +}
> +
> +static void coresight_clear_percpu_source(struct coresight_device *csdev)
> +{
> +	if (!coresight_is_percpu_source(csdev))
> +		return;
> +
> +	_coresight_set_percpu_source(csdev->cpu, NULL);
> +}
> +



---8>---
>   static struct coresight_device *coresight_get_source(struct coresight_path *path)
>   {
>   	struct coresight_device *csdev;
> @@ -1401,6 +1452,8 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
>   
>   	mutex_unlock(&coresight_mutex);
>   
> +	coresight_set_percpu_source(csdev);
> +
>   	if (cti_assoc_ops && cti_assoc_ops->add)
>   		cti_assoc_ops->add(csdev);
>   
> @@ -1427,6 +1480,7 @@ void coresight_unregister(struct coresight_device *csdev)
>   	if (cti_assoc_ops && cti_assoc_ops->remove)
>   		cti_assoc_ops->remove(csdev);
>   
> +	coresight_clear_percpu_source(csdev);

Should these be done with the mutex lock held ?

>   	mutex_lock(&coresight_mutex);
>   	etm_perf_del_symlink_sink(csdev);
>   	coresight_remove_conns(csdev);
> 




More information about the linux-arm-kernel mailing list