spi: Fixes for v6.6
A couple of fixes for the sun6i driver, the patch to reduce DMA RX to single byte width all the time is *hopefully* excessively cautious but it's unclear which SoCs are affected so the fix just covers everything for safety. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmT5wQ0ACgkQJNaLcl1U h9Bltgf/T7tViGF1+g0fUx7Nlju+h8Hg3qBhlE+VKwRO6/qjBczT4ny4nkiej+CK IapuEDul+F56Cy4/dgyFQkICTCm7qGev+r7Oya0OCWqAiXif5fz/zfxc4rHUzRA9 lZrdWrYNxhlAqcDu80G00nh5Gx5UCpTHEriWJQUQ0oxXGQoPRPW2WczMsksF6QLs gnqr7hhIWzSvj0OOHVWi6a1iOMVgw0ICEgUF6TSoDsMOzvi6c1WVnCLZaE6udWhv 0wwOBzH1YBbwhfK/RdjUcSfHIy/jI2Gs7BnrUWviIfQSCb90V9YvAGlgusJAR4Ks Y5UM3d8pVxQg5tW75IFjMt/fic6Rfg== =HZqv -----END PGP SIGNATURE----- Merge tag 'spi-fix-v6.6-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi fixes from Mark Brown: "A couple of fixes for the sun6i driver. The patch to reduce DMA RX to single byte width all the time is *hopefully* excessively cautious but it's unclear which SoCs are affected so the fix just covers everything for safety" * tag 'spi-fix-v6.6-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: sun6i: fix race between DMA RX transfer completion and RX FIFO drain spi: sun6i: reduce DMA RX transfer width to single byte
This commit is contained in:
commit
32904dec06
|
@ -106,6 +106,7 @@ struct sun6i_spi {
|
|||
struct reset_control *rstc;
|
||||
|
||||
struct completion done;
|
||||
struct completion dma_rx_done;
|
||||
|
||||
const u8 *tx_buf;
|
||||
u8 *rx_buf;
|
||||
|
@ -200,6 +201,13 @@ static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
|
|||
return SUN6I_MAX_XFER_SIZE - 1;
|
||||
}
|
||||
|
||||
static void sun6i_spi_dma_rx_cb(void *param)
|
||||
{
|
||||
struct sun6i_spi *sspi = param;
|
||||
|
||||
complete(&sspi->dma_rx_done);
|
||||
}
|
||||
|
||||
static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
|
@ -211,7 +219,7 @@ static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
|
|||
struct dma_slave_config rxconf = {
|
||||
.direction = DMA_DEV_TO_MEM,
|
||||
.src_addr = sspi->dma_addr_rx,
|
||||
.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
|
||||
.src_maxburst = 8,
|
||||
};
|
||||
|
||||
|
@ -224,6 +232,8 @@ static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
|
|||
DMA_PREP_INTERRUPT);
|
||||
if (!rxdesc)
|
||||
return -EINVAL;
|
||||
rxdesc->callback_param = sspi;
|
||||
rxdesc->callback = sun6i_spi_dma_rx_cb;
|
||||
}
|
||||
|
||||
txdesc = NULL;
|
||||
|
@ -279,6 +289,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
|
|||
return -EINVAL;
|
||||
|
||||
reinit_completion(&sspi->done);
|
||||
reinit_completion(&sspi->dma_rx_done);
|
||||
sspi->tx_buf = tfr->tx_buf;
|
||||
sspi->rx_buf = tfr->rx_buf;
|
||||
sspi->len = tfr->len;
|
||||
|
@ -479,6 +490,22 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
|
|||
start = jiffies;
|
||||
timeout = wait_for_completion_timeout(&sspi->done,
|
||||
msecs_to_jiffies(tx_time));
|
||||
|
||||
if (!use_dma) {
|
||||
sun6i_spi_drain_fifo(sspi);
|
||||
} else {
|
||||
if (timeout && rx_len) {
|
||||
/*
|
||||
* Even though RX on the peripheral side has finished
|
||||
* RX DMA might still be in flight
|
||||
*/
|
||||
timeout = wait_for_completion_timeout(&sspi->dma_rx_done,
|
||||
timeout);
|
||||
if (!timeout)
|
||||
dev_warn(&master->dev, "RX DMA timeout\n");
|
||||
}
|
||||
}
|
||||
|
||||
end = jiffies;
|
||||
if (!timeout) {
|
||||
dev_warn(&master->dev,
|
||||
|
@ -506,7 +533,6 @@ static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
|
|||
/* Transfer complete */
|
||||
if (status & SUN6I_INT_CTL_TC) {
|
||||
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
|
||||
sun6i_spi_drain_fifo(sspi);
|
||||
complete(&sspi->done);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -665,6 +691,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
init_completion(&sspi->done);
|
||||
init_completion(&sspi->dma_rx_done);
|
||||
|
||||
sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(sspi->rstc)) {
|
||||
|
|
Loading…
Reference in New Issue