From: NoNine <chenmin83@gmail.com>
To: suzuki.poulose@arm.com
Cc: mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Min Chen <min.chen@siengine.com>
Subject: [PATCH 1/1] coresight: tmc-etr: Sync the trace buffer for the device
Date: Tue, 15 Sep 2026 21:05:03 +0800 [thread overview]
Message-ID: <20260915130503.645953-2-min.chen@siengine.com> (raw)
In-Reply-To: <20260915130503.645953-1-min.chen@siengine.com>
From: Min Chen <min.chen@siengine.com>
The flat ETR buffer comes from dma_alloc_noncoherent(), which zeroes it
with CPU stores. The DMA API requires the caller to sync the buffer for
the device before the device writes into it, but the TMC driver only
ever syncs for the CPU afterwards. On a non-coherent sink the zero fill
is therefore still dirty in cache when the ETR starts writing, and its
write-back lands on top of the trace data.
Add a sync_for_device() buffer operation and call it from
__tmc_etr_enable_hw() just before the TMC is enabled. Only the flat
buffer implements it. The ETR_SG and CATU data pages are synced by
dma_map_page() when they are allocated; their remaining corner case, a
barrier packet followed by a live-drain re-arm, is left for a separate
change.
Tested on an AD1000 EVB: five first windows on freshly allocated
buffers, including the first capture of a boot, all without the
previous all-zero-formatter-frame runs.
Signed-off-by: Min Chen <min.chen@siengine.com>
---
.../hwtracing/coresight/coresight-tmc-etr.c | 29 +++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.h | 1 +
2 files changed, 30 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 76a8cb2..bf1d6c6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -689,10 +689,29 @@ static ssize_t tmc_etr_get_data_flat_buf(struct etr_buf *etr_buf,
return len;
}
+/*
+ * tmc_etr_sync_flat_buf_for_device: Drop any CPU cache lines over the trace
+ * buffer before the ETR is allowed to write into it. The buffer is allocated
+ * with dma_alloc_noncoherent(), which zeroes it with CPU stores, and the DMA
+ * API requires a sync for the device before the device writes into the
+ * memory. Without it a non-coherent sink writes into memory while the zero
+ * fill is still dirty in cache, and the write-back lands on top of the trace
+ * data.
+ */
+static void tmc_etr_sync_flat_buf_for_device(struct etr_buf *etr_buf)
+{
+ struct etr_flat_buf *flat_buf = etr_buf->private;
+ struct device *real_dev = flat_buf->dev->parent;
+
+ dma_sync_single_for_device(real_dev, flat_buf->daddr, etr_buf->size,
+ DMA_FROM_DEVICE);
+}
+
static const struct etr_buf_operations etr_flat_buf_ops = {
.alloc = tmc_etr_alloc_flat_buf,
.free = tmc_etr_free_flat_buf,
.sync = tmc_etr_sync_flat_buf,
+ .sync_for_device = tmc_etr_sync_flat_buf_for_device,
.get_data = tmc_etr_get_data_flat_buf,
};
@@ -1113,6 +1132,16 @@ static int __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+
+ /*
+ * Hand the buffer over in a state the device can write into: drop
+ * any dirty CPU cache lines first, or they get written back over
+ * the trace data the ETR produces. Only the flat buffer needs
+ * this; the ETR_SG and CATU data pages are synced by
+ * dma_map_page() when they are allocated.
+ */
+ if (etr_buf->ops->sync_for_device)
+ etr_buf->ops->sync_for_device(etr_buf);
tmc_enable_hw(drvdata);
CS_LOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 6541a27..3dd17da 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -277,6 +277,7 @@ struct etr_buf_operations {
int (*alloc)(struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
int node, void **pages);
void (*sync)(struct etr_buf *etr_buf, u64 rrp, u64 rwp);
+ void (*sync_for_device)(struct etr_buf *etr_buf);
ssize_t (*get_data)(struct etr_buf *etr_buf, u64 offset, size_t len,
char **bufpp);
void (*free)(struct etr_buf *etr_buf);
--
2.34.1
next prev parent reply other threads:[~2026-09-15 13:05 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 13:05 [PATCH 0/1] " NoNine
2026-09-15 13:05 ` NoNine [this message]
2026-09-16 3:04 ` [PATCH 1/1] " Jie Gan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915130503.645953-2-min.chen@siengine.com \
--to=chenmin83@gmail.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=coresight@lists.linaro.org \
--cc=james.clark@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mike.leach@linaro.org \
--cc=min.chen@siengine.com \
--cc=suzuki.poulose@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®