The byte-cntr read function always reads trace data from the deactivated
and filled buffer which is already synced. The read function will fail
when the ETR cannot find a available buffer to receive trace data.
The read function terminates when the path is disabled or interrupted by a
signal.
Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
---
.../hwtracing/coresight/coresight-tmc-core.c | 31 ++++++-
.../hwtracing/coresight/coresight-tmc-etr.c | 90 +++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.h | 3 +
3 files changed, 120 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 354faeeddbb2..3ab25adc4e4d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -318,14 +318,18 @@ static int tmc_open(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len,
- char **bufpp)
+static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ struct ctcu_byte_cntr *byte_cntr_data,
+ loff_t pos, size_t len, char **bufpp)
{
switch (drvdata->config_type) {
case TMC_CONFIG_TYPE_ETB:
case TMC_CONFIG_TYPE_ETF:
return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp);
case TMC_CONFIG_TYPE_ETR:
+ if (byte_cntr_data && byte_cntr_data->thresh_val)
+ return tmc_byte_cntr_get_data(drvdata, byte_cntr_data, len, bufpp);
+
return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
}
@@ -339,7 +343,21 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
ssize_t actual;
struct tmc_drvdata *drvdata = container_of(file->private_data,
struct tmc_drvdata, miscdev);
- actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
+ struct coresight_device *helper = coresight_get_helper(drvdata->csdev,
+ CORESIGHT_DEV_SUBTYPE_HELPER_CTCU);
+ struct ctcu_byte_cntr *byte_cntr_data = NULL;
+ struct ctcu_drvdata *ctcu_drvdata = NULL;
+ int port;
+
+ if (helper) {
+ port = coresight_get_port_helper(drvdata->csdev, helper);
+ if (port >= 0) {
+ ctcu_drvdata = dev_get_drvdata(helper->dev.parent);
+ byte_cntr_data = &ctcu_drvdata->byte_cntr_data[port];
+ }
+ }
+
+ actual = tmc_get_sysfs_trace(drvdata, byte_cntr_data, *ppos, len, &bufp);
if (actual <= 0)
return 0;
@@ -349,7 +367,12 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
return -EFAULT;
}
- *ppos += actual;
+ if (byte_cntr_data && byte_cntr_data->thresh_val) {
+ byte_cntr_data->total_size += actual;
+ drvdata->reading_node->pos += actual;
+ } else
+ *ppos += actual;
+
dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual);
return actual;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 3e3e1b5e78ca..174411e76047 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1163,6 +1163,10 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
ssize_t actual = len;
struct etr_buf *etr_buf = drvdata->sysfs_buf;
+ /* Reading the buffer from the buf_node if it exists*/
+ if (drvdata->reading_node)
+ etr_buf = drvdata->reading_node->sysfs_buf;
+
if (pos + actual > etr_buf->len)
actual = etr_buf->len - pos;
if (actual <= 0)
@@ -1339,6 +1343,92 @@ static bool tmc_byte_cntr_switch_buffer(struct tmc_drvdata *drvdata,
return found_free_buf;
}
+/*
+ * tmc_byte_cntr_get_data() - reads data from the deactivated and filled buffer.
+ * The byte-cntr reading work reads data from the deactivated and filled buffer.
+ * The read operation waits for a buffer to become available, either filled or
+ * upon timeout, and then reads trace data from the synced buffer.
+ */
+ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata,
+ struct ctcu_byte_cntr *byte_cntr_data,
+ size_t len, char **bufpp)
+{
+ size_t thresh_val = byte_cntr_data->thresh_val;
+ atomic_t *irq_cnt = &byte_cntr_data->irq_cnt;
+ struct etr_buf *sysfs_buf = drvdata->sysfs_buf;
+ struct device *dev = &drvdata->csdev->dev;
+ struct etr_buf_node *nd, *next;
+ ssize_t size = sysfs_buf->size;
+ ssize_t actual;
+ loff_t pos;
+ int ret;
+
+wait_buffer:
+ if (!byte_cntr_data->reading_buf) {
+ ret = wait_event_interruptible_timeout(byte_cntr_data->wq,
+ ((atomic_read(irq_cnt) + 1) * thresh_val >= size) ||
+ !byte_cntr_data->enable,
+ BYTE_CNTR_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ /*
+ * The current etr_buf is almost full or timeout is triggered,
+ * so switch the buffer and mark the switched buffer as reading.
+ */
+ if (byte_cntr_data->enable) {
+ if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data)) {
+ dev_err(dev, "Switch buffer failed for byte-cntr\n");
+ return -EINVAL;
+ }
+
+ byte_cntr_data->reading_buf = true;
+ } else {
+ if (!drvdata->reading_node) {
+ list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, node) {
+ if (nd->sysfs_buf == sysfs_buf) {
+ nd->pos = 0;
+ drvdata->reading_node = nd;
+ break;
+ }
+ }
+ }
+
+ pos = drvdata->reading_node->pos;
+ actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
+ if (actual > 0)
+ return actual;
+
+ drvdata->reading_node = NULL;
+
+ /* Exit byte-cntr reading */
+ return -EINVAL;
+ }
+ }
+
+ /* Check the status of current etr_buf*/
+ if ((atomic_read(irq_cnt) + 1) * thresh_val >= size)
+ /*
+ * Unlikely to find a free buffer to switch, so just disable
+ * the ETR for a while.
+ */
+ if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data))
+ dev_info(dev, "No available buffer to store data, disable ETR\n");
+
+ pos = drvdata->reading_node->pos;
+ actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
+ if (actual == 0) {
+ /* Reading work for marked buffer has finished, reset flags */
+ drvdata->reading_node->reading = false;
+ byte_cntr_data->reading_buf = false;
+ drvdata->reading_node = NULL;
+
+ /* Nothing in the buffer, wait for next buffer to be filled */
+ goto wait_buffer;
+ }
+
+ return actual;
+}
+
static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
{
int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 1dbba0bc50a3..4136ec5ecaf7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -364,6 +364,9 @@ int tmc_read_prepare_byte_cntr(struct tmc_drvdata *drvdata,
struct ctcu_byte_cntr *byte_cntr_data);
int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *drvdata,
struct ctcu_byte_cntr *byte_cntr_data);
+ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata,
+ struct ctcu_byte_cntr *byte_cntr_data,
+ size_t len, char **bufpp);
#define TMC_REG_PAIR(name, lo_off, hi_off) \
static inline u64 \
--
2.34.1
Hi, On Mon, 14 Jul 2025 at 07:32, Jie Gan <jie.gan@oss.qualcomm.com> wrote: > > The byte-cntr read function always reads trace data from the deactivated > and filled buffer which is already synced. The read function will fail > when the ETR cannot find a available buffer to receive trace data. > > The read function terminates when the path is disabled or interrupted by a > signal. > > Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com> > --- > .../hwtracing/coresight/coresight-tmc-core.c | 31 ++++++- > .../hwtracing/coresight/coresight-tmc-etr.c | 90 +++++++++++++++++++ > drivers/hwtracing/coresight/coresight-tmc.h | 3 + > 3 files changed, 120 insertions(+), 4 deletions(-) > > diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c > index 354faeeddbb2..3ab25adc4e4d 100644 > --- a/drivers/hwtracing/coresight/coresight-tmc-core.c > +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c > @@ -318,14 +318,18 @@ static int tmc_open(struct inode *inode, struct file *file) > return 0; > } > > -static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, > - char **bufpp) > +static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, > + struct ctcu_byte_cntr *byte_cntr_data, > + loff_t pos, size_t len, char **bufpp) Don't change "core" functionalilty to add in bytecntr parameters. Use helper functions to have a pattern such as: if (bytecntr_active()) call_byte_cntr_fn() else call_standard_fn() > { > switch (drvdata->config_type) { > case TMC_CONFIG_TYPE_ETB: > case TMC_CONFIG_TYPE_ETF: > return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp); > case TMC_CONFIG_TYPE_ETR: > + if (byte_cntr_data && byte_cntr_data->thresh_val) > + return tmc_byte_cntr_get_data(drvdata, byte_cntr_data, len, bufpp); > + > return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); > } > > @@ -339,7 +343,21 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, > ssize_t actual; > struct tmc_drvdata *drvdata = container_of(file->private_data, > struct tmc_drvdata, miscdev); > - actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp); > + struct coresight_device *helper = coresight_get_helper(drvdata->csdev, > + CORESIGHT_DEV_SUBTYPE_HELPER_CTCU); > + struct ctcu_byte_cntr *byte_cntr_data = NULL; > + struct ctcu_drvdata *ctcu_drvdata = NULL; > + int port; > + > + if (helper) { > + port = coresight_get_port_helper(drvdata->csdev, helper); > + if (port >= 0) { > + ctcu_drvdata = dev_get_drvdata(helper->dev.parent); > + byte_cntr_data = &ctcu_drvdata->byte_cntr_data[port]; > + } > + } > + > + actual = tmc_get_sysfs_trace(drvdata, byte_cntr_data, *ppos, len, &bufp); > if (actual <= 0) > return 0; > > @@ -349,7 +367,12 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, > return -EFAULT; > } > > - *ppos += actual; > + if (byte_cntr_data && byte_cntr_data->thresh_val) { > + byte_cntr_data->total_size += actual; > + drvdata->reading_node->pos += actual; > + } else > + *ppos += actual; > + > dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual); > > return actual; > diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c > index 3e3e1b5e78ca..174411e76047 100644 > --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c > +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c > @@ -1163,6 +1163,10 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, > ssize_t actual = len; > struct etr_buf *etr_buf = drvdata->sysfs_buf; > > + /* Reading the buffer from the buf_node if it exists*/ > + if (drvdata->reading_node) > + etr_buf = drvdata->reading_node->sysfs_buf; > + > if (pos + actual > etr_buf->len) > actual = etr_buf->len - pos; > if (actual <= 0) > @@ -1339,6 +1343,92 @@ static bool tmc_byte_cntr_switch_buffer(struct tmc_drvdata *drvdata, > return found_free_buf; > } > > +/* > + * tmc_byte_cntr_get_data() - reads data from the deactivated and filled buffer. > + * The byte-cntr reading work reads data from the deactivated and filled buffer. > + * The read operation waits for a buffer to become available, either filled or > + * upon timeout, and then reads trace data from the synced buffer. > + */ This entire function should be moved to one of the byte-cntr source files. > +ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata, > + struct ctcu_byte_cntr *byte_cntr_data, > + size_t len, char **bufpp) > +{ > + size_t thresh_val = byte_cntr_data->thresh_val; > + atomic_t *irq_cnt = &byte_cntr_data->irq_cnt; > + struct etr_buf *sysfs_buf = drvdata->sysfs_buf; > + struct device *dev = &drvdata->csdev->dev; > + struct etr_buf_node *nd, *next; > + ssize_t size = sysfs_buf->size; > + ssize_t actual; > + loff_t pos; > + int ret; > + > +wait_buffer: > + if (!byte_cntr_data->reading_buf) { > + ret = wait_event_interruptible_timeout(byte_cntr_data->wq, > + ((atomic_read(irq_cnt) + 1) * thresh_val >= size) || > + !byte_cntr_data->enable, > + BYTE_CNTR_TIMEOUT); > + if (ret < 0) > + return ret; > + /* > + * The current etr_buf is almost full or timeout is triggered, > + * so switch the buffer and mark the switched buffer as reading. > + */ > + if (byte_cntr_data->enable) { > + if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data)) { > + dev_err(dev, "Switch buffer failed for byte-cntr\n"); > + return -EINVAL; > + } > + > + byte_cntr_data->reading_buf = true; > + } else { > + if (!drvdata->reading_node) { > + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, node) { > + if (nd->sysfs_buf == sysfs_buf) { > + nd->pos = 0; > + drvdata->reading_node = nd; > + break; > + } > + } > + } > + > + pos = drvdata->reading_node->pos; > + actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); > + if (actual > 0) > + return actual; > + > + drvdata->reading_node = NULL; > + > + /* Exit byte-cntr reading */ > + return -EINVAL; > + } > + } > + > + /* Check the status of current etr_buf*/ > + if ((atomic_read(irq_cnt) + 1) * thresh_val >= size) > + /* > + * Unlikely to find a free buffer to switch, so just disable > + * the ETR for a while. > + */ > + if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data)) > + dev_info(dev, "No available buffer to store data, disable ETR\n"); > + > + pos = drvdata->reading_node->pos; > + actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); > + if (actual == 0) { > + /* Reading work for marked buffer has finished, reset flags */ > + drvdata->reading_node->reading = false; > + byte_cntr_data->reading_buf = false; > + drvdata->reading_node = NULL; > + > + /* Nothing in the buffer, wait for next buffer to be filled */ > + goto wait_buffer; > + } > + > + return actual; > +} > + > static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) > { > int ret = 0; > diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h > index 1dbba0bc50a3..4136ec5ecaf7 100644 > --- a/drivers/hwtracing/coresight/coresight-tmc.h > +++ b/drivers/hwtracing/coresight/coresight-tmc.h > @@ -364,6 +364,9 @@ int tmc_read_prepare_byte_cntr(struct tmc_drvdata *drvdata, > struct ctcu_byte_cntr *byte_cntr_data); > int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *drvdata, > struct ctcu_byte_cntr *byte_cntr_data); Declare this in a byte_cntr header file, not here. > +ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata, > + struct ctcu_byte_cntr *byte_cntr_data, > + size_t len, char **bufpp); > > #define TMC_REG_PAIR(name, lo_off, hi_off) \ > static inline u64 \ > -- > 2.34.1 > -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 7/22/2025 11:01 PM, Mike Leach wrote: > Hi, > > On Mon, 14 Jul 2025 at 07:32, Jie Gan <jie.gan@oss.qualcomm.com> wrote: >> >> The byte-cntr read function always reads trace data from the deactivated >> and filled buffer which is already synced. The read function will fail >> when the ETR cannot find a available buffer to receive trace data. >> >> The read function terminates when the path is disabled or interrupted by a >> signal. >> >> Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com> >> --- >> .../hwtracing/coresight/coresight-tmc-core.c | 31 ++++++- >> .../hwtracing/coresight/coresight-tmc-etr.c | 90 +++++++++++++++++++ >> drivers/hwtracing/coresight/coresight-tmc.h | 3 + >> 3 files changed, 120 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c >> index 354faeeddbb2..3ab25adc4e4d 100644 >> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c >> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c >> @@ -318,14 +318,18 @@ static int tmc_open(struct inode *inode, struct file *file) >> return 0; >> } >> >> -static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, >> - char **bufpp) >> +static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, >> + struct ctcu_byte_cntr *byte_cntr_data, >> + loff_t pos, size_t len, char **bufpp) > > Don't change "core" functionalilty to add in bytecntr parameters. > > Use helper functions to have a pattern such as: > > if (bytecntr_active()) > call_byte_cntr_fn() > else > call_standard_fn() got it. Will fix in next version. Thanks, Jie > >> { >> switch (drvdata->config_type) { >> case TMC_CONFIG_TYPE_ETB: >> case TMC_CONFIG_TYPE_ETF: >> return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp); >> case TMC_CONFIG_TYPE_ETR: >> + if (byte_cntr_data && byte_cntr_data->thresh_val) >> + return tmc_byte_cntr_get_data(drvdata, byte_cntr_data, len, bufpp); >> + >> return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); >> } >> >> @@ -339,7 +343,21 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, >> ssize_t actual; >> struct tmc_drvdata *drvdata = container_of(file->private_data, >> struct tmc_drvdata, miscdev); >> - actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp); >> + struct coresight_device *helper = coresight_get_helper(drvdata->csdev, >> + CORESIGHT_DEV_SUBTYPE_HELPER_CTCU); >> + struct ctcu_byte_cntr *byte_cntr_data = NULL; >> + struct ctcu_drvdata *ctcu_drvdata = NULL; >> + int port; >> + >> + if (helper) { >> + port = coresight_get_port_helper(drvdata->csdev, helper); >> + if (port >= 0) { >> + ctcu_drvdata = dev_get_drvdata(helper->dev.parent); >> + byte_cntr_data = &ctcu_drvdata->byte_cntr_data[port]; >> + } >> + } >> + >> + actual = tmc_get_sysfs_trace(drvdata, byte_cntr_data, *ppos, len, &bufp); >> if (actual <= 0) >> return 0; >> >> @@ -349,7 +367,12 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, >> return -EFAULT; >> } >> >> - *ppos += actual; >> + if (byte_cntr_data && byte_cntr_data->thresh_val) { >> + byte_cntr_data->total_size += actual; >> + drvdata->reading_node->pos += actual; >> + } else >> + *ppos += actual; >> + >> dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual); >> >> return actual; >> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c >> index 3e3e1b5e78ca..174411e76047 100644 >> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c >> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c >> @@ -1163,6 +1163,10 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, >> ssize_t actual = len; >> struct etr_buf *etr_buf = drvdata->sysfs_buf; >> >> + /* Reading the buffer from the buf_node if it exists*/ >> + if (drvdata->reading_node) >> + etr_buf = drvdata->reading_node->sysfs_buf; >> + >> if (pos + actual > etr_buf->len) >> actual = etr_buf->len - pos; >> if (actual <= 0) >> @@ -1339,6 +1343,92 @@ static bool tmc_byte_cntr_switch_buffer(struct tmc_drvdata *drvdata, >> return found_free_buf; >> } >> >> +/* >> + * tmc_byte_cntr_get_data() - reads data from the deactivated and filled buffer. >> + * The byte-cntr reading work reads data from the deactivated and filled buffer. >> + * The read operation waits for a buffer to become available, either filled or >> + * upon timeout, and then reads trace data from the synced buffer. >> + */ > > This entire function should be moved to one of the byte-cntr source files. > >> +ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata, >> + struct ctcu_byte_cntr *byte_cntr_data, >> + size_t len, char **bufpp) >> +{ >> + size_t thresh_val = byte_cntr_data->thresh_val; >> + atomic_t *irq_cnt = &byte_cntr_data->irq_cnt; >> + struct etr_buf *sysfs_buf = drvdata->sysfs_buf; >> + struct device *dev = &drvdata->csdev->dev; >> + struct etr_buf_node *nd, *next; >> + ssize_t size = sysfs_buf->size; >> + ssize_t actual; >> + loff_t pos; >> + int ret; >> + >> +wait_buffer: >> + if (!byte_cntr_data->reading_buf) { >> + ret = wait_event_interruptible_timeout(byte_cntr_data->wq, >> + ((atomic_read(irq_cnt) + 1) * thresh_val >= size) || >> + !byte_cntr_data->enable, >> + BYTE_CNTR_TIMEOUT); >> + if (ret < 0) >> + return ret; >> + /* >> + * The current etr_buf is almost full or timeout is triggered, >> + * so switch the buffer and mark the switched buffer as reading. >> + */ >> + if (byte_cntr_data->enable) { >> + if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data)) { >> + dev_err(dev, "Switch buffer failed for byte-cntr\n"); >> + return -EINVAL; >> + } >> + >> + byte_cntr_data->reading_buf = true; >> + } else { >> + if (!drvdata->reading_node) { >> + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, node) { >> + if (nd->sysfs_buf == sysfs_buf) { >> + nd->pos = 0; >> + drvdata->reading_node = nd; >> + break; >> + } >> + } >> + } >> + >> + pos = drvdata->reading_node->pos; >> + actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); >> + if (actual > 0) >> + return actual; >> + >> + drvdata->reading_node = NULL; >> + >> + /* Exit byte-cntr reading */ >> + return -EINVAL; >> + } >> + } >> + >> + /* Check the status of current etr_buf*/ >> + if ((atomic_read(irq_cnt) + 1) * thresh_val >= size) >> + /* >> + * Unlikely to find a free buffer to switch, so just disable >> + * the ETR for a while. >> + */ >> + if (!tmc_byte_cntr_switch_buffer(drvdata, byte_cntr_data)) >> + dev_info(dev, "No available buffer to store data, disable ETR\n"); >> + >> + pos = drvdata->reading_node->pos; >> + actual = tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); >> + if (actual == 0) { >> + /* Reading work for marked buffer has finished, reset flags */ >> + drvdata->reading_node->reading = false; >> + byte_cntr_data->reading_buf = false; >> + drvdata->reading_node = NULL; >> + >> + /* Nothing in the buffer, wait for next buffer to be filled */ >> + goto wait_buffer; >> + } >> + >> + return actual; >> +} >> + >> static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) >> { >> int ret = 0; >> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h >> index 1dbba0bc50a3..4136ec5ecaf7 100644 >> --- a/drivers/hwtracing/coresight/coresight-tmc.h >> +++ b/drivers/hwtracing/coresight/coresight-tmc.h >> @@ -364,6 +364,9 @@ int tmc_read_prepare_byte_cntr(struct tmc_drvdata *drvdata, >> struct ctcu_byte_cntr *byte_cntr_data); >> int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *drvdata, >> struct ctcu_byte_cntr *byte_cntr_data); > > Declare this in a byte_cntr header file, not here. I will add it to,for example, ctcu_byte_cntr_read_ops->read. So I think I dont need define it in any header file in future. Will remove it. Thanks, Jie > >> +ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *drvdata, >> + struct ctcu_byte_cntr *byte_cntr_data, >> + size_t len, char **bufpp); >> >> #define TMC_REG_PAIR(name, lo_off, hi_off) \ >> static inline u64 \ >> -- >> 2.34.1 >> > >
© 2016 - 2025 Red Hat, Inc.