Skip to content

Commit 32904de

Browse files
committed
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
2 parents 0c02183 + 1f11f42 commit 32904de

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

drivers/spi/spi-sun6i.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct sun6i_spi {
106106
struct reset_control *rstc;
107107

108108
struct completion done;
109+
struct completion dma_rx_done;
109110

110111
const u8 *tx_buf;
111112
u8 *rx_buf;
@@ -200,6 +201,13 @@ static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
200201
return SUN6I_MAX_XFER_SIZE - 1;
201202
}
202203

204+
static void sun6i_spi_dma_rx_cb(void *param)
205+
{
206+
struct sun6i_spi *sspi = param;
207+
208+
complete(&sspi->dma_rx_done);
209+
}
210+
203211
static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
204212
struct spi_transfer *tfr)
205213
{
@@ -211,7 +219,7 @@ static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
211219
struct dma_slave_config rxconf = {
212220
.direction = DMA_DEV_TO_MEM,
213221
.src_addr = sspi->dma_addr_rx,
214-
.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
222+
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
215223
.src_maxburst = 8,
216224
};
217225

@@ -224,6 +232,8 @@ static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
224232
DMA_PREP_INTERRUPT);
225233
if (!rxdesc)
226234
return -EINVAL;
235+
rxdesc->callback_param = sspi;
236+
rxdesc->callback = sun6i_spi_dma_rx_cb;
227237
}
228238

229239
txdesc = NULL;
@@ -279,6 +289,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
279289
return -EINVAL;
280290

281291
reinit_completion(&sspi->done);
292+
reinit_completion(&sspi->dma_rx_done);
282293
sspi->tx_buf = tfr->tx_buf;
283294
sspi->rx_buf = tfr->rx_buf;
284295
sspi->len = tfr->len;
@@ -479,6 +490,22 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
479490
start = jiffies;
480491
timeout = wait_for_completion_timeout(&sspi->done,
481492
msecs_to_jiffies(tx_time));
493+
494+
if (!use_dma) {
495+
sun6i_spi_drain_fifo(sspi);
496+
} else {
497+
if (timeout && rx_len) {
498+
/*
499+
* Even though RX on the peripheral side has finished
500+
* RX DMA might still be in flight
501+
*/
502+
timeout = wait_for_completion_timeout(&sspi->dma_rx_done,
503+
timeout);
504+
if (!timeout)
505+
dev_warn(&master->dev, "RX DMA timeout\n");
506+
}
507+
}
508+
482509
end = jiffies;
483510
if (!timeout) {
484511
dev_warn(&master->dev,
@@ -506,7 +533,6 @@ static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
506533
/* Transfer complete */
507534
if (status & SUN6I_INT_CTL_TC) {
508535
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
509-
sun6i_spi_drain_fifo(sspi);
510536
complete(&sspi->done);
511537
return IRQ_HANDLED;
512538
}
@@ -665,6 +691,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
665691
}
666692

667693
init_completion(&sspi->done);
694+
init_completion(&sspi->dma_rx_done);
668695

669696
sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
670697
if (IS_ERR(sspi->rstc)) {

0 commit comments

Comments
 (0)