On 13/07/2023 14:47, Linu Cherian wrote:
- Get reserved region from device tree node for metadata
- Define metadata format for TMC
- Add TMC ETR panic sync handler that syncs register snapshot to metadata region
- Add TMC ETF panic sync handler that syncs register snapshot to metadata region and internal SRAM to reserved trace buffer region.
Signed-off-by: Linu Cherian lcherian@marvell.com
.../hwtracing/coresight/coresight-tmc-core.c | 30 +++++++++- .../hwtracing/coresight/coresight-tmc-etf.c | 56 +++++++++++++++++++ .../hwtracing/coresight/coresight-tmc-etr.c | 55 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc.h | 18 ++++++ 4 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index b0374ae007d2..67a4bc6f4bff 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -368,7 +368,9 @@ static inline bool is_tmc_reserved_region_valid(struct device *dev) struct tmc_drvdata *drvdata = dev_get_drvdata(dev); if (drvdata->resrv_buf.paddr &&
drvdata->resrv_buf.size)
drvdata->resrv_buf.size &&
drvdata->metadata.paddr &&
return true; return false;drvdata->metadata.size)
} @@ -407,6 +409,32 @@ static void tmc_get_reserved_region(struct device *parent) /* Size of contiguous buffer space for TMC ETR */ drvdata->size = drvdata->resrv_buf.size;
- /* Metadata region */
- node = of_parse_phandle(parent->of_node, "memory-region", 1);
- if (!node) {
dev_dbg(parent, "No metadata memory-region specified\n");
goto out;
- }
- rc = of_address_to_resource(node, 0, &res);
- of_node_put(node);
- if (rc || res.start == 0 || resource_size(&res) == 0) {
dev_err(parent, "Metadata memory is invalid\n");
goto out;
- }
- drvdata->metadata.vaddr = memremap(res.start,
resource_size(&res),
MEMREMAP_WC);
- if (IS_ERR(drvdata->metadata.vaddr)) {
dev_err(parent, "Metadata memory mapping failed\n");
rc = PTR_ERR(drvdata->metadata.vaddr);
goto out;
- }
- drvdata->metadata.paddr = res.start;
- drvdata->metadata.size = resource_size(&res);
out: return; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 0ab1f73c2d06..63f59ea1508e 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -586,6 +586,57 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, return to_read; } +static int tmc_panic_sync_etf(struct coresight_device *csdev) +{
- u32 val;
- struct tmc_register_snapshot *tmc;
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* Make sure we have valid reserved memory */
- if (!drvdata->metadata.vaddr || !drvdata->resrv_buf.vaddr)
return 0;
- tmc = (struct tmc_register_snapshot *)drvdata->metadata.vaddr;
- tmc->valid = 0x0;
- CS_UNLOCK(drvdata->base);
- /* Proceed only if ETF is enabled or configured as sink */
- val = readl(drvdata->base + TMC_CTL);
- if (!(val & TMC_CTL_CAPT_EN))
goto out;
- val = readl(drvdata->base + TMC_MODE);
- if (val != TMC_MODE_CIRCULAR_BUFFER)
goto out;
- tmc_flush_and_stop(drvdata);
- /* Sync registers from hardware to metadata region */
- tmc->sts = readl(drvdata->base + TMC_STS);
- tmc->trc_addrhi = drvdata->resrv_buf.paddr >> 32;
- tmc->trc_addr = drvdata->resrv_buf.paddr & 0xffffffff;
- /* Sync Internal SRAM to reserved trace buffer region */
- tmc_etb_dump_hw(drvdata);
- memcpy(drvdata->resrv_buf.vaddr, drvdata->buf, drvdata->len);
- tmc->size = drvdata->len;
- /*
* Make sure all previous writes are completed,
* before we mark valid
*/
- dsb(sy);
- tmc->valid = 0x1;
- tmc_disable_hw(drvdata);
- dev_info(&csdev->dev, "%s: success\n", __func__);
+out:
- CS_UNLOCK(drvdata->base);
- return 0;
+}
static const struct coresight_ops_sink tmc_etf_sink_ops = { .enable = tmc_enable_etf_sink, .disable = tmc_disable_etf_sink, @@ -599,6 +650,10 @@ static const struct coresight_ops_link tmc_etf_link_ops = { .disable = tmc_disable_etf_link, }; +static const struct coresight_ops_panic tmc_etf_sync_ops = {
- .sync = tmc_panic_sync_etf,
+};
const struct coresight_ops tmc_etb_cs_ops = { .sink_ops = &tmc_etf_sink_ops, }; @@ -606,6 +661,7 @@ const struct coresight_ops tmc_etb_cs_ops = { const struct coresight_ops tmc_etf_cs_ops = { .sink_ops = &tmc_etf_sink_ops, .link_ops = &tmc_etf_link_ops,
- .panic_ops = &tmc_etf_sync_ops,
}; int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 857c77d867c5..a99b3e9fb9ec 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1784,8 +1784,63 @@ static const struct coresight_ops_sink tmc_etr_sink_ops = { .free_buffer = tmc_free_etr_buffer, }; +static int tmc_etr_panic_sync(struct coresight_device *csdev) +{
- u32 val;
- struct tmc_register_snapshot *tmc;
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- /* Make sure we have valid reserved memory */
- if (!drvdata->metadata.vaddr || !drvdata->resrv_buf.vaddr)
return 0;
- tmc = (struct tmc_register_snapshot *)drvdata->metadata.vaddr;
- tmc->valid = 0x0;
- CS_UNLOCK(drvdata->base);
- /* Proceed only if ETR is enabled */
- val = readl(drvdata->base + TMC_CTL);
- if (!(val & TMC_CTL_CAPT_EN))
goto out;
- tmc_flush_and_stop(drvdata);
- /* Sync registers from hardware to metadata region */
- tmc->size = readl(drvdata->base + TMC_RSZ);
- tmc->rrphi = readl(drvdata->base + TMC_RRPHI);
- tmc->rrp = readl(drvdata->base + TMC_RRP);
- tmc->rwphi = readl(drvdata->base + TMC_RWPHI);
- tmc->rwp = readl(drvdata->base + TMC_RWP);
- tmc->sts = readl(drvdata->base + TMC_STS);
- tmc->trc_addrhi = drvdata->resrv_buf.paddr >> 32;
- tmc->trc_addr = drvdata->resrv_buf.paddr & 0xffffffff;
- tmc->dba = readl(drvdata->base + TMC_DBALO);
- tmc->dbahi = readl(drvdata->base + TMC_DBAHI);
Can you just store a 64bit value and use tmc_read_dba()? There are a couple of 32bit pairs that are read and restored manually when there are already some utility functions for that.
There is also the new register access abstraction:
struct csdev_access *csa = &drvdata->csdev.access; tmc->size = csdev_access_relaxed_read32(csa, TMC_RSZ)
- /*
* Make sure all previous writes are completed,
* before we mark valid
*/
- dsb(sy);
- tmc->valid = 0x1;
- tmc_disable_hw(drvdata);
- dev_info(&csdev->dev, "%s: success\n", __func__);
+out:
- CS_UNLOCK(drvdata->base);
- return 0;
+}
+static const struct coresight_ops_panic tmc_etr_sync_ops = {
- .sync = tmc_etr_panic_sync,
+};
const struct coresight_ops tmc_etr_cs_ops = { .sink_ops = &tmc_etr_sink_ops,
- .panic_ops = &tmc_etr_sync_ops,
}; int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 3c344a3a8953..8ebf624b26d9 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -133,6 +133,22 @@ enum tmc_mem_intf_width { #define CORESIGHT_SOC_600_ETR_CAPS \ (TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE) +/* TMC metadata region for ETR and ETF configurations */ +struct tmc_register_snapshot {
- uint32_t valid; /* Indicate if this ETF/ETR was enabled */
- uint32_t size; /* Size of trace data */
- uint32_t rrphi; /* Read pointer high address bits */
- uint32_t rrp; /* Read pointer */
- uint32_t rwphi; /* Write pointer high address bits */
- uint32_t rwp; /* Write pointer */
- uint32_t sts; /* Status register */
- uint32_t trc_addrhi; /* Phys high address bits of trace buffer */
- uint32_t trc_addr; /* Phys address of trace buffer */
- uint32_t dbahi; /* Data buffer high address bits */
- uint32_t dba; /* Data buffer address */
- uint32_t reserved[5];
+};
enum etr_mode { ETR_MODE_FLAT, /* Uses contiguous flat buffer */ ETR_MODE_ETR_SG, /* Uses in-built TMC ETR SG mechanism */ @@ -202,6 +218,7 @@ struct tmc_resrv_buf {
- @sysfs_buf: SYSFS buffer for ETR.
- @perf_buf: PERF buffer for ETR.
- @resrv_buf: Reserved Memory for trace data buffer. Used by ETR/ETF.
*/
- @metadata: Reserved memory for metadata. Used by ETR/ETF.
struct tmc_drvdata { void __iomem *base; @@ -227,6 +244,7 @@ struct tmc_drvdata { struct etr_buf *sysfs_buf; struct etr_buf *perf_buf; struct tmc_resrv_buf resrv_buf;
- struct tmc_resrv_buf metadata;
}; struct etr_buf_operations {