[PATCH] spi: s3c64xx: move dma_release_channel to unprepare

Chanho Park chanho61.park at samsung.com
Sun Jun 26 18:38:45 PDT 2022


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 at samsung.com>
---
 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 819b660dae82..7f0faf0d75d9 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.36.1




More information about the linux-arm-kernel mailing list