[PATCH 06/25] coresight: perf: Simplify flow for CPUs without a path
From: Leo Yan
Date: Tue Sep 15 2026 - 12:12:14 EST
etm_setup_aux() removes a CPU from the event mask when it cannot build a
path from that CPU's ETM to the selected sink. The start nevertheless
allocates buffer handle and keeps event data active until the
corresponding stop callback.
End the newly acquired handle immediately when the current CPU is not in
the mask, and do not publish event data in the per-CPU context. The
event remains logically active so that a task event can trace after
migrating to an eligible CPU. A stop on the unsupported CPU then has no
CoreSight modules to disable or trace data to synchronize. Mark its
hardware state stopped and up to date.
Assisted-by: Codex:gpt-6
Signed-off-by: Leo Yan <leo.yan@xxxxxxx>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 38 +++++++++++-------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 13d865ca86f1161b2e21174f096473c4829afc8c..afd22fd4a851e600ab69fd5b6883e6f8518b2cab 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -572,13 +572,15 @@ static void etm_event_start(struct perf_event *event, int flags)
* the sink was specified or hinted to the driver. For
* now, simply don't record anything on this ETM.
*
- * As such we pretend that everything is fine, and let
- * it continue without actually tracing. The event could
- * continue tracing when it moves to a CPU where it is
- * reachable to a sink.
+ * In that case, leave the event logically active but stop AUX
+ * output on this CPU. The event could continue tracing when
+ * it moves to a CPU where it is reachable to a sink.
*/
- if (!cpumask_test_cpu(cpu, &event_data->mask))
- goto out;
+ if (!cpumask_test_cpu(cpu, &event_data->mask)) {
+ perf_aux_output_end(handle, 0);
+ event->hw.state = 0;
+ return;
+ }
path = etm_event_cpu_path(event_data, cpu);
path->handle = handle;
@@ -613,7 +615,6 @@ static void etm_event_start(struct perf_event *event, int flags)
perf_report_aux_output_id(event, hw_id);
}
-out:
/* Tell the perf core the event is alive */
event->hw.state = 0;
/* Save the event_data for this ETM */
@@ -709,7 +710,6 @@ static void etm_event_pause(struct coresight_path *path,
static void etm_event_stop(struct perf_event *event, int mode)
{
- int cpu = smp_processor_id();
struct coresight_device *source, *sink;
struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
struct perf_output_handle *handle = &ctxt->handle;
@@ -719,6 +719,15 @@ static void etm_event_stop(struct perf_event *event, int mode)
if (mode & PERF_EF_PAUSE)
return etm_event_pause(path, event, ctxt);
+ /*
+ * With no path enabled, there is no hardware to stop or trace data
+ * to synchronize. Mark the event stopped and up to date.
+ */
+ if (!path) {
+ event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ return;
+ }
+
/*
* If we still have access to the event_data via handle,
* confirm that we haven't messed up the tracking.
@@ -738,19 +747,6 @@ static void etm_event_stop(struct perf_event *event, int mode)
if (WARN_ON(!event_data))
return;
- /*
- * Check if this ETM was allowed to trace, as decided at
- * etm_setup_aux(). If it wasn't allowed to trace, then
- * nothing needs to be torn down other than outputting a
- * zero sized record.
- */
- if (handle->event && (mode & PERF_EF_UPDATE) &&
- !cpumask_test_cpu(cpu, &event_data->mask)) {
- event->hw.state = PERF_HES_STOPPED;
- perf_aux_output_end(handle, 0);
- return;
- }
-
source = coresight_get_source(path);
sink = coresight_get_sink(path);
if (!source || !sink)
--
2.34.1