arm_trbe_update_buffer() must account trace when perf stops a session, even if no maintenance interrupt has been handled. Prepare it for trigger and wrap modes by making the trace-size decision from the drained TRBSR status rather than gating classification on IRQ. Acknowledge IRQ only when it is set.
In FILL mode, reaching LIMIT sets WRAP and IRQ and returns TRBPTR to BASE. Interrupt delivery can be delayed, so update_buffer() may run before the IRQ handler. The existing IRQ-gated path uses WRAP to size through LIMIT in that case; preserve this while also classifying updates without a pending IRQ.
With classification on the no-IRQ path, a normal software stop can have TRBSR.S clear and an ignored detected trigger can set TRBSR.TRG. Neither should warn or discard valid trace. Mark fatal status as truncated and return zero. Use LIMIT for a filled WRAP and TRBPTR otherwise.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-trbe.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index ac49098aa08412a23a20d32f84c2e1977ee4a223..661f4a78e67c30652de8c834e4773819fa67b5ac 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -662,8 +662,6 @@ static enum trbe_fault_action trbe_get_fault_act(struct perf_output_handle *hand int ec = get_trbe_ec(trbsr); int bsc = get_trbe_bsc(trbsr);
- WARN_ON(is_trbe_running(trbsr)); - if (is_trbe_abort(trbsr)) { err_str = "External abort"; goto out_fatal; @@ -844,7 +842,6 @@ static unsigned long arm_trbe_update_buffer(struct coresight_device *csdev, enum trbe_fault_action act; unsigned long size, status; unsigned long flags; - bool wrap = false;
WARN_ON(buf->cpudata != cpudata); WARN_ON(cpudata->cpu != smp_processor_id()); @@ -896,23 +893,20 @@ static unsigned long arm_trbe_update_buffer(struct coresight_device *csdev, */ clr_trbe_irq(); isb(); + }
- act = trbe_get_fault_act(handle, status); - /* - * If this was not due to a WRAP event, we have some - * errors and as such buffer is empty. - */ - if (act != TRBE_FAULT_ACT_WRAP) { - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); - size = 0; - goto done; - } + act = trbe_get_fault_act(handle, status);
+ /* If an error occurred, the buffer may be empty */ + if (act == TRBE_FAULT_ACT_FATAL) { + 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); - wrap = true; }
- size = trbe_get_trace_size(handle, buf, wrap); + size = trbe_get_trace_size(handle, buf, act == TRBE_FAULT_ACT_WRAP);
done: local_irq_restore(flags);