[PATCH v1 05/11] coresight: Save activated path into source device

Leo Yan leo.yan at arm.com
Fri Jun 20 07:24:39 PDT 2025


On Tue, Jun 03, 2025 at 03:49:26PM +0100, James Clark wrote:

[...]

> > @@ -577,6 +583,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
> >   		}
> >   	}
> > +	source = coresight_get_source(path);
> > +	if (coresight_is_percpu_source(source))
> > +		source->path = path;
> > +
> >   out:
> >   	return ret;
> >   err_disable_helpers:
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index 64cee4040daa..cd9709a36b9c 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -265,6 +265,7 @@ struct coresight_trace_id_map {
> >    *		CS_MODE_SYSFS. Otherwise it must be accessed from inside the
> >    *		spinlock.
> >    * @orphan:	true if the component has connections that haven't been linked.
> > + * @path:	activated path pointer (only used for source device).
> >    * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs
> >    *		by writing a 1 to the 'enable_sink' file.  A sink can be
> >    *		activated but not yet enabled.  Enabling for a _sink_ happens
> > @@ -291,6 +292,8 @@ struct coresight_device {
> >   	local_t	mode;
> >   	int refcnt;
> >   	bool orphan;
> > +	/* activated path (for source only) */
> > +	struct coresight_path *path;
> 
> This is probably cleaner if it's saved in the new global per-cpu you added
> in patch 2. It's even more specific than "for source only", it's actually
> only for per-cpu sources so it's not worth having it on every device.

We can maintain Coresight path pointers in a global per-CPU data
structure. These path pointers are set and cleared during path enable
and disable operations, respectively. Idle threads can then access
these pointers for power management purposes.

However, the challenge is how we can safely access the path pointer from
an idle thread - particularly because idle threads cannot acquire
coresight_mutex, which is a sleepable lock. Consider a race condition
scenario where SysFS knobs frequently enable and disable paths, while
the corresponding CPUs enter and exit idle states. In such cases, if
an idle thread attempts to access the path pointers, we would need to
use raw spinlocks to ensure safety. This is problematic, as it could
result in the CPU suspend/resume flow waiting on SysFS operations.

This is why it turns out to use lockless approach. Two key background
info:

- Path pointers are not guaranteed to be safe to access in CPU power
  management (PM) notifiers. In contrast, the coresight_device pointer
  of a source device (e.g., an ETM) is safe to access.

  A path's lifecycle begins and ends with SysFS enable and disable
  operations. OTOH, an ETM’s coresight_device pointer is initialized
  during the probe phase and cleared during module removal. Module
  loading and unloading trigger SMP calls for initialization and
  cleanup. These synchronized SMP calls ensure that it is safe for CPU
  PM notifiers to access the source device structure.

- Another factor is that the device mode is used to determine whether
  it is safe to access the path pointer. When a source device is
  enabled, we must ensure that its state transitions from DISABLED to
  an enabled state on the target CPU. This guarantees that the mode,
  and any subsequent operations dependent on it, follow a strictly
  sequential order.

  CPU0                                    CPU1
  etm4_enable()
   ` etm4_enable_sysfs()
      ` smp_call_function_single() ---->  etm4_enable_hw_smp_call()
                                           ` coresight_take_mode(SYSFS)

                                           CPU idle:
                                           etm4_cpu_save()
                                            ` coresight_get_mode()
                                               ^^^
                                               Read out the SYSFS mode
                                               Safely access coresight_device::path

Therefore, safe access to the Coresight path heavily relies on the
mode (as part of the state machine). This is why the patch adds the
path pointer to the same structure as the mode.

Thanks,
Leo

> >   	/* sink specific fields */
> >   	bool sysfs_sink_activated;
> >   	struct dev_ext_attribute *ea;
> 



More information about the linux-arm-kernel mailing list