Skip to content

Commit 551060e

Browse files
Vishwaroop Agregkh
authored andcommitted
spi: tegra210-quad: Fix timeout handling
[ Upstream commit b4e002d ] When the CPU that the QSPI interrupt handler runs on (typically CPU 0) is excessively busy, it can lead to rare cases of the IRQ thread not running before the transfer timeout is reached. While handling the timeouts, any pending transfers are cleaned up and the message that they correspond to is marked as failed, which leaves the curr_xfer field pointing at stale memory. To avoid this, clear curr_xfer to NULL upon timeout and check for this condition when the IRQ thread is finally run. While at it, also make sure to clear interrupts on failure so that new interrupts can be run. A better, more involved, fix would move the interrupt clearing into a hard IRQ handler. Ideally we would also want to signal that the IRQ thread no longer needs to be run after the timeout is hit to avoid the extra check for a valid transfer. Fixes: 921fc18 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Vishwaroop A <va@nvidia.com> Link: https://patch.msgid.link/20251028155703.4151791-2-va@nvidia.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5a0060d commit 551060e

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

drivers/spi/spi-tegra210-quad.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,10 @@ static void tegra_qspi_handle_error(struct tegra_qspi *tqspi)
999999
dev_err(tqspi->dev, "error in transfer, fifo status 0x%08x\n", tqspi->status_reg);
10001000
tegra_qspi_dump_regs(tqspi);
10011001
tegra_qspi_flush_fifos(tqspi, true);
1002-
if (device_reset(tqspi->dev) < 0)
1002+
if (device_reset(tqspi->dev) < 0) {
10031003
dev_warn_once(tqspi->dev, "device reset failed\n");
1004+
tegra_qspi_mask_clear_irq(tqspi);
1005+
}
10041006
}
10051007

10061008
static void tegra_qspi_transfer_end(struct spi_device *spi)
@@ -1145,9 +1147,11 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
11451147
}
11461148

11471149
/* Reset controller if timeout happens */
1148-
if (device_reset(tqspi->dev) < 0)
1150+
if (device_reset(tqspi->dev) < 0) {
11491151
dev_warn_once(tqspi->dev,
11501152
"device reset failed\n");
1153+
tegra_qspi_mask_clear_irq(tqspi);
1154+
}
11511155
ret = -EIO;
11521156
goto exit;
11531157
}
@@ -1169,11 +1173,13 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
11691173
tegra_qspi_transfer_end(spi);
11701174
spi_transfer_delay_exec(xfer);
11711175
}
1176+
tqspi->curr_xfer = NULL;
11721177
transfer_phase++;
11731178
}
11741179
ret = 0;
11751180

11761181
exit:
1182+
tqspi->curr_xfer = NULL;
11771183
msg->status = ret;
11781184

11791185
return ret;
@@ -1257,6 +1263,8 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,
12571263
msg->actual_length += xfer->len + dummy_bytes;
12581264

12591265
complete_xfer:
1266+
tqspi->curr_xfer = NULL;
1267+
12601268
if (ret < 0) {
12611269
tegra_qspi_transfer_end(spi);
12621270
spi_transfer_delay_exec(xfer);
@@ -1353,6 +1361,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_qspi *tqspi)
13531361
tegra_qspi_calculate_curr_xfer_param(tqspi, t);
13541362
tegra_qspi_start_cpu_based_transfer(tqspi, t);
13551363
exit:
1364+
tqspi->curr_xfer = NULL;
13561365
spin_unlock_irqrestore(&tqspi->lock, flags);
13571366
return IRQ_HANDLED;
13581367
}
@@ -1436,6 +1445,15 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data)
14361445
{
14371446
struct tegra_qspi *tqspi = context_data;
14381447

1448+
/*
1449+
* Occasionally the IRQ thread takes a long time to wake up (usually
1450+
* when the CPU that it's running on is excessively busy) and we have
1451+
* already reached the timeout before and cleaned up the timed out
1452+
* transfer. Avoid any processing in that case and bail out early.
1453+
*/
1454+
if (!tqspi->curr_xfer)
1455+
return IRQ_NONE;
1456+
14391457
tqspi->status_reg = tegra_qspi_readl(tqspi, QSPI_FIFO_STATUS);
14401458

14411459
if (tqspi->cur_direction & DATA_DIR_TX)

0 commit comments

Comments
 (0)