/* Wait for TMCSReady bit to be set */
rc = tmc_wait_for_tmcready(drvdata); if (rc) {
dev_err(&drvdata->csdev->dev, "Failed to enable: TMC not ready\n");
CS_LOCK(drvdata->base); return rc;
}
staticint __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{ int rc = 0;
CS_UNLOCK(drvdata->base);
/* Wait for TMCSReady bit to be set */
rc = tmc_wait_for_tmcready(drvdata); if (rc) {
dev_err(&drvdata->csdev->dev, "Failed to enable : TMC is not ready\n");
CS_LOCK(drvdata->base); return rc;
}
/* Adjust the len to available size @pos */ if (pos + actual > drvdata->len)
actual = drvdata->len - pos; if (actual > 0)
*bufpp = drvdata->buf + pos; return actual;
}
staticint tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
{ int ret = 0; bool used = false; char *buf = NULL; unsignedlong flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
raw_spin_lock_irqsave(&drvdata->spinlock, flags); do {
ret = -EINVAL; if (drvdata->reading) break; /* *NoneedtocontinueiftheETB/ETFisalreadyoperated *fromsysFS.
*/ if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
ret = -EBUSY; break;
}
/* Get a handle on the pid of the process to monitor */
pid = buf->pid;
if (drvdata->pid != -1 && drvdata->pid != pid) {
ret = -EBUSY; break;
}
ret = tmc_set_etf_buffer(csdev, handle); if (ret) break;
switch (mode) { case CS_MODE_SYSFS:
ret = tmc_enable_etf_sink_sysfs(csdev); break; case CS_MODE_PERF:
ret = tmc_enable_etf_sink_perf(csdev, data); break; /* We shouldn't be here */ default:
ret = -EINVAL; break;
}
if (drvdata->reading) {
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY;
}
csdev->refcnt--; if (csdev->refcnt) {
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY;
}
/* Complain if we (somehow) got out of sync */
WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
tmc_etb_disable_hw(drvdata); /* Dissociate from monitored process. */
drvdata->pid = -1;
coresight_set_mode(csdev, CS_MODE_DISABLED);
cur = buf->cur;
offset = buf->offset;
barrier = coresight_barrier_pkt;
/* for every byte to read */ for (i = 0; i < to_read; i += 4) {
buf_ptr = buf->data_pages[cur] + offset;
*buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
if (lost && i < CORESIGHT_BARRIER_PKT_SIZE) {
*buf_ptr = *barrier;
barrier++;
}
offset += 4; if (offset >= PAGE_SIZE) {
offset = 0;
cur++; /* wrap around at the end of the buffer */
cur &= buf->nr_pages - 1;
}
}
/* *Insnapshotmodewesimplyincrementtheheadbythenumberofbyte *thatwerewritten.Userspacewillfigureouthowmanybytestoget *fromtheAUXbufferbasedonthepositionofthehead.
*/ if (buf->snapshot)
handle->head += to_read;
/* Make sure we have valid reserved memory */ if (!tmc_has_reserved_buffer(drvdata) ||
!tmc_has_crash_mdata_buffer(drvdata)) return0;
tmc_crashdata_set_invalid(drvdata);
CS_UNLOCK(drvdata->base);
/* Proceed only if ETF is enabled or configured as sink */
val = readl(drvdata->base + TMC_CTL); if (!(val & TMC_CTL_CAPT_EN)) goto out;
val = readl(drvdata->base + TMC_MODE); if (val != TMC_MODE_CIRCULAR_BUFFER) goto out;
val = readl(drvdata->base + TMC_FFSR); /* Do manual flush and stop only if its not auto-stopped */ if (!(val & TMC_FFSR_FT_STOPPED)) {
dev_dbg(&csdev->dev, "%s: Triggering manual flush\n", __func__);
tmc_flush_and_stop(drvdata);
} else
tmc_wait_for_tmcready(drvdata);
/* Sync registers from hardware to metadata region */
mdata->tmc_sts = readl(drvdata->base + TMC_STS);
mdata->tmc_mode = readl(drvdata->base + TMC_MODE);
mdata->tmc_ffcr = readl(drvdata->base + TMC_FFCR);
mdata->tmc_ffsr = readl(drvdata->base + TMC_FFSR);
/* Sync Internal SRAM to reserved trace buffer region */
drvdata->buf = drvdata->resrv_buf.vaddr;
tmc_etb_dump_hw(drvdata); /* Store as per RSZ register convention */
mdata->tmc_ram_size = drvdata->len >> 2;
int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
{ enum tmc_mode mode; int ret = 0; unsignedlong flags;
/* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
drvdata->config_type != TMC_CONFIG_TYPE_ETF)) return -EINVAL;
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
ret = -EBUSY; goto out;
}
/* Don't interfere if operated from Perf */ if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF) {
ret = -EINVAL; goto out;
}
/* If drvdata::buf is NULL the trace data has been read already */ if (drvdata->buf == NULL) {
ret = -EINVAL; goto out;
}
/* Disable the TMC if need be */ if (coresight_get_mode(drvdata->csdev) == 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) {
ret = -EINVAL; goto out;
}
__tmc_etb_disable_hw(drvdata);
}
/* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
drvdata->config_type != TMC_CONFIG_TYPE_ETF)) return -EINVAL;
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
/* Re-enable the TMC if need be */ if (coresight_get_mode(drvdata->csdev) == 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) {
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EINVAL;
} /* *Thetracerunwillcontinuewiththesameallocatedtrace *buffer.Assuchzero-outthebuffersothatwedon'tend *upwithstaledata. * *Sincethetracerisstillenableddrvdata::buf *can'tbeNULL.
*/
memset(drvdata->buf, 0, drvdata->size); /* *IgnorefailurestoenabletheTMCtomakesure,wedon't *leavetheTMCina"reading"state.
*/
__tmc_etb_enable_hw(drvdata);
} else { /* *TheETB/ETFisnottracingandthebufferwasjustread. *Assuchpreparetofreethetracebuffer.
*/
buf = drvdata->buf;
drvdata->buf = NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.