On Thu, Oct 19, 2017 at 06:15:53PM +0100, Suzuki K Poulose wrote:
Add necessary support for using ETR as a sink in ETM perf tracing.
We try make the best use of the available modes of buffers to
try and avoid software double buffering.
We can use the perf ring buffer for ETR directly if all of the
conditions below are met :
1) ETR is DMA coherent
2) perf is used in snapshot mode. In full tracing mode, we cannot
guarantee that the ETR will stop before it overwrites the data
which may not have been consumed by the user.
3) ETR supports save-restore with a scatter-gather mechanism
which can use a given set of pages we use the perf ring buffer
directly. If we have an in-built TMC ETR Scatter Gather unit,
we make use of a circular SG list to restart from a given head.
However, we need to align the starting offset to 4K in this case.
If the ETR doesn't support either of this, we fallback to software
double buffering.
Cc: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
+/*
+ * etr_perf_buffer - Perf buffer used for ETR
+ * @etr_buf - Actual buffer used by the ETR
+ * @snaphost - Perf session mode
+ * @head - handle->head at the beginning of the session.
+ * @nr_pages - Number of pages in the ring buffer.
+ * @pages - Pages in the ring buffer.
+ * @flags - Capabilities of the hardware buffer used in the
+ * session. If flags == 0, we use software double
+ * buffering.
+ */
+struct etr_perf_buffer {
+ struct etr_buf *etr_buf;
+ bool snapshot;
+ unsigned long head;
+ int nr_pages;
+ void **pages;
+ u32 flags;
+};
Please move this to the top, just below the declaration for etr_sg_table.
+
+/*
+ * XXX: What is the expected behavior here in the following cases ?
+ * 1) Full trace mode, without double buffering : What should be the size
+ * reported back when the buffer is full and has wrapped around. Ideally,
+ * we should report for the lost trace to make sure the "head" in the ring
+ * buffer comes back to the position as in the trace buffer, rather than
+ * returning "total size" of the buffer.
+ * 2) In snapshot mode, should we always return "full buffer size" ?
+ */
+static unsigned long
+tmc_etr_update_perf_buffer(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *config)
+{
+ bool double_buffer, lost = false;
+ unsigned long flags, offset, size = 0;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ struct etr_perf_buffer *etr_perf = config;
+ struct etr_buf *etr_buf = etr_perf->etr_buf;
+
+ double_buffer = (etr_perf->flags == 0);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (WARN_ON(drvdata->perf_data != etr_perf)) {
+ lost = true;
If we are here something went seriously wrong - I don't think much more can be
done other than a WARN_ON()...
...static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
{
+
+ etr_perf = drvdata->perf_data;
+ if (!etr_perf || !etr_perf->etr_buf) {
+ rc = -EINVAL;
This is a serious malfunction - I would WARN_ON() before unlocking.
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 2c5b905b6494..06386ceb7866 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -198,6 +198,7 @@ struct etr_buf {
* @trigger_cntr: amount of words to store after a trigger.
* @etr_caps: Bitmask of capabilities of the TMC ETR, inferred from the
* device configuration register (DEVID)
+ * @perf_data: PERF buffer for ETR.
* @sysfs_data: SYSFS buffer for ETR.
*/
struct tmc_drvdata {
@@ -219,6 +220,7 @@ struct tmc_drvdata {
u32 trigger_cntr;
u32 etr_caps;
struct etr_buf *sysfs_buf;
+ void *perf_data;
This is a temporary place holder while an event is active, i.e theoretically it
doesn't stay the same for the entire trace session. In situations where there
could be one ETR per CPU, the same ETR could be used to serve more than one
trace session (since only one session can be active at a time on a CPU). As
such I would call it curr_perf_data or something similar. I'd also make that
clear in the above documentation.
Have you tried your implementation on a dragonboard or a Hikey?
Thanks,
Mathieu
};
struct etr_buf_operations {
--
2.13.6