mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: James Clark <james.clark@linaro.org>
To: Suzuki K Poulose <suzuki.poulose@arm.com>,
	 Mike Leach <mike.leach@arm.com>, Leo Yan <leo.yan@arm.com>,
	 Suyash Mahar <smahar@meta.com>,
	Yeoreum Yun <yeoreum.yun@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	 Qi Liu <liuqi115@huawei.com>, Junhao He <hejunhao3@huawei.com>,
	 coresight@lists.linaro.org,
	linux-arm-kernel@lists.infradead.org,
	 linux-kernel@vger.kernel.org,
	James Clark <james.clark@linaro.org>,
	 Jonathan Cameron <jic23@kernel.org>
Subject: [PATCH v4 04/10] coresight: etm-perf: Reject event if building path fails
Date: Fri, 16 Oct 2026 11:46:14 +0100	[thread overview]
Message-ID: <20261016-james-cs-multiple-per-threads-v4-4-dedf961aca0e@linaro.org> (raw)
In-Reply-To: <20261016-james-cs-multiple-per-threads-v4-0-dedf961aca0e@linaro.org>

etm_event_build_path() silently skips error cases to support opening
cpu=-1 events on all CPUs when a system might not have reachable sinks
or ETMs for every CPU. In the next commit we want to reject the event
if invalid sharing on any sink is detected, so propagate errors.

This means that things like failed memory allocations when building the
path and invalid aux pause options now reject the event which is
probably an improvement.

Keep the silent skips for things that make sense like missing ETMs and
sinks.

Previously, _coresight_build_path() used -ENODEV both when no route to
the sink existed and when coresight_grab_device() could not acquire a
device or helper on a found route. Return -ENOENT exclusively for the
unreachable case, and retain -ENODEV for device acquisition failures,
such as a missing driver or failure to take a module reference.

