summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-s3c64xx.c
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2022-06-27 10:38:45 +0900
committerMark Brown <broonie@kernel.org>2022-06-27 23:26:54 +0100
commit82295bc0d192d7e35e0568b18ca66da2c3058fd5 (patch)
tree210c03b0361dcc34f39a283de8fa3b9fee0c6954 /drivers/spi/spi-s3c64xx.c
parent917e43de2a56d9b82576f1cc94748261f1988458 (diff)
spi: s3c64xx: move dma_release_channel to unprepare
This fixes the sequence of dma_release_channel. Since commit f52b03c70744 ("spi: s3c64xx: requests spi-dma channel only during data transfer"), dma_release_channel has been located in the s3c64xx_spi_transfer_one but this makes invalid return of can_dma callback. __spi_unmap_msg will check whether the request is requested by dma or not via can_dma callback. When it is calling to check it, the channels will be already released at the end of s3c64xx_spi_transfer_one so the callback function will return always "false". So, they can't be unmapped from __spi_unmap_msg call. To fix this, we need to add unprepare_transfer_hardware callback and move the dma_release_channel from s3c64xx_spi_transfer_one to there. Fixes: f52b03c70744 ("spi: s3c64xx: requests spi-dma channel only during data transfer") Signed-off-by: Chanho Park <chanho61.park@samsung.com> Link: https://lore.kernel.org/r/20220627013845.138350-1-chanho61.park@samsung.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-s3c64xx.c')
-rw-r--r--drivers/spi/spi-s3c64xx.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 499c56dd875e..302c1d4a28b1 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -373,6 +373,24 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
return 0;
}
+static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
+{
+ struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
+
+ if (is_polling(sdd))
+ return 0;
+
+ /* Releases DMA channels if they are allocated */
+ if (sdd->rx_dma.ch && sdd->tx_dma.ch) {
+ dma_release_channel(sdd->rx_dma.ch);
+ dma_release_channel(sdd->tx_dma.ch);
+ sdd->rx_dma.ch = 0;
+ sdd->tx_dma.ch = 0;
+ }
+
+ return 0;
+}
+
static bool s3c64xx_spi_can_dma(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
@@ -804,14 +822,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
xfer->len = origin_len;
}
- /* Releases DMA channels after data transfer is completed */
- if (sdd->rx_dma.ch && sdd->tx_dma.ch) {
- dma_release_channel(sdd->rx_dma.ch);
- dma_release_channel(sdd->tx_dma.ch);
- sdd->rx_dma.ch = NULL;
- sdd->tx_dma.ch = NULL;
- }
-
return status;
}
@@ -1128,6 +1138,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->setup = s3c64xx_spi_setup;
master->cleanup = s3c64xx_spi_cleanup;
master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
+ master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
master->prepare_message = s3c64xx_spi_prepare_message;
master->transfer_one = s3c64xx_spi_transfer_one;
master->num_chipselect = sci->num_cs;