Hi, On Mon, 10 Mar 2025 at 09:04, Jie Gan <quic_jiegan@xxxxxxxxxxx> wrote: > > The new functions calculate and return the offset to the write pointer of > the ETR buffer based on whether the memory mode is SG, flat or reserved. > The functions have the RWP offset can directly read data from ETR buffer, > enabling the transfer of data to any required location. > > Signed-off-by: Jie Gan <quic_jiegan@xxxxxxxxxxx> > --- > .../hwtracing/coresight/coresight-tmc-etr.c | 40 +++++++++++++++++++ > drivers/hwtracing/coresight/coresight-tmc.h | 1 + > 2 files changed, 41 insertions(+) > > diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c > index eda7cdad0e2b..ec636ab1fd75 100644 > --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c > +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c > @@ -267,6 +267,46 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table) > } > EXPORT_SYMBOL_GPL(tmc_free_sg_table); > > +static long tmc_flat_resrv_get_rwp_offset(struct tmc_drvdata *drvdata) > +{ > + dma_addr_t paddr = drvdata->sysfs_buf->hwaddr; > + u64 rwp; > + It is not valid to read RWP if the TMC is running. It must be in the stopped or disabled state - see the specifications for TMC /ETR It is likely that CSUNLOCK / CSLOCK are needed here too, along with the spinlock that protects drvdata See the code in coresight_tmc_etr.c :- e.g. in tmc_update_etr_buffer() ... <take spinlock> ... CS_UNLOCK(drvdata->base); tmc_flush_and_stop(drvdata); // this ensures tmc is stopped and flushed to memory - essential to ensure full formatted frame is in memory. tmc_sync_etr_buf(drvdata); // this function reads rwp. CS_LOCK(drvdata->base); <release spinlokc> This type of program flow is common to both sysfs and perf handling of TMC buffers. > + rwp = tmc_read_rwp(drvdata); > + return rwp - paddr; > +} > + > +static long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata) > +{ > + struct etr_buf *etr_buf = drvdata->sysfs_buf; > + struct etr_sg_table *etr_table = etr_buf->private; > + struct tmc_sg_table *table = etr_table->sg_table; > + long w_offset; > + u64 rwp; > + Same comments as above > + rwp = tmc_read_rwp(drvdata); > + w_offset = tmc_sg_get_data_page_offset(table, rwp); > + > + return w_offset; > +} > + > +/* > + * Retrieve the offset to the write pointer of the ETR buffer based on whether > + * the memory mode is SG, flat or reserved. > + */ > +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata) > +{ > + struct etr_buf *etr_buf = drvdata->sysfs_buf; > + As this is an exported function, please ensure that the inputs are valid - check the pointers Code to ensure TMC is flushed and stopped could be inserted here. Regards Mike > + if (etr_buf->mode == ETR_MODE_ETR_SG) > + return tmc_sg_get_rwp_offset(drvdata); > + else if (etr_buf->mode == ETR_MODE_FLAT || etr_buf->mode == ETR_MODE_RESRV) > + return tmc_flat_resrv_get_rwp_offset(drvdata); > + else > + return -EINVAL; > +} > +EXPORT_SYMBOL_GPL(tmc_get_rwp_offset); > + > /* > * Alloc pages for the table. Since this will be used by the device, > * allocate the pages closer to the device (i.e, dev_to_node(dev) > diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h > index b48bc9a01cc0..baedb4dcfc3f 100644 > --- a/drivers/hwtracing/coresight/coresight-tmc.h > +++ b/drivers/hwtracing/coresight/coresight-tmc.h > @@ -442,5 +442,6 @@ void tmc_etr_remove_catu_ops(void); > struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, > enum cs_mode mode, void *data); > extern const struct attribute_group coresight_etr_group; > +long tmc_get_rwp_offset(struct tmc_drvdata *drvdata); > > #endif > -- > 2.34.1 > -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK