coresight: byte-cntr: Add support for streaming interface for ETR

Add support for a streaming interface for TMC ETR to allow for continuous
log collection to secondary storage. An interrupt based mechanism is used
to stream out the data from the device. The streaming interface cannot be
used in conjunction with the traditional ETR read operation.

Change-Id: Ie80f817740fe3fddbb7fe95b02263525b0bff6e8
Signed-off-by: Mulu He <muluhe@codeaurora.org>
Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org>
This commit is contained in:
Mulu He 2017-09-12 15:34:14 -07:00 • committed by Gerrit - the friendly Code Review server
commit dea749a618
3 changed files with 57 additions and 1 deletions

View file

@ -1187,6 +1187,8 @@ out:
if (free_buf)
tmc_etr_free_sysfs_buf(free_buf);
tmc_etr_byte_cntr_start(drvdata->byte_cntr);
if (!ret)
dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@ -1654,12 +1656,13 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
spin_unlock_irqrestore(&drvdata->spinlock, flags);
tmc_etr_byte_cntr_stop(drvdata->byte_cntr);
/* Free memory outside the spinlock if need be */
if (drvdata->etr_buf) {
tmc_etr_free_sysfs_buf(drvdata->etr_buf);
drvdata->etr_buf = NULL;
}
dev_dbg(&csdev->dev, "TMC-ETR disabled\n");
dev_info(&csdev->dev, "TMC-ETR disabled\n");
return 0;
}
@ -1700,6 +1703,11 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
goto out;
}
if (drvdata->byte_cntr && drvdata->byte_cntr->enable) {
ret = -EINVAL;
goto out;
}
/* Disable the TMC if we are trying to read from a running session. */
if (drvdata->mode == CS_MODE_SYSFS)
__tmc_etr_disable_hw(drvdata);

View file

@ -355,9 +355,51 @@ static ssize_t buffer_size_store(struct device *dev,
static DEVICE_ATTR_RW(buffer_size);
static ssize_t block_size_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
uint32_t val = 0;
if (drvdata->byte_cntr)
val = drvdata->byte_cntr->block_size;
return scnprintf(buf, PAGE_SIZE, "%d\n",
val);
}
static ssize_t block_size_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (!drvdata->byte_cntr)
return -EINVAL;
if (val && val < 4096) {
pr_err("Assign minimum block size of 4096 bytes\n");
return -EINVAL;
}
mutex_lock(&drvdata->byte_cntr->byte_cntr_lock);
drvdata->byte_cntr->block_size = val;
mutex_unlock(&drvdata->byte_cntr->byte_cntr_lock);
return size;
}
static DEVICE_ATTR_RW(block_size);
static struct attribute *coresight_tmc_attrs[] = {
&dev_attr_trigger_cntr.attr,
&dev_attr_buffer_size.attr,
&dev_attr_block_size.attr,
NULL,
};
@ -508,6 +550,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
desc.ops = &tmc_etr_cs_ops;
ret = tmc_etr_setup_caps(dev, devid,
coresight_get_uci_data(id));
drvdata->byte_cntr = byte_cntr_init(adev, drvdata);
if (ret)
goto out;
idr_init(&drvdata->idr);

View file

@ -13,6 +13,8 @@
#include <linux/mutex.h>
#include <linux/refcount.h>
#include "coresight-byte-cntr.h"
#define TMC_RSZ 0x004
#define TMC_STS 0x00c
#define TMC_RRD 0x010
@ -210,6 +212,7 @@ struct tmc_drvdata {
struct coresight_csr *csr;
const char *csr_name;
bool enable;
struct byte_cntr *byte_cntr;
};
struct etr_buf_operations {
@ -271,6 +274,8 @@ ssize_t tmc_etb_get_sysfs_trace(struct tmc_drvdata *drvdata,
/* ETR functions */
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata);
int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata);
extern struct byte_cntr *byte_cntr_init(struct amba_device *adev,
struct tmc_drvdata *drvdata);
extern const struct coresight_ops tmc_etr_cs_ops;
ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
loff_t pos, size_t len, char **bufpp);