From: Leo Yan Date: Fri, 15 May 2026 20:08:26 +0000 (+0100) Subject: coresight: Save active path for system tracers X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=ac8eac9062eefc33f5e97e526eef69bc98ecbdbc;p=thirdparty%2Fkernel%2Flinux.git coresight: Save active path for system tracers This commit only set the path pointer for system tracers (e.g. STM) in coresight_{enable|disable}_source(). Later changes will set the path pointer locally for per-CPU sources. This is because the mode and path pointer must be set together, so that they are observed atomically by the CPU PM notifier. Reviewed-by: Yeoreum Yun Reviewed-by: James Clark Tested-by: James Clark Tested-by: Jie Gan Signed-off-by: Leo Yan Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-19-f88c4a3ecfe9@arm.com --- diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index f833b73ebc16..7f6febd20faa 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -487,10 +487,28 @@ int coresight_enable_source(struct coresight_device *csdev, struct perf_event *event, enum cs_mode mode, struct coresight_path *path) { + int ret; + if (!coresight_is_device_source(csdev)) return -EINVAL; - return source_ops(csdev)->enable(csdev, event, mode, path); + ret = source_ops(csdev)->enable(csdev, event, mode, path); + if (ret) + return ret; + + /* + * Update the path pointer until after the source is enabled to avoid + * races where multiple paths attempt to enable the same source. + * + * Do not set the path pointer here for per-CPU sources; set it locally + * on the CPU instead. Otherwise, there is a window where the path is + * enabled but the pointer is not yet set, causing CPU PM notifiers to + * miss PM operations due to reading a NULL pointer. + */ + if (!coresight_is_percpu_source(csdev)) + csdev->path = path; + + return 0; } void coresight_disable_source(struct coresight_device *csdev, void *data) @@ -498,6 +516,9 @@ void coresight_disable_source(struct coresight_device *csdev, void *data) if (!coresight_is_device_source(csdev)) return; + if (!coresight_is_percpu_source(csdev)) + csdev->path = NULL; + source_ops(csdev)->disable(csdev, data); } EXPORT_SYMBOL_GPL(coresight_disable_source); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 5f9d7ea9f594..58d474b26980 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -257,6 +257,7 @@ struct coresight_trace_id_map { * by @coresight_ops. * @access: Device i/o access abstraction for this device. * @dev: The device entity associated to this component. + * @path: Activated path pointer (only used for source device). * @mode: The device mode, i.e sysFS, Perf or disabled. This is actually * an 'enum cs_mode' but stored in an atomic type. Access is always * through atomic APIs, ensuring SMP-safe synchronisation between @@ -291,6 +292,7 @@ struct coresight_device { const struct coresight_ops *ops; struct csdev_access access; struct device dev; + struct coresight_path *path; atomic_t mode; int refcnt; int cpu;