Small fixes for bugs in the CoreSight drivers that were found by Sashiko. Mostly reference and resource leaks on error paths, plus a deadlock, a missing lock, and a sysfs store that should return -EBUSY while a sysfs session is enabled.
This series depends on "coresight: Prevent per-thread events from sharing a sink" v4 [1]. That series takes coresight_mutex for perf AUX setup and adds coresight_release_path_locked(), which the etm_setup_aux() and coresight_build_path() fixes here are based on.
[1]: https://lore.kernel.org/r/20261016-james-cs-multiple-per-threads-v4-0-dedf96...
Signed-off-by: James Clark james.clark@linaro.org --- James Clark (9): coresight: cpu-debug: Fix PM usage counter leak in debug_enable_func() coresight: etm4x: Remove perf symlink if config registration fails coresight: etm4x: Fix truncation of nr_ext_inp coresight: etm-perf: Fix sink device reference leak in etm_setup_aux() coresight: syscfg: Take csdev lock when removing owned features coresight: syscfg: Fix deadlock in cscfg_create_device() error path coresight: Fix resource leaks on coresight_build_path() errors coresight: etm3x: Don't ignore etm_parse_event_config() errors coresight: etm3x: Prohibit modifying seq_curr_state while session is enabled
drivers/hwtracing/coresight/coresight-core.c | 6 ++++-- drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 ++-- drivers/hwtracing/coresight/coresight-etm-perf.c | 4 ++++ drivers/hwtracing/coresight/coresight-etm3x-core.c | 6 +++++- drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 5 +++++ drivers/hwtracing/coresight/coresight-etm4x-core.c | 1 + drivers/hwtracing/coresight/coresight-etm4x.h | 2 +- drivers/hwtracing/coresight/coresight-syscfg.c | 8 +++++++- 8 files changed, 29 insertions(+), 7 deletions(-) --- base-commit: 343cfcbb3ecfdb80aa576a428cfa3b65ad783842 change-id: 20261027-james-cs-sashiko-easy-fixes-1-692d80016a89 prerequisite-message-id: 20261016-james-cs-multiple-per-threads-v4-0-dedf961aca0e@linaro.org prerequisite-patch-id: 81acda380ba25acd3845eb58d5ded812175b9631 prerequisite-patch-id: 430caddc9c87948d4e9a0d1967bf3d8a50bca06b prerequisite-patch-id: 633377150141300f7578b265fcc02eba52e592a8 prerequisite-patch-id: 9a82ffe5d705ac1fdf1250ff6bf242cfcd9d8fbf prerequisite-patch-id: cf211801575d6bd0aa7fc0f6e19c3b90cea446a0 prerequisite-patch-id: d22fee48bf4aa3e01536e4683ccd797b3dbe1c91 prerequisite-patch-id: 55eeffb37cae55a1f47c2827899e0512b47a6efa prerequisite-patch-id: c542d74cd4bc76158d5872bab12b8bd7a00f0c27 prerequisite-patch-id: 71cd37ed83d3e01d7a0321cdfa5cfc5ee113fe7b prerequisite-patch-id: 74c1e3ed6dba4e25bfd3c39f06d43b079eed45e1
Best regards, -- James Clark james.clark@linaro.org
pm_runtime_get_sync() increments the usage counter even when it fails, but the failing CPU isn't added to the rollback mask, so its reference is never dropped. Use pm_runtime_resume_and_get() which drops the reference itself on failure.
Fixes: 2227b7c74634 ("coresight: add support for CPU debug module") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-2ff60e6d-33ac-4a69-9c62-63eb482f1913 Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 3a806c1d50ea..06e55dfa6b91 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -429,7 +429,7 @@ static int debug_enable_func(void) if (!drvdata) continue;
- ret = pm_runtime_get_sync(drvdata->dev); + ret = pm_runtime_resume_and_get(drvdata->dev); if (ret < 0) goto err; else @@ -440,7 +440,7 @@ static int debug_enable_func(void)
err: /* - * If pm_runtime_get_sync() has failed, need rollback on + * If pm_runtime_resume_and_get() has failed, need rollback on * all the other CPUs that have been enabled before that. */ for_each_cpu(cpu, &mask) {
On Tue, Oct 27, 2026 at 02:55:47PM +0000, James Clark wrote:
pm_runtime_get_sync() increments the usage counter even when it fails, but the failing CPU isn't added to the rollback mask, so its reference is never dropped. Use pm_runtime_resume_and_get() which drops the reference itself on failure.
Fixes: 2227b7c74634 ("coresight: add support for CPU debug module") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-2ff60e6d-33ac-4a69-9c62-63eb482f1913 Signed-off-by: James Clark james.clark@linaro.org
This duplicates with: https://lore.kernel.org/linux-arm-kernel/20260911-b4-coresight-runtime-pm-fa...
I'd prefer to pick up that patch, as it has fixed all drivers in the CoreSight directory.
Thanks, Leo
On 27/10/2026 18:08, Leo Yan wrote:
On Tue, Oct 27, 2026 at 02:55:47PM +0000, James Clark wrote:
pm_runtime_get_sync() increments the usage counter even when it fails, but the failing CPU isn't added to the rollback mask, so its reference is never dropped. Use pm_runtime_resume_and_get() which drops the reference itself on failure.
Fixes: 2227b7c74634 ("coresight: add support for CPU debug module") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-2ff60e6d-33ac-4a69-9c62-63eb482f1913 Signed-off-by: James Clark james.clark@linaro.org
This duplicates with: https://lore.kernel.org/linux-arm-kernel/20260911-b4-coresight-runtime-pm-fa...
I'd prefer to pick up that patch, as it has fixed all drivers in the CoreSight directory.
Thanks, Leo
Yep we should drop this one
If etm4_cscfg_register() fails, the perf symlink created just before it is left behind in the etm_pmu device's directory. Remove it in the same way as etm4_remove_dev() does.
Fixes: 810ac401db1f ("coresight: etm4x: Add complex configuration handlers to etmv4") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-5a385158-37fb-48f1-a8c7-28e86e07848a Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm4x-core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index e21be6468e95..ba21fe12870b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -2258,6 +2258,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) /* register with config infrastructure & load any current features */ ret = etm4_cscfg_register(drvdata->csdev); if (ret) { + etm_perf_symlink(drvdata->csdev, false); coresight_unregister(drvdata->csdev); return ret; }
TRCIDR5.NUMEXTIN is a 9 bit field but it's stored in a u8, so values of 256 or more are truncated. Make nr_ext_inp a u16.
Fixes: 2e1cdfe184b5 ("coresight-etm4x: Adding CoreSight ETM4x driver") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-b3468d48-ff08-49c9-9ed8-fb6af6979e1e Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm4x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 5417280cdb27..8628dd4e15db 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -874,7 +874,7 @@ struct etmv4_caps { u8 nr_pe_cmp; u8 nr_addr_cmp; u8 nr_cntr; - u8 nr_ext_inp; + u16 nr_ext_inp; u8 numcidc; u8 numextinsel; u8 numvmidc;
coresight_get_sink_by_id() returns the sink with a reference taken by bus_find_device(), but etm_setup_aux() never drops it. The paths built for each CPU take their own references on the sink, so drop the lookup reference before returning on both the success and error paths.
Fixes: 226443925887 ("coresight: Use event attributes for sink selection") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-89fe1ee7-7e2f-4c78-a8e6-93a1a260015b Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm-perf.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 5261061e4dd4..6946058b5401 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -519,10 +519,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, if (!event_data->snk_config) goto err;
+ if (user_sink) + put_device(&user_sink->dev); mutex_unlock(&coresight_mutex); return event_data;
err: + if (user_sink) + put_device(&user_sink->dev); mutex_unlock(&coresight_mutex); etm_free_aux(event_data); return NULL;
cscfg_remove_owned_csdev_features() modifies csdev->feature_csdev_list without holding csdev->cscfg_csdev_lock, but other users of the list like cscfg_csdev_reset_feats() take it. Take the lock in the same way as cscfg_remove_owned_csdev_configs() already does for the config list.
Fixes: 02bd588e12df ("coresight: configuration: Update API to permit dynamic load/unload") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-6bcce2f2-5aba-40a4-8946-4d843ec84683 Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-syscfg.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 7e3c9844bc00..f93150a1bee4 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -415,6 +415,8 @@ static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, vo if (list_empty(&csdev->feature_csdev_list)) return;
+ guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock); + list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) { if (feat_csdev->feat_desc->load_owner == load_owner) list_del(&feat_csdev->node);
If device_register() fails, put_device() is called with cscfg_mutex held. This calls cscfg_dev_release() which takes cscfg_mutex again and deadlocks. Drop the mutex before calling put_device().
Fixes: 199380decc5f ("coresight: configfs: Fix unload of configurations on module exit") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-e07a8e2f-c34e-4609-a667-9f294c6fcf29 Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-syscfg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index f93150a1bee4..92aef8b9c734 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -1217,8 +1217,12 @@ static int cscfg_create_device(void) dev->init_name = "cs_system_cfg";
err = device_register(dev); - if (err) + if (err) { + /* cscfg_dev_release() takes cscfg_mutex */ + mutex_unlock(&cscfg_mutex); put_device(dev); + return err; + }
create_dev_exit_unlock: mutex_unlock(&cscfg_mutex);
If allocating the path node fails in _coresight_build_path(), the references taken by coresight_grab_device() just before are leaked. Drop them before returning.
Also, when _coresight_build_path() fails, nodes for devices further along the path may have already been added and grabbed, but coresight_build_path() only frees the path itself. Use coresight_release_path_locked() to drop and free any nodes too.
Fixes: b3e94405941e ("coresight: associating path with session rather than tracer") Fixes: 32b0707a4182 ("coresight: Add try_get_module() in coresight_grab_device()") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-fe264804-52b6-4b0d-a43e-184e228df19b Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index fe64c509bf67..1d9c7ced39d2 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1103,8 +1103,10 @@ static int _coresight_build_path(struct coresight_device *csdev, return ret;
node = kzalloc_obj(struct coresight_node); - if (!node) + if (!node) { + coresight_drop_device(csdev); return -ENOMEM; + }
node->csdev = csdev; list_add(&node->link, &path->path_list); @@ -1131,7 +1133,7 @@ struct coresight_path *coresight_build_path(struct coresight_device *source,
rc = _coresight_build_path(source, source, sink, path); if (rc) { - kfree(path); + coresight_release_path_locked(path); return ERR_PTR(rc); }
etm_parse_event_config() can fail, for example if an invalid timestamp level is requested, but etm_enable_perf() ignores the error and enables the tracer anyway. Roll back to disabled mode and return the error instead, like etm4_enable_perf() does.
Fixes: 882d5e112491 ("coresight: etm3x: implementing perf_enable/disable() API") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-bc35b336-f835-40fa-89d9-7a580efc3b53 Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm3x-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index b670a324bb41..db8413522d72 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -487,7 +487,11 @@ static int etm_enable_perf(struct coresight_device *csdev, return -EBUSY;
/* Configure the tracer based on the session's specifics */ - etm_parse_event_config(drvdata, event); + ret = etm_parse_event_config(drvdata, event); + if (ret) { + coresight_set_mode(csdev, CS_MODE_DISABLED); + return ret; + } drvdata->traceid = path->trace_id;
/* And enable it */
When a sysfs session is disabled, seq_curr_state is read back from the hardware into sysfs_config, overwriting any value written while the session was enabled. Return -EBUSY in that case.
Do the mode check and the write under drvdata->spinlock. etm_enable_sysfs() takes the mode before copying sysfs_config to curr_config under the same lock, so either the new value is included in the copy, or the store sees that the session is enabled. etm_disable_sysfs() does the read back before releasing the mode, so a store can't succeed until it's done.
Fixes: a939fc5a71ad ("coresight-etm: add CoreSight ETM/PTM driver") Reported-by: Sashiko sashiko-bot@kernel.org Closes: https://sashiko.dev/#/bug/linux-d70beb3d-d997-429d-9828-d396e1bbfbb5 Signed-off-by: James Clark james.clark@linaro.org --- drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index d185fb8270e1..08c10fd146d5 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -1014,6 +1014,11 @@ static ssize_t seq_curr_state_store(struct device *dev, if (val > ETM_SEQ_STATE_MAX_VAL) return -EINVAL;
+ guard(spinlock)(&drvdata->spinlock); + if (IS_ERR_OR_NULL(drvdata->csdev) || + coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) + return -EBUSY; + sysfs_config->seq_curr_state = val;
return size;