Merge "coresight-tmc: Re-use ETR buffer across use cases"

This commit is contained in:
qctecmdr 2019-12-17 12:30:57 -08:00 • committed by Gerrit - the friendly Code Review server
commit d1ec209b2c
6 changed files with 104 additions and 5 deletions

View file

@ -44,5 +44,11 @@ static inline struct coresight_csr *coresight_csr_get(const char *name)
static inline int of_get_coresight_csr_name(struct device_node *node,
const char **csr_name){ return -EINVAL; }
#endif
#if IS_ENABLED(CONFIG_CORESIGHT_CTI) && IS_ENABLED(CONFIG_OF)
extern struct coresight_cti_data *of_get_coresight_cti_data(
struct device *dev, struct device_node *node);
#else
static inline struct coresight_cti_data *of_get_coresight_cti_data(
struct device *dev, struct device_node *node) { return NULL; }
#endif
#endif

View file

@ -1466,6 +1466,48 @@ static int cti_init_save(struct cti_drvdata *drvdata,
return 0;
}
struct coresight_cti_data *of_get_coresight_cti_data(
struct device *dev, struct device_node *node)
{
int i, ret;
uint32_t ctis_len;
struct device_node *child_node;
struct coresight_cti_data *ctidata;
ctidata = devm_kzalloc(dev, sizeof(*ctidata), GFP_KERNEL);
if (!ctidata)
return ERR_PTR(-ENOMEM);
if (of_get_property(node, "coresight-ctis", &ctis_len))
ctidata->nr_ctis = ctis_len/sizeof(uint32_t);
else
return ERR_PTR(-EINVAL);
if (ctidata->nr_ctis) {
ctidata->names = devm_kzalloc(dev, ctidata->nr_ctis *
sizeof(*ctidata->names),
GFP_KERNEL);
if (!ctidata->names)
return ERR_PTR(-ENOMEM);
for (i = 0; i < ctidata->nr_ctis; i++) {
child_node = of_parse_phandle(node, "coresight-ctis",
i);
if (!child_node)
return ERR_PTR(-EINVAL);
ret = of_property_read_string(child_node,
"coresight-name",
&ctidata->names[i]);
of_node_put(child_node);
if (ret)
return ERR_PTR(ret);
}
}
return ctidata;
}
EXPORT_SYMBOL(of_get_coresight_cti_data);
static int cti_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;

View file

@ -217,6 +217,12 @@ out:
if (!used)
kfree(buf);
if (!ret) {
coresight_cti_map_trigin(drvdata->cti_reset, 0, 0);
coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
dev_info(&csdev->dev, "TMC-ETB/ETF enabled\n");
}
return ret;
}
@ -327,6 +333,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
spin_unlock_irqrestore(&drvdata->spinlock, flags);
coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0);
coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n");
return 0;
}

View file

@ -1135,6 +1135,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
* buffer, provided the size matches. Any allocation has to be done
* with the lock released.
*/
mutex_lock(&drvdata->mem_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
@ -1142,13 +1143,17 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
/* Allocate memory with the locks released */
free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
if (IS_ERR(new_buf))
if (IS_ERR(new_buf)) {
mutex_unlock(&drvdata->mem_lock);
return PTR_ERR(new_buf);
}
/* Let's try again */
spin_lock_irqsave(&drvdata->spinlock, flags);
}
coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
if (drvdata->reading || drvdata->mode == CS_MODE_PERF) {
ret = -EBUSY;
goto out;
@ -1188,6 +1193,7 @@ out:
tmc_etr_free_sysfs_buf(free_buf);
tmc_etr_byte_cntr_start(drvdata->byte_cntr);
mutex_unlock(&drvdata->mem_lock);
if (!ret)
dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@ -1633,10 +1639,12 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
mutex_lock(&drvdata->mem_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
mutex_unlock(&drvdata->mem_lock);
return -EBUSY;
}
@ -1657,11 +1665,14 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
spin_unlock_irqrestore(&drvdata->spinlock, flags);
tmc_etr_byte_cntr_stop(drvdata->byte_cntr);
coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
/* Free memory outside the spinlock if need be */
if (drvdata->etr_buf) {
tmc_etr_free_sysfs_buf(drvdata->etr_buf);
drvdata->etr_buf = NULL;
}
mutex_unlock(&drvdata->mem_lock);
dev_info(&csdev->dev, "TMC-ETR disabled\n");
return 0;
}
@ -1687,6 +1698,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
return -EINVAL;
mutex_lock(&drvdata->mem_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
ret = -EBUSY;
@ -1715,6 +1727,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
drvdata->reading = true;
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
mutex_unlock(&drvdata->mem_lock);
return ret;
}
@ -1727,7 +1740,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
/* config types are set a boot time and never change */
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
return -EINVAL;
mutex_lock(&drvdata->mem_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
/* RE-enable the TMC if need be */
@ -1754,5 +1767,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
if (sysfs_buf)
tmc_etr_free_sysfs_buf(sysfs_buf);
mutex_unlock(&drvdata->mem_lock);
return 0;
}

View file

@ -184,19 +184,24 @@ 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);
mutex_lock(&drvdata->mem_lock);
actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
if (actual <= 0)
if (actual <= 0) {
mutex_unlock(&drvdata->mem_lock);
return 0;
}
if (copy_to_user(data, bufp, actual)) {
dev_dbg(&drvdata->csdev->dev,
"%s: copy_to_user failed\n", __func__);
mutex_unlock(&drvdata->mem_lock);
return -EFAULT;
}
*ppos += actual;
dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual);
mutex_unlock(&drvdata->mem_lock);
return actual;
}
@ -493,6 +498,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
struct coresight_dev_list *dev_list = NULL;
struct coresight_cti_data *ctidata;
ret = -ENOMEM;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
@ -511,6 +517,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->base = base;
spin_lock_init(&drvdata->spinlock);
mutex_init(&drvdata->mem_lock);
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
drvdata->config_type = BMVAL(devid, 6, 7);
@ -534,6 +541,23 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
}
}
ctidata = of_get_coresight_cti_data(dev, adev->dev.of_node);
if (IS_ERR(ctidata)) {
dev_err(dev, "invalid cti data\n");
} else if (ctidata && ctidata->nr_ctis == 2) {
drvdata->cti_flush = coresight_cti_get(ctidata->names[0]);
if (IS_ERR(drvdata->cti_flush)) {
dev_err(dev, "failed to get flush cti, defer probe\n");
return -EPROBE_DEFER;
}
drvdata->cti_reset = coresight_cti_get(ctidata->names[1]);
if (IS_ERR(drvdata->cti_reset)) {
dev_err(dev, "failed to get reset cti, defer probe\n");
return -EPROBE_DEFER;
}
}
desc.dev = dev;
desc.groups = coresight_tmc_groups;

View file

@ -12,6 +12,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
#include <linux/coresight-cti.h>
#include "coresight-byte-cntr.h"
@ -203,6 +204,7 @@ struct tmc_drvdata {
u32 mode;
enum tmc_config_type config_type;
enum tmc_mem_intf_width memwidth;
struct mutex mem_lock;
u32 trigger_cntr;
u32 etr_caps;
struct idr idr;
@ -213,6 +215,8 @@ struct tmc_drvdata {
const char *csr_name;
bool enable;
struct byte_cntr *byte_cntr;
struct coresight_cti *cti_flush;
struct coresight_cti *cti_reset;
};
struct etr_buf_operations {