* @pid: Process ID of the process being monitored by the session
* that is using this component.
* @buf: area of memory where ETB buffer content gets sent.
- * @mode: this ETB is being used.
* @buffer_depth: size of @buf.
* @trigger_cntr: amount of words to store after a trigger.
*/
local_t reading;
pid_t pid;
u8 *buf;
- u32 mode;
u32 buffer_depth;
u32 trigger_cntr;
};
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Don't messup with perf sessions. */
- if (drvdata->mode == CS_MODE_PERF) {
+ if (local_read(&csdev->mode) == CS_MODE_PERF) {
ret = -EBUSY;
goto out;
}
- if (drvdata->mode == CS_MODE_DISABLED) {
+ if (local_read(&csdev->mode) == CS_MODE_DISABLED) {
ret = etb_enable_hw(drvdata);
if (ret)
goto out;
- drvdata->mode = CS_MODE_SYSFS;
+ local_set(&csdev->mode, CS_MODE_SYSFS);
}
atomic_inc(&csdev->refcnt);
spin_lock_irqsave(&drvdata->spinlock, flags);
/* No need to continue if the component is already in used by sysFS. */
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) {
ret = -EBUSY;
goto out;
}
if (!ret) {
/* Associate with monitored process. */
drvdata->pid = pid;
- drvdata->mode = CS_MODE_PERF;
+ local_set(&drvdata->csdev->mode, CS_MODE_PERF);
atomic_inc(&csdev->refcnt);
}
}
/* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);
+ WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED);
etb_disable_hw(drvdata);
/* Dissociate from monitored process. */
drvdata->pid = -1;
- drvdata->mode = CS_MODE_DISABLED;
+ local_set(&csdev->mode, CS_MODE_DISABLED);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_dbg(&csdev->dev, "ETB disabled\n");
unsigned long flags;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) {
__etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
__etb_enable_hw(drvdata);
* @port_size: port size as reported by ETMCR bit 4-6 and 21.
* @arch: ETM/PTM version number.
* @use_cpu14: true if management registers need to be accessed via CP14.
- * @mode: this tracer's mode, i.e sysFS, Perf or disabled.
* @sticky_enable: true if ETM base configuration has been done.
* @boot_enable:true if we should start tracing at boot time.
* @os_unlock: true if access to management registers is allowed.
int port_size;
u8 arch;
bool use_cp14;
- local_t mode;
bool sticky_enable;
bool boot_enable;
bool os_unlock;
u32 val;
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
+ val = local_cmpxchg(&drvdata->csdev->mode, CS_MODE_DISABLED, mode);
/* Someone is already using the tracer */
if (val)
/* The tracer didn't start */
if (ret)
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ local_set(&drvdata->csdev->mode, CS_MODE_DISABLED);
return ret;
}
struct perf_event *event)
{
enum cs_mode mode;
- struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
/*
* For as long as the tracer isn't disabled another entity can't
* change its status. As such we can read the status here without
* fearing it will change under us.
*/
- mode = local_read(&drvdata->mode);
+ mode = local_read(&csdev->mode);
switch (mode) {
case CS_MODE_DISABLED:
}
if (mode)
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ local_set(&csdev->mode, CS_MODE_DISABLED);
}
static const struct coresight_ops_source etm_source_ops = {
etmdrvdata[cpu]->os_unlock = true;
}
- if (local_read(&etmdrvdata[cpu]->mode))
+ if (local_read(&etmdrvdata[cpu]->csdev->mode))
etm_enable_hw(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
return 0;
return 0;
spin_lock(&etmdrvdata[cpu]->spinlock);
- if (local_read(&etmdrvdata[cpu]->mode))
+ if (local_read(&etmdrvdata[cpu]->csdev->mode))
etm_disable_hw(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
return 0;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etm_config *config = &drvdata->config;
- if (!local_read(&drvdata->mode)) {
+ if (!local_read(&drvdata->csdev->mode)) {
spin_lock(&drvdata->spinlock);
for (i = 0; i < drvdata->nr_cntr; i++)
ret += sprintf(buf, "counter %d: %x\n",
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etm_config *config = &drvdata->config;
- if (!local_read(&drvdata->mode)) {
+ if (!local_read(&drvdata->csdev->mode)) {
val = config->seq_curr_state;
goto out;
}
{
int ret;
u32 val;
- struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
+ val = local_cmpxchg(&csdev->mode, CS_MODE_DISABLED, mode);
/* Someone is already using the tracer */
if (val)
/* The tracer didn't start */
if (ret)
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ local_set(&csdev->mode, CS_MODE_DISABLED);
return ret;
}
struct perf_event *event)
{
enum cs_mode mode;
- struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
/*
* For as long as the tracer isn't disabled another entity can't
* change its status. As such we can read the status here without
* fearing it will change under us.
*/
- mode = local_read(&drvdata->mode);
+ mode = local_read(&csdev->mode);
switch (mode) {
case CS_MODE_DISABLED:
}
if (mode)
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ local_set(&csdev->mode, CS_MODE_DISABLED);
}
static const struct coresight_ops_source etm4_source_ops = {
if (!etmdrvdata[cpu]->os_unlock)
etm4_os_unlock(etmdrvdata[cpu]);
- if (local_read(&etmdrvdata[cpu]->mode))
+ if (local_read(&etmdrvdata[cpu]->csdev->mode))
etm4_enable_hw(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
return 0;
return 0;
spin_lock(&etmdrvdata[cpu]->spinlock);
- if (local_read(&etmdrvdata[cpu]->mode))
+ if (local_read(&etmdrvdata[cpu]->csdev->mode))
etm4_disable_hw(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
return 0;
* Save and restore the ETM Trace registers only if
* the ETM is active.
*/
- if (local_read(&drvdata->mode) && drvdata->save_state)
+ if (local_read(&drvdata->csdev->mode) && drvdata->save_state)
ret = __etm4_cpu_save(drvdata);
return ret;
}
void __iomem *base;
struct coresight_device *csdev;
spinlock_t spinlock;
- local_t mode;
int cpu;
u8 arch;
u8 nr_pe;
* @spinlock: only one at a time pls.
* @chs: the channels accociated to this STM.
* @stm: structure associated to the generic STM interface.
- * @mode: this tracer's mode (enum cs_mode), i.e sysFS, or disabled.
* @traceid: value of the current ID for this component.
* @write_bytes: Maximus bytes this STM can write at a time.
* @stmsper: settings for register STMSPER.
spinlock_t spinlock;
struct channel_space chs;
struct stm_data stm;
- local_t mode;
u8 traceid;
u32 write_bytes;
u32 stmsper;
if (mode != CS_MODE_SYSFS)
return -EINVAL;
- val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
+ val = local_cmpxchg(&csdev->mode, CS_MODE_DISABLED, mode);
/* Someone is already using the tracer */
if (val)
* change its status. As such we can read the status here without
* fearing it will change under us.
*/
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+ if (local_read(&csdev->mode) == CS_MODE_SYSFS) {
spin_lock(&drvdata->spinlock);
stm_disable_hw(drvdata);
spin_unlock(&drvdata->spinlock);
pm_runtime_put(csdev->dev.parent);
- local_set(&drvdata->mode, CS_MODE_DISABLED);
+ local_set(&csdev->mode, CS_MODE_DISABLED);
dev_dbg(&csdev->dev, "STM tracing disabled\n");
}
}
{
struct stm_drvdata *drvdata = container_of(stm_data,
struct stm_drvdata, stm);
- if (!(drvdata && local_read(&drvdata->mode)))
+ if (!(drvdata && local_read(&drvdata->csdev->mode)))
return -EINVAL;
if (channel >= drvdata->numsp)
struct stm_drvdata, stm);
unsigned int stm_flags;
- if (!(drvdata && local_read(&drvdata->mode)))
+ if (!(drvdata && local_read(&drvdata->csdev->mode)))
return -EACCES;
if (channel >= drvdata->numsp)
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- if (!local_read(&drvdata->mode)) {
+ if (!local_read(&drvdata->csdev->mode)) {
val = drvdata->stmspscr;
} else {
spin_lock(&drvdata->spinlock);
spin_lock(&drvdata->spinlock);
drvdata->stmspscr = val;
- if (local_read(&drvdata->mode)) {
+ if (local_read(&drvdata->csdev->mode)) {
CS_UNLOCK(drvdata->base);
/* Process as per ARM's TRM recommendation */
stmsper = readl_relaxed(drvdata->base + STMSPER);
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
- if (!local_read(&drvdata->mode)) {
+ if (!local_read(&drvdata->csdev->mode)) {
val = drvdata->stmsper;
} else {
spin_lock(&drvdata->spinlock);
spin_lock(&drvdata->spinlock);
drvdata->stmsper = val;
- if (local_read(&drvdata->mode)) {
+ if (local_read(&drvdata->csdev->mode)) {
CS_UNLOCK(drvdata->base);
writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
CS_LOCK(drvdata->base);
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->mode == CS_MODE_DISABLED)
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_DISABLED)
goto out;
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
* When operating in sysFS mode the content of the buffer needs to be
* read before the TMC is disabled.
*/
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS)
tmc_etb_dump_hw(drvdata);
tmc_disable_hw(drvdata);
* sink is already enabled no memory is needed and the HW need not be
* touched.
*/
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&csdev->mode) == CS_MODE_SYSFS) {
atomic_inc(&csdev->refcnt);
goto out;
}
ret = tmc_etb_enable_hw(drvdata);
if (!ret) {
- drvdata->mode = CS_MODE_SYSFS;
+ local_set(&csdev->mode, CS_MODE_SYSFS);
atomic_inc(&csdev->refcnt);
} else {
/* Free up the buffer if we failed to enable */
* No need to continue if the ETB/ETF is already operated
* from sysFS.
*/
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&csdev->mode) == CS_MODE_SYSFS) {
ret = -EBUSY;
break;
}
if (!ret) {
/* Associate with monitored process. */
drvdata->pid = pid;
- drvdata->mode = CS_MODE_PERF;
+ local_set(&csdev->mode, CS_MODE_PERF);
atomic_inc(&csdev->refcnt);
}
} while (0);
}
/* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);
+ WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED);
tmc_etb_disable_hw(drvdata);
/* Dissociate from monitored process. */
drvdata->pid = -1;
- drvdata->mode = CS_MODE_DISABLED;
+ local_set(&csdev->mode, CS_MODE_DISABLED);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (atomic_read(&csdev->refcnt) == 0) {
ret = tmc_etf_enable_hw(drvdata);
if (!ret) {
- drvdata->mode = CS_MODE_SYSFS;
+ local_set(&csdev->mode, CS_MODE_SYSFS);
first_enable = true;
}
}
if (atomic_dec_return(&csdev->refcnt) == 0) {
tmc_etf_disable_hw(drvdata);
- drvdata->mode = CS_MODE_DISABLED;
+ local_set(&csdev->mode, CS_MODE_DISABLED);
last_disable = true;
}
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return 0;
/* This shouldn't happen */
- if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))
+ if (WARN_ON_ONCE(local_read(&csdev->mode) != CS_MODE_PERF))
return 0;
spin_lock_irqsave(&drvdata->spinlock, flags);
}
/* Don't interfere if operated from Perf */
- if (drvdata->mode == CS_MODE_PERF) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_PERF) {
ret = -EINVAL;
goto out;
}
}
/* Disable the TMC if need be */
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) {
/* There is no point in reading a TMC in HW FIFO mode */
mode = readl_relaxed(drvdata->base + TMC_MODE);
if (mode != TMC_MODE_CIRCULAR_BUFFER) {
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Re-enable the TMC if need be */
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) {
/* There is no point in reading a TMC in HW FIFO mode */
mode = readl_relaxed(drvdata->base + TMC_MODE);
if (mode != TMC_MODE_CIRCULAR_BUFFER) {
* When operating in sysFS mode the content of the buffer needs to be
* read before the TMC is disabled.
*/
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS)
tmc_etr_sync_sysfs_buf(drvdata);
tmc_disable_hw(drvdata);
spin_lock_irqsave(&drvdata->spinlock, flags);
}
- if (drvdata->reading || drvdata->mode == CS_MODE_PERF) {
+ if (drvdata->reading || local_read(&csdev->mode) == CS_MODE_PERF) {
ret = -EBUSY;
goto out;
}
* sink is already enabled no memory is needed and the HW need not be
* touched, even if the buffer size has changed.
*/
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&csdev->mode) == CS_MODE_SYSFS) {
atomic_inc(&csdev->refcnt);
goto out;
}
ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
if (!ret) {
- drvdata->mode = CS_MODE_SYSFS;
+ local_set(&csdev->mode, CS_MODE_SYSFS);
atomic_inc(&csdev->refcnt);
}
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Don't use this sink if it is already claimed by sysFS */
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&csdev->mode) == CS_MODE_SYSFS) {
rc = -EBUSY;
goto unlock_out;
}
if (!rc) {
/* Associate with monitored process. */
drvdata->pid = pid;
- drvdata->mode = CS_MODE_PERF;
+ local_set(&csdev->mode, CS_MODE_PERF);
drvdata->perf_buf = etr_perf->etr_buf;
atomic_inc(&csdev->refcnt);
}
}
/* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);
+ WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED);
tmc_etr_disable_hw(drvdata);
/* Dissociate from monitored process. */
drvdata->pid = -1;
- drvdata->mode = CS_MODE_DISABLED;
+ local_set(&csdev->mode, CS_MODE_DISABLED);
/* Reset perf specific data */
drvdata->perf_buf = NULL;
}
/* Disable the TMC if we are trying to read from a running session. */
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS)
__tmc_etr_disable_hw(drvdata);
drvdata->reading = true;
spin_lock_irqsave(&drvdata->spinlock, flags);
/* RE-enable the TMC if need be */
- if (drvdata->mode == CS_MODE_SYSFS) {
+ if (local_read(&drvdata->csdev->mode) == CS_MODE_SYSFS) {
/*
* The trace run will continue with the same allocated trace
* buffer. Since the tracer is still enabled drvdata::buf can't
* @size: trace buffer size for this TMC (common for all modes).
* @max_burst_size: The maximum burst size that can be initiated by
* TMC-ETR on AXI bus.
- * @mode: how this TMC is being used.
* @config_type: TMC variant, must be of type @tmc_config_type.
* @memwidth: width of the memory interface databus, in bytes.
* @trigger_cntr: amount of words to store after a trigger.
u32 len;
u32 size;
u32 max_burst_size;
- u32 mode;
enum tmc_config_type config_type;
enum tmc_mem_intf_width memwidth;
u32 trigger_cntr;
{
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
- if (drvdata->mode != CS_MODE_DISABLED)
+ if (local_read(&csdev->mode) != CS_MODE_DISABLED)
return;
smb_enable_hw(drvdata);
- drvdata->mode = CS_MODE_SYSFS;
+ local_set(&csdev->mode, CS_MODE_SYSFS);
}
static int smb_enable_perf(struct coresight_device *csdev, void *data)
if (drvdata->pid == -1) {
smb_enable_hw(drvdata);
drvdata->pid = pid;
- drvdata->mode = CS_MODE_PERF;
+ local_set(&csdev->mode, CS_MODE_PERF);
}
return 0;
return -EBUSY;
/* Do nothing, the SMB is already enabled as other mode */
- if (drvdata->mode != CS_MODE_DISABLED && drvdata->mode != mode)
+ if (local_read(&csdev->mode) != CS_MODE_DISABLED &&
+ local_read(&csdev->mode) != mode)
return -EBUSY;
switch (mode) {
return -EBUSY;
/* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);
+ WARN_ON_ONCE(local_read(&csdev->mode) == CS_MODE_DISABLED);
smb_disable_hw(drvdata);
/* Dissociate from the target process. */
drvdata->pid = -1;
- drvdata->mode = CS_MODE_DISABLED;
+ local_set(&csdev->mode, CS_MODE_DISABLED);
dev_dbg(&csdev->dev, "Ultrasoc SMB disabled\n");
return 0;
* @reading: Synchronise user space access to SMB buffer.
* @pid: Process ID of the process being monitored by the
* session that is using this component.
- * @mode: How this SMB is being used, perf mode or sysfs mode.
*/
struct smb_drv_data {
void __iomem *base;
spinlock_t spinlock;
bool reading;
pid_t pid;
- enum cs_mode mode;
};
#endif
* by @coresight_ops.
* @access: Device i/o access abstraction for this device.
* @dev: The device entity associated to this component.
+ * @mode: This tracer's mode, i.e sysFS, Perf or disabled. This is
+ * actually an 'enum cs_mode', but is stored in an atomic type.
+ * This is always accessed through local_read() and local_set(),
+ * but wherever it's done from within the Coresight device's lock,
+ * a non-atomic read would also work.
* @refcnt: keep track of what is in use.
* @orphan: true if the component has connections that haven't been linked.
* @enable: 'true' if component is currently part of an active path.
const struct coresight_ops *ops;
struct csdev_access access;
struct device dev;
+ local_t mode;
atomic_t refcnt;
bool orphan;
bool enable;