Skip to content

Commit 8070954

Browse files
mitabroonie
authored andcommitted
spi: omap2-mcspi: Undo broken fix for dma transfer of vmalloced buffer
This reverts commit 3525e0a. The DMA transfer for RX buffer was not handled correctly in this change. The actual transfer length for DMA RX can be less than xfer->len in the specific condition and the last words will be filled after the DMA completion, but the commit doesn't consider it and the dmaengine is started with rx_sg mapped by spi core. The solution for this at least requires more lines than this commit has inserted. So revert it for now. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent bf16200 commit 8070954

File tree

1 file changed

+45
-17
lines changed

1 file changed

+45
-17
lines changed

drivers/spi/spi-omap2-mcspi.c

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,16 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
423423

424424
if (mcspi_dma->dma_tx) {
425425
struct dma_async_tx_descriptor *tx;
426+
struct scatterlist sg;
426427

427428
dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
428429

429-
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl,
430-
xfer->tx_sg.nents, DMA_MEM_TO_DEV,
431-
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
430+
sg_init_table(&sg, 1);
431+
sg_dma_address(&sg) = xfer->tx_dma;
432+
sg_dma_len(&sg) = xfer->len;
433+
434+
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1,
435+
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
432436
if (tx) {
433437
tx->callback = omap2_mcspi_tx_callback;
434438
tx->callback_param = spi;
@@ -474,15 +478,20 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
474478

475479
if (mcspi_dma->dma_rx) {
476480
struct dma_async_tx_descriptor *tx;
481+
struct scatterlist sg;
477482

478483
dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
479484

480485
if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)
481486
dma_count -= es;
482487

483-
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, xfer->rx_sg.sgl,
484-
xfer->rx_sg.nents, DMA_DEV_TO_MEM,
485-
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
488+
sg_init_table(&sg, 1);
489+
sg_dma_address(&sg) = xfer->rx_dma;
490+
sg_dma_len(&sg) = dma_count;
491+
492+
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
493+
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
494+
DMA_CTRL_ACK);
486495
if (tx) {
487496
tx->callback = omap2_mcspi_rx_callback;
488497
tx->callback_param = spi;
@@ -496,6 +505,8 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
496505
omap2_mcspi_set_dma_req(spi, 1, 1);
497506

498507
wait_for_completion(&mcspi_dma->dma_rx_completion);
508+
dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
509+
DMA_FROM_DEVICE);
499510

500511
if (mcspi->fifo_depth > 0)
501512
return count;
@@ -608,6 +619,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
608619

609620
if (tx != NULL) {
610621
wait_for_completion(&mcspi_dma->dma_tx_completion);
622+
dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
623+
DMA_TO_DEVICE);
611624

612625
if (mcspi->fifo_depth > 0) {
613626
irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
@@ -1074,16 +1087,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
10741087
gpio_free(spi->cs_gpio);
10751088
}
10761089

1077-
static bool omap2_mcspi_can_dma(struct spi_master *master,
1078-
struct spi_device *spi,
1079-
struct spi_transfer *xfer)
1080-
{
1081-
if (xfer->len < DMA_MIN_BYTES)
1082-
return false;
1083-
1084-
return true;
1085-
}
1086-
10871090
static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
10881091
struct spi_device *spi, struct spi_transfer *t)
10891092
{
@@ -1265,6 +1268,32 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
12651268
return -EINVAL;
12661269
}
12671270

1271+
if (len < DMA_MIN_BYTES)
1272+
goto skip_dma_map;
1273+
1274+
if (mcspi_dma->dma_tx && tx_buf != NULL) {
1275+
t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,
1276+
len, DMA_TO_DEVICE);
1277+
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
1278+
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
1279+
'T', len);
1280+
return -EINVAL;
1281+
}
1282+
}
1283+
if (mcspi_dma->dma_rx && rx_buf != NULL) {
1284+
t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,
1285+
DMA_FROM_DEVICE);
1286+
if (dma_mapping_error(mcspi->dev, t->rx_dma)) {
1287+
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
1288+
'R', len);
1289+
if (tx_buf != NULL)
1290+
dma_unmap_single(mcspi->dev, t->tx_dma,
1291+
len, DMA_TO_DEVICE);
1292+
return -EINVAL;
1293+
}
1294+
}
1295+
1296+
skip_dma_map:
12681297
return omap2_mcspi_work_one(mcspi, spi, t);
12691298
}
12701299

@@ -1348,7 +1377,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
13481377
master->transfer_one = omap2_mcspi_transfer_one;
13491378
master->set_cs = omap2_mcspi_set_cs;
13501379
master->cleanup = omap2_mcspi_cleanup;
1351-
master->can_dma = omap2_mcspi_can_dma;
13521380
master->dev.of_node = node;
13531381
master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
13541382
master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;

0 commit comments

Comments
 (0)