From 82295bc0d192d7e35e0568b18ca66da2c3058fd5 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Mon, 27 Jun 2022 10:38:45 +0900 Subject: [PATCH] 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 Link: https://lore.kernel.org/r/20220627013845.138350-1-chanho61.park@samsung.com Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 499c56d..302c1d4 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; -- 2.7.4