diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2018-09-05 10:49:39 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-13 09:09:27 +0200 |
commit | 6ea058b70a290b02f1d8a15f6503928cc21a85e1 (patch) | |
tree | b3c4e841fb32a156be2fb2d1fb85d844a12b4505 /drivers/spi | |
parent | 5a5b2a2bd334aedf3aa8520fc3b37484a72be5d5 (diff) | |
download | linux-stable-6ea058b70a290b02f1d8a15f6503928cc21a85e1.tar.gz linux-stable-6ea058b70a290b02f1d8a15f6503928cc21a85e1.tar.bz2 linux-stable-6ea058b70a290b02f1d8a15f6503928cc21a85e1.zip |
spi: rspi: Fix interrupted DMA transfers
commit 8dbbaa47b96f6ea5f09f922b4effff3c505cd8cf upstream.
When interrupted, wait_event_interruptible_timeout() returns
-ERESTARTSYS, and the SPI transfer in progress will fail, as expected:
m25p80 spi0.0: SPI transfer failed: -512
spi_master spi0: failed to transfer one message from queue
However, as the underlying DMA transfers may not have completed, all
subsequent SPI transfers may start to fail:
spi_master spi0: receive timeout
qspi_transfer_out_in() returned -110
m25p80 spi0.0: SPI transfer failed: -110
spi_master spi0: failed to transfer one message from queue
Fix this by calling dmaengine_terminate_all() not only for timeouts, but
also for errors.
This can be reproduced on r8a7991/koelsch, using "hd /dev/mtd0" followed
by CTRL-C.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-rspi.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 54bb0faec155..4ee0bfa86e4a 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -538,11 +538,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ret = wait_event_interruptible_timeout(rspi->wait, rspi->dma_callbacked, HZ); - if (ret > 0 && rspi->dma_callbacked) + if (ret > 0 && rspi->dma_callbacked) { ret = 0; - else if (!ret) { - dev_err(&rspi->master->dev, "DMA timeout\n"); - ret = -ETIMEDOUT; + } else { + if (!ret) { + dev_err(&rspi->master->dev, "DMA timeout\n"); + ret = -ETIMEDOUT; + } if (tx) dmaengine_terminate_all(rspi->master->dma_tx); if (rx) |