mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-06 21:14:18 +00:00
spi: s3c64xx: move dma_release_channel to unprepare
This fixes the sequence of dma_release_channel. Since commitf52b03c707
("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:f52b03c707
("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>
This commit is contained in:
parent
917e43de2a
commit
82295bc0d1
@ -373,6 +373,24 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
|
|||||||
return 0;
|
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,
|
static bool s3c64xx_spi_can_dma(struct spi_master *master,
|
||||||
struct spi_device *spi,
|
struct spi_device *spi,
|
||||||
struct spi_transfer *xfer)
|
struct spi_transfer *xfer)
|
||||||
@ -804,14 +822,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
|
|||||||
xfer->len = origin_len;
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,6 +1138,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
|
|||||||
master->setup = s3c64xx_spi_setup;
|
master->setup = s3c64xx_spi_setup;
|
||||||
master->cleanup = s3c64xx_spi_cleanup;
|
master->cleanup = s3c64xx_spi_cleanup;
|
||||||
master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
|
master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
|
||||||
|
master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
|
||||||
master->prepare_message = s3c64xx_spi_prepare_message;
|
master->prepare_message = s3c64xx_spi_prepare_message;
|
||||||
master->transfer_one = s3c64xx_spi_transfer_one;
|
master->transfer_one = s3c64xx_spi_transfer_one;
|
||||||
master->num_chipselect = sci->num_cs;
|
master->num_chipselect = sci->num_cs;
|
||||||
|
Loading…
Reference in New Issue
Block a user