Unverified Commit 5b94c94c authored by Breno Leitao's avatar Breno Leitao Committed by Mark Brown
Browse files

spi: tegra210-quad: Fix false positive WARN on interrupt timeout with transfer complete



The WARN_ON_ONCE/WARN_ON fired unconditionally on any completion
timeout, including the recoverable case where the interrupt was lost but
the hardware actually finished the transfer. This produced a noisy splat
with a full call trace even though the driver successfully recovered via
tegra_qspi_handle_timeout().

Since tegra210 uses threaded interrupts, the transfer completion can be
signaled before the interrupt fires, making this false positive case
common in practice.

Almost all the hosts I sysadmin in my fleet produce the following splat:

	WARNING: CPU: 47 PID: 844 at drivers/spi/spi-tegra210-quad.c:1226 tegra_qspi_transfer_one_message+0x8a4/0xba8
	....
	tegra-qspi NVDA1513:00: QSPI interrupt timeout, but transfer complete

Move WARN_ON_ONCE/WARN_ON to fire only on real unrecoverable timeouts,
i.e., when tegra_qspi_handle_timeout() confirms the hardware did NOT
complete. This makes the warning actionable instead of just polluting
the metrics.

Signed-off-by: default avatarBreno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260408-tegra_warn-v1-1-669a3bc74d77@debian.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6dd13023
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1223,7 +1223,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
					(&tqspi->xfer_completion,
					QSPI_DMA_TIMEOUT);

			if (WARN_ON_ONCE(ret == 0)) {
			if (ret == 0) {
				/*
				 * Check if hardware completed the transfer
				 * even though interrupt was lost or delayed.
@@ -1232,6 +1232,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
				ret = tegra_qspi_handle_timeout(tqspi);
				if (ret < 0) {
					/* Real timeout - clean up and fail */
					WARN_ON_ONCE(1);
					dev_err(tqspi->dev, "transfer timeout\n");

					/* Abort transfer by resetting pio/dma bit */
@@ -1340,7 +1341,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,

		ret = wait_for_completion_timeout(&tqspi->xfer_completion,
						  QSPI_DMA_TIMEOUT);
		if (WARN_ON(ret == 0)) {
		if (ret == 0) {
			/*
			 * Check if hardware completed the transfer even though
			 * interrupt was lost or delayed. If so, process the
@@ -1349,6 +1350,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,
			ret = tegra_qspi_handle_timeout(tqspi);
			if (ret < 0) {
				/* Real timeout - clean up and fail */
				WARN_ON(1);
				dev_err(tqspi->dev, "transfer timeout\n");

				if (tqspi->is_curr_dma_xfer)