Signed-off-by: James Clark <james.clark@linaro.org>
---
 drivers/hwtracing/coresight/coresight-core.c     | 22 ++++++---
 drivers/hwtracing/coresight/coresight-etm-perf.c | 61 +++++++++++++-----------
 2 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index c05d657cde73..a635c51c25ac 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -980,6 +980,9 @@ int coresight_path_assign_trace_id(struct coresight_path *path,
  * From there the sink is added to the list along with all the devices that led
  * to that point - the end result is a list from source to sink. In that list
  * the source is the first device and the sink the last one.
+ *
+ * Return: 0 on success, -ENOENT if the sink is unreachable, or another error
+ * if path construction fails.
  */
 static int _coresight_build_path(struct coresight_device *csdev,
 				 struct coresight_device *source,
@@ -996,10 +999,10 @@ static int _coresight_build_path(struct coresight_device *csdev,
 
 	if (coresight_is_percpu_source(csdev) && coresight_is_percpu_sink(sink) &&
 	    sink == per_cpu(csdev_sink, csdev->cpu)) {
-		if (_coresight_build_path(sink, source, sink, path) == 0) {
-			found = true;
-			goto out;
-		}
+		ret = _coresight_build_path(sink, source, sink, path);
+		if (ret)
+			return ret;
+		goto out;
 	}
 
 	/* Not a sink - recursively explore each port found on this element */
@@ -1011,15 +1014,20 @@ static int _coresight_build_path(struct coresight_device *csdev,
 		if (coresight_blocks_source(source, csdev->pdata->out_conns[i]))
 			continue;
 
-		if (child_dev &&
-		    _coresight_build_path(child_dev, source, sink, path) == 0) {
+		if (!child_dev)
+			continue;
+
+		ret = _coresight_build_path(child_dev, source, sink, path);
+		if (!ret) {
 			found = true;
 			break;
 		}
+		if (ret != -ENOENT)
+			return ret;
 	}
 
 	if (!found)
-		return -ENODEV;
+		return -ENOENT;
 
 out:
 	/*
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index faec4c7bb83d..a9adf1cca7a8 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -334,32 +334,30 @@ static struct coresight_path *etm_event_get_ctxt_path(struct etm_ctxt *ctxt)
 	return path;
 }
 
-static struct coresight_path *
-etm_event_build_path(struct perf_event *event, int cpu,
-		     struct coresight_device *user_sink,
-		     struct coresight_device *match_sink)
+static int etm_event_build_path(struct perf_event *event, int cpu,
+				struct coresight_device *user_sink,
+				struct coresight_device *match_sink,
+				struct coresight_path **path)
 {
-	struct coresight_path *path = NULL;
 	struct coresight_device *source, *sink;
-	int ret;
+	int ret = 0;
 
+	*path = NULL;
 	source = coresight_get_percpu_source_ref(cpu);
 
-	/*
-	 * If there is no ETM associated with this CPU or ever we try to trace
-	 * on this CPU, we handle it accordingly.
-	 */
+	/* Silently skip CPUs without a loaded ETM. */
 	if (!source)
-		return NULL;
+		return 0;
 
 	/*
 	 * If AUX pause feature is enabled but the ETM driver does not
-	 * support the operations, skip for this source.
+	 * support the operations, reject the whole event.
 	 */
 	if (event->attr.aux_start_paused &&
 	    (!source_ops(source)->pause_perf ||
 	     !source_ops(source)->resume_perf)) {
 		dev_err_once(&source->dev, "AUX pause is not supported.\n");
+		ret = -EINVAL;
 		goto out;
 	}
 
@@ -380,30 +378,34 @@ etm_event_build_path(struct perf_event *event, int cpu,
 		 * trace on a CPU if the sink is not compatible.
 		 */
 
-		/* Find the default sink for this ETM */
+		/* Silently skip ETMs with no reachable sink loaded */
 		sink = coresight_find_default_sink(source);
 		if (!sink)
 			goto out;
 
-		/* Check if this sink compatible with the last sink */
+		/* Silently skip sinks incompatible with the last sink. */
 		if (match_sink && !sinks_compatible(match_sink, sink))
 			goto out;
 	}
 
 	/*
-	 * Building a path doesn't enable it, it simply builds a
-	 * list of devices from source to sink that can be
-	 * referenced later when the path is actually needed.
+	 * Build path, but don't enable. Skip CPUs that cannot reach the sink.
+	 * Reject the whole event on other path construction errors.
 	 */
-	path = coresight_build_path(source, sink);
-	if (IS_ERR(path))
+	*path = coresight_build_path(source, sink);
+	if (IS_ERR(*path)) {
+		ret = PTR_ERR(*path);
+		if (ret == -ENOENT)
+			ret = 0;
+		*path = NULL;
 		goto out;
+	}
 
-	/* ensure we can allocate a trace ID for this CPU */
-	ret = coresight_path_assign_trace_id(path, CS_MODE_PERF);
+	/* Reject whole event if we can't allocate a trace ID for this CPU */
+	ret = coresight_path_assign_trace_id(*path, CS_MODE_PERF);
 	if (ret) {
-		coresight_release_path_locked(path);
-		path = NULL;
+		coresight_release_path_locked(*path);
+		*path = NULL;
 		goto out;
 	}
 
@@ -411,7 +413,7 @@ etm_event_build_path(struct perf_event *event, int cpu,
 
 out:
 	coresight_put_percpu_source_ref(source);
-	return IS_ERR_OR_NULL(path) ? NULL : path;
+	return ret;
 }
 
 static void *etm_setup_aux(struct perf_event *event, void **pages,
@@ -448,15 +450,16 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
 
 	/*
 	 * Setup the path for each CPU in a trace session. We try to build
-	 * trace path for each CPU in the mask. If we don't find an ETM
-	 * for the CPU or fail to build a path, we clear the CPU from the
-	 * mask and continue with the rest. If ever we try to trace on those
-	 * CPUs, we can handle it and fail the session.
+	 * trace path for each CPU in the mask. Skip CPUs without an ETM, without
+	 * a compatible default sink, or unable to reach the selected sink by
+	 * clearing them from the mask. Other errors reject the whole event.
 	 */
 	for_each_cpu(cpu, mask) {
 		struct coresight_path *path;
 
-		path = etm_event_build_path(event, cpu, user_sink, sink);
+		if (etm_event_build_path(event, cpu, user_sink, sink, &path))
+			goto err;
+
 		if (!path) {
 			/*
 			 * Failed to create a path for the CPU, clear it from

-- 
2.43.0


  parent reply	other threads:[~2026-10-16 10:46 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-16 10:46 [PATCH v4 00/10] coresight: Prevent per-thread events from sharing a sink James Clark
2026-10-16 10:46 ` [PATCH v4 01/10] coresight: configfs: Don't assume active until cscfg_mgr is set James Clark
2026-10-16 10:46 ` [PATCH v4 02/10] coresight: etm-perf: Remove workqueue for freeing AUX data James Clark
2026-10-16 10:46 ` [PATCH v4 03/10] coresight: etm-perf: Serialize AUX topology access James Clark
2026-10-16 10:46 ` James Clark [this message]
2026-10-16 10:46 ` [PATCH v4 05/10] coresight: etm-perf: Prevent sink sharing at setup time James Clark
2026-10-16 10:46 ` [PATCH v4 06/10] coresight: tmc-etr: Reflect new sharing rules in allocator James Clark
2026-10-16 10:46 ` [PATCH v4 07/10] coresight: tmc-etr: Remove sharing guards from ETR James Clark
2026-10-16 10:46 ` [PATCH v4 08/10] coresight: tmc-etf: Remove sharing guards from ETF James Clark
2026-10-16 10:46 ` [PATCH v4 09/10] coresight: etb10: Remove sharing guards from ETB10 James Clark
2026-10-16 10:46 ` [PATCH v4 10/10] coresight: ultrasoc-smb: Remove sharing guards from SMB James Clark

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261016-james-cs-multiple-per-threads-v4-4-dedf961aca0e@linaro.org \
    --to=james.clark@linaro.org \
    --cc=coresight@lists.linaro.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=hejunhao3@huawei.com \
    --cc=jic23@kernel.org \
    --cc=leo.yan@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuqi115@huawei.com \
    --cc=mike.leach@arm.com \
    --cc=smahar@meta.com \
    --cc=suzuki.poulose@arm.com \
    --cc=yeoreum.yun@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®