| From: Geert Uytterhoeven <geert+renesas@glider.be> |
| Date: Wed, 5 Sep 2018 10:49:39 +0200 |
| Subject: 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> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/spi/spi-rspi.c | 10 ++++++---- |
| 1 file changed, 6 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/spi/spi-rspi.c |
| +++ b/drivers/spi/spi-rspi.c |
| @@ -538,11 +538,13 @@ static int rspi_dma_transfer(struct rspi |
| |
| 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) |