mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
coresight: etb10: Splitting function etb_enable()
Up until now the relative simplicity of enabling the ETB made it possible to accommodate processing for both sysFS and perf methods. But work on claimtags and CPU-wide trace scenarios is adding some complexity, making the current code messy and hard to maintain. As such follow what has been done for ETF and ETR components and split function etb_enable() so that processing for both API can be done cleanly. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d43b8ec599
commit
d4989fe886
1 changed files with 52 additions and 21 deletions
|
@ -134,7 +134,7 @@ static void etb_enable_hw(struct etb_drvdata *drvdata)
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etb_enable(struct coresight_device *csdev, u32 mode, void *data)
|
static int etb_enable_sysfs(struct coresight_device *csdev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -142,48 +142,79 @@ static int etb_enable(struct coresight_device *csdev, u32 mode, void *data)
|
||||||
|
|
||||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||||
|
|
||||||
/*
|
/* Don't messup with perf sessions. */
|
||||||
* When accessing from Perf, a HW buffer can be handled
|
|
||||||
* by a single trace entity. In sysFS mode many tracers
|
|
||||||
* can be logging to the same HW buffer.
|
|
||||||
*/
|
|
||||||
if (drvdata->mode == CS_MODE_PERF) {
|
if (drvdata->mode == CS_MODE_PERF) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't let perf disturb sysFS sessions */
|
/* Nothing to do, the tracer is already enabled. */
|
||||||
if (drvdata->mode == CS_MODE_SYSFS && mode == CS_MODE_PERF) {
|
if (drvdata->mode == CS_MODE_SYSFS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
drvdata->mode = CS_MODE_SYSFS;
|
||||||
|
etb_enable_hw(drvdata);
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int etb_enable_perf(struct coresight_device *csdev, void *data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||||
|
|
||||||
|
/* No need to continue if the component is already in use. */
|
||||||
|
if (drvdata->mode != CS_MODE_DISABLED) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing to do, the tracer is already enabled. */
|
|
||||||
if (drvdata->mode == CS_MODE_SYSFS && mode == CS_MODE_SYSFS)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't have an internal state to clean up if we fail to setup
|
* We don't have an internal state to clean up if we fail to setup
|
||||||
* the perf buffer. So we can perform the step before we turn the
|
* the perf buffer. So we can perform the step before we turn the
|
||||||
* ETB on and leave without cleaning up.
|
* ETB on and leave without cleaning up.
|
||||||
*/
|
*/
|
||||||
if (mode == CS_MODE_PERF) {
|
ret = etb_set_buffer(csdev, (struct perf_output_handle *)data);
|
||||||
ret = etb_set_buffer(csdev, (struct perf_output_handle *)data);
|
if (ret)
|
||||||
if (ret)
|
goto out;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
drvdata->mode = mode;
|
drvdata->mode = CS_MODE_PERF;
|
||||||
etb_enable_hw(drvdata);
|
etb_enable_hw(drvdata);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
dev_dbg(drvdata->dev, "ETB enabled\n");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int etb_enable(struct coresight_device *csdev, u32 mode, void *data)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case CS_MODE_SYSFS:
|
||||||
|
ret = etb_enable_sysfs(csdev);
|
||||||
|
break;
|
||||||
|
case CS_MODE_PERF:
|
||||||
|
ret = etb_enable_perf(csdev, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dev_dbg(drvdata->dev, "ETB enabled\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void etb_disable_hw(struct etb_drvdata *drvdata)
|
static void etb_disable_hw(struct etb_drvdata *drvdata)
|
||||||
{
|
{
|
||||||
u32 ffcr;
|
u32 ffcr;
|
||||||
|
|
Loading…
Reference in a new issue