Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d44cc18 authored by Suzuki K Poulose's avatar Suzuki K Poulose Committed by Yabin Cui
Browse files

UPSTREAM: coresight: tmc-etr: Refactor for handling errors



(Upstream commit 6276f9cba50f77c5b51b581c11b74a51a3f9e040).

Refactor the tmc-etr enable operation to make it easier to
handle errors in enabling the hardware. We need to make
sure that the buffer is compatible with the ETR. This
patch re-arranges to make the error handling easier, by
deferring the hardware enablement until all the errors
are checked. This also avoids turning the CATU on/off
during a sysfs read session.

Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>

Bug: 140266694
Change-Id: If37267ec025df465507bf9e592a512058579914d
Signed-off-by: default avatarYabin Cui <yabinc@google.com>
parent ba7f8c66
Loading
Loading
Loading
Loading
+43 −24
Original line number Diff line number Diff line
@@ -918,21 +918,10 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata)
		tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset);
}

static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
			      struct etr_buf *etr_buf)
static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
{
	u32 axictl, sts;

	/* Callers should provide an appropriate buffer for use */
	if (WARN_ON(!etr_buf || drvdata->etr_buf))
		return;
	drvdata->etr_buf = etr_buf;

	/*
	 * If this ETR is connected to a CATU, enable it before we turn
	 * this on
	 */
	tmc_etr_enable_catu(drvdata);
	struct etr_buf *etr_buf = drvdata->etr_buf;

	CS_UNLOCK(drvdata->base);

@@ -952,11 +941,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
		axictl |= TMC_AXICTL_ARCACHE_OS;
	}

	if (etr_buf->mode == ETR_MODE_ETR_SG) {
		if (WARN_ON(!tmc_etr_has_cap(drvdata, TMC_ETR_SG)))
			return;
	if (etr_buf->mode == ETR_MODE_ETR_SG)
		axictl |= TMC_AXICTL_SCT_GAT_MODE;
	}

	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
	tmc_write_dba(drvdata, etr_buf->hwaddr);
@@ -982,6 +968,32 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
	CS_LOCK(drvdata->base);
}

static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
			     struct etr_buf *etr_buf)
{
	/* Callers should provide an appropriate buffer for use */
	if (WARN_ON(!etr_buf))
		return -EINVAL;

	if ((etr_buf->mode == ETR_MODE_ETR_SG) &&
	    WARN_ON(!tmc_etr_has_cap(drvdata, TMC_ETR_SG)))
		return -EINVAL;

	if (WARN_ON(drvdata->etr_buf))
		return -EBUSY;

	/* Set the buffer for the session */
	drvdata->etr_buf = etr_buf;
	/*
	 * If this ETR is connected to a CATU, enable it before we turn
	 * this on.
	 */
	tmc_etr_enable_catu(drvdata);

	__tmc_etr_enable_hw(drvdata);
	return 0;
}

/*
 * Return the available trace data in the buffer (starts at etr_buf->offset,
 * limited by etr_buf->len) from @pos, with a maximum limit of @len,
@@ -1037,7 +1049,7 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata)
	}
}

static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
{
	CS_UNLOCK(drvdata->base);

@@ -1053,6 +1065,11 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)

	CS_LOCK(drvdata->base);

}

static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
{
	__tmc_etr_disable_hw(drvdata);
	/* Disable CATU device if this ETR is connected to one */
	tmc_etr_disable_catu(drvdata);
	/* Reset the ETR buf used by hardware */
@@ -1111,8 +1128,9 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
		drvdata->sysfs_buf = new_buf;
	}

	ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
	if (!ret)
		drvdata->mode = CS_MODE_SYSFS;
	tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
out:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

@@ -1342,8 +1360,9 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)

	etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf);
	drvdata->perf_data = etr_perf;
	rc = tmc_etr_enable_hw(drvdata, etr_perf->etr_buf);
	if (!rc)
		drvdata->mode = CS_MODE_PERF;
	tmc_etr_enable_hw(drvdata, etr_perf->etr_buf);

unlock_out:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1425,7 +1444,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)

	/* Disable the TMC if we are trying to read from a running session. */
	if (drvdata->mode == CS_MODE_SYSFS)
		tmc_etr_disable_hw(drvdata);
		__tmc_etr_disable_hw(drvdata);

	drvdata->reading = true;
out:
@@ -1452,7 +1471,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
		 * buffer. Since the tracer is still enabled drvdata::buf can't
		 * be NULL.
		 */
		tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
		__tmc_etr_enable_hw(drvdata);
	} else {
		/*
		 * The ETR is not tracing and the buffer was just read.