gtrace_path_copyto_auxbuf() walked the path and copied from the first component implementing copyto_auxbuf(). For a linksink like ETF used as a link, this picked the wrong component. Call the sink's callback directly via gtrace_path_sink() and pass the perf handle so the sink can set AUX flags itself.
Signed-off-by: Zane Leung liangzhen@linux.spacemit.com --- drivers/hwtracing/gtrace/gtrace-core.c | 39 ++++++++++------------ drivers/hwtracing/gtrace/gtrace-perf.c | 13 ++------ drivers/hwtracing/gtrace/rvtrace-ramsink.c | 10 ++++-- include/linux/gtrace.h | 10 +++--- 4 files changed, 34 insertions(+), 38 deletions(-)
diff --git a/drivers/hwtracing/gtrace/gtrace-core.c b/drivers/hwtracing/gtrace/gtrace-core.c index 231d06218d8e..a42b1844da29 100644 --- a/drivers/hwtracing/gtrace/gtrace-core.c +++ b/drivers/hwtracing/gtrace/gtrace-core.c @@ -806,14 +806,14 @@ int gtrace_path_stop(struct gtrace_path *path) EXPORT_SYMBOL_GPL(gtrace_path_stop);
int gtrace_path_copyto_auxbuf(struct gtrace_path *path, + struct perf_output_handle *handle, struct gtrace_perf_auxbuf *buf, - size_t *bytes_copied, u64 *format) + size_t *bytes_copied) { - struct gtrace_comp_priv *sink = to_gtrace_comp_priv(gtrace_path_sink(path)); - const struct gtrace_driver *gtdrv; - struct gtrace_component *comp; - struct gtrace_path_node *node; - int ret = -EOPNOTSUPP; + struct gtrace_component *sink = gtrace_path_sink(path); + struct gtrace_comp_priv *spriv = to_gtrace_comp_priv(sink); + const struct gtrace_driver *sinkdrv = to_gtrace_driver(sink->dev.driver); + int ret = 0; unsigned long flags;
/* @@ -823,25 +823,20 @@ int gtrace_path_copyto_auxbuf(struct gtrace_path *path, * sink's lock also stops another path from starting the sink before copy * completes. */ - raw_spin_lock_irqsave(&sink->lock, flags); - if (sink->start_count) { - *bytes_copied = 0; - ret = 0; - goto out; - } - - list_for_each_entry(node, &path->comp_list, head) { - comp = node->comp; - gtdrv = to_gtrace_driver(comp->dev.driver); - if (!gtdrv || !gtdrv->copyto_auxbuf) - continue; + raw_spin_lock_irqsave(&spriv->lock, flags); + if (!spriv->start_count) { + if (!sinkdrv) { + ret = -ENODEV; + goto out; + }
- *bytes_copied = gtdrv->copyto_auxbuf(comp, buf, format); - ret = 0; - break; + if (sinkdrv->copyto_auxbuf) { + *bytes_copied = sinkdrv->copyto_auxbuf(sink, handle, buf); + ret = 0; + } } out: - raw_spin_unlock_irqrestore(&sink->lock, flags); + raw_spin_unlock_irqrestore(&spriv->lock, flags); return ret; } EXPORT_SYMBOL_GPL(gtrace_path_copyto_auxbuf); diff --git a/drivers/hwtracing/gtrace/gtrace-perf.c b/drivers/hwtracing/gtrace/gtrace-perf.c index 604b673a29d5..3c8b620df5a8 100644 --- a/drivers/hwtracing/gtrace/gtrace-perf.c +++ b/drivers/hwtracing/gtrace/gtrace-perf.c @@ -243,7 +243,6 @@ static void gtrace_event_stop(struct perf_event *event, int mode) { struct gtrace_ctxt *ctxt = this_cpu_ptr(>race_ctxt); struct perf_output_handle *handle = &ctxt->handle; - u64 format = PERF_AUX_FLAG_GTRACE_FORMAT_UNKNOWN; struct gtrace_event_data *event_data; int ret, cpu = smp_processor_id(); struct gtrace_path *path; @@ -280,17 +279,11 @@ static void gtrace_event_stop(struct perf_event *event, int mode) if (handle->event && (mode & PERF_EF_UPDATE)) { if (WARN_ON_ONCE(handle->event != event)) return; - ret = gtrace_path_copyto_auxbuf(path, &event_data->buf, &size, &format); + ret = gtrace_path_copyto_auxbuf(path, handle, &event_data->buf, &size); WARN_ON_ONCE(ret); - if (READ_ONCE(handle->event)) { - /* Tag the AUX data with the source's trace format. */ - perf_aux_output_flag(handle, format); - if (size > handle->size) { - size = handle->size; - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); - } + if (READ_ONCE(handle->event)) perf_aux_output_end(handle, size); - } else + else WARN_ON(size); }
diff --git a/drivers/hwtracing/gtrace/rvtrace-ramsink.c b/drivers/hwtracing/gtrace/rvtrace-ramsink.c index 9588c32c5b13..e0826d3f0d60 100644 --- a/drivers/hwtracing/gtrace/rvtrace-ramsink.c +++ b/drivers/hwtracing/gtrace/rvtrace-ramsink.c @@ -11,6 +11,7 @@ #include <linux/minmax.h> #include <linux/types.h> #include <linux/sizes.h> +#include <linux/perf_event.h> #include <uapi/linux/perf_event.h> #include "rvtrace.h"
@@ -147,8 +148,8 @@ static void tbuf_to_pbuf_copy(struct trace_buf *src, struct trace_buf *dst, size }
static size_t rvtrace_ramsink_copyto_auxbuf(struct gtrace_component *comp, - struct gtrace_perf_auxbuf *buf, - u64 *format) + struct perf_output_handle *handle, + struct gtrace_perf_auxbuf *buf) { struct rvtrace_ramsink_priv *priv = dev_get_drvdata(&comp->dev); struct trace_buf src, dst; @@ -181,6 +182,11 @@ static size_t rvtrace_ramsink_copyto_auxbuf(struct gtrace_component *comp, priv->prev_wp = wp; }
+ if (bytes > handle->size) { + bytes = handle->size; + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + } + tbuf_to_pbuf_copy(&src, &dst, bytes); dev_dbg(&comp->dev, "Copied %zu bytes\n", bytes); return bytes; diff --git a/include/linux/gtrace.h b/include/linux/gtrace.h index e9210b0a73b5..39ae13701615 100644 --- a/include/linux/gtrace.h +++ b/include/linux/gtrace.h @@ -13,6 +13,7 @@ #include <linux/platform_device.h> #include <linux/property.h> #include <linux/types.h> +#include <linux/perf_event.h>
#define GTRACE_PMU_ATTR_CFG_CONTEXT_SHIFT 1 #define GTRACE_PMU_ATTR_CFG_SYNCMODE_MASK GENMASK(3, 2) @@ -363,15 +364,16 @@ struct gtrace_perf_auxbuf { };
int gtrace_path_copyto_auxbuf(struct gtrace_path *path, + struct perf_output_handle *handle, struct gtrace_perf_auxbuf *buf, - size_t *bytes_copied, u64 *format); + size_t *bytes_copied);
/** * struct gtrace_driver - Representation of a trace driver. * @id_table: Table to match components handled by the driver. * @copyto_auxbuf: Callback to copy data into perf AUX buffer. The driver * reports the PMU specific trace format of the copied data - * via @format (see PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK). + * via @handle (see PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK). * @start: Callback to start tracing. * @stop: Callback to stop tracing. * @start_port: Callback to start a specific component port. @@ -385,8 +387,8 @@ int gtrace_path_copyto_auxbuf(struct gtrace_path *path, struct gtrace_driver { const struct gtrace_component_id *id_table; size_t (*copyto_auxbuf)(struct gtrace_component *comp, - struct gtrace_perf_auxbuf *buf, - u64 *format); + struct perf_output_handle *handle, + struct gtrace_perf_auxbuf *buf); int (*start)(struct gtrace_component *comp); int (*stop)(struct gtrace_component *comp); int (*start_port)(struct gtrace_component *comp,