When a fill-mode wrap stops TRBE, the trace source can continue running until software handles the stop. Trace generated during this interval may be lost.
The overflow path now stops and restarts the trace source around buffer reprogramming. This emits ASYNC packets so the decoder can synchronize with the next trace segment. Use PERF_AUX_FLAG_PARTIAL to report the possible gap instead of PERF_AUX_FLAG_COLLISION.
Set PARTIAL in both the overflow handler and the buffer update callback. This also preserves the gap indication when event shutdown handles a pending wrap, even if no further trace segment follows. Limit the flag to stopped buffers.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-trbe.c | 29 +++++++--------------------- 1 file changed, 7 insertions(+), 22 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 6bc82d5b55539795059da37039d2929b4ea504e3..29a1882b1f3c2eb7166f71eeef37badece67039c 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -285,25 +285,6 @@ static void trbe_reset_local(struct trbe_cpudata *cpudata) write_sysreg_s(0, SYS_TRBSR_EL1); }
-static void trbe_report_wrap_event(struct perf_output_handle *handle) -{ - /* - * Mark the buffer to indicate that there was a WRAP event by - * setting the COLLISION flag. This indicates to the user that - * the TRBE trace collection was stopped without stopping the - * ETE and thus there might be some amount of trace that was - * lost between the time the WRAP was detected and the IRQ - * was consumed by the CPU. - * - * Setting the TRUNCATED flag would move the event to STOPPED - * state unnecessarily, even when there is space left in the - * ring buffer. Using the COLLISION flag doesn't have this side - * effect. We only set TRUNCATED flag when there is no space - * left in the ring buffer. - */ - perf_aux_output_flag(handle, PERF_AUX_FLAG_COLLISION); -} - static void trbe_truncate_event(struct perf_output_handle *handle) { perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); @@ -917,10 +898,12 @@ static unsigned long arm_trbe_update_buffer(struct coresight_device *csdev, perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); size = 0; goto done; - } else if (act == TRBE_FAULT_ACT_WRAP) { - trbe_report_wrap_event(handle); }
+ /* Trace may have been lost before the source was stopped. */ + if (act == TRBE_FAULT_ACT_WRAP && !is_trbe_running(status)) + perf_aux_output_flag(handle, PERF_AUX_FLAG_PARTIAL); + size = trbe_get_trace_size(handle, buf, act == TRBE_FAULT_ACT_WRAP);
done: @@ -1246,7 +1229,9 @@ static int trbe_handle_overflow(struct trbe_cpudata *cpudata, if (buf->snapshot) handle->head += size;
- trbe_report_wrap_event(handle); + if (is_buffer_stopped) + perf_aux_output_flag(handle, PERF_AUX_FLAG_PARTIAL); + perf_aux_output_end(handle, size); event_data = perf_aux_output_begin(handle, event); /*