[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