Skip to content

Commit 6fcc2b7

Browse files
Cyrille Pitchenalexandrebelloni
authored andcommitted
spi: atmel: Use SPI core DMA mapping framework
Use the SPI core DMA mapping framework instead of our own in case of DMA support. PDC support is not converted to this framework. The driver is now able to transfer a complete sg list through DMA. This eventually fix an issue with vmalloc'ed DMA memory that is provided for example by UBI/UBIFS layers. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> [nicolas.ferre@atmel.com: restrict the use to non-PDC DMA] Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent d9e37da commit 6fcc2b7

1 file changed

Lines changed: 25 additions & 32 deletions

File tree

drivers/spi/spi-atmel.c

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,6 @@
268268
struct atmel_spi_dma {
269269
struct dma_chan *chan_rx;
270270
struct dma_chan *chan_tx;
271-
struct scatterlist sgrx;
272-
struct scatterlist sgtx;
273271
struct dma_async_tx_descriptor *data_desc_rx;
274272
struct dma_async_tx_descriptor *data_desc_tx;
275273

@@ -454,6 +452,15 @@ static inline bool atmel_spi_use_dma(struct atmel_spi *as,
454452
return as->use_dma && xfer->len >= DMA_MIN_BYTES;
455453
}
456454

455+
static bool atmel_spi_can_dma(struct spi_master *master,
456+
struct spi_device *spi,
457+
struct spi_transfer *xfer)
458+
{
459+
struct atmel_spi *as = spi_master_get_devdata(master);
460+
461+
return atmel_spi_use_dma(as, xfer);
462+
}
463+
457464
static int atmel_spi_dma_slave_config(struct atmel_spi *as,
458465
struct dma_slave_config *slave_config,
459466
u8 bits_per_word)
@@ -721,7 +728,6 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
721728
struct dma_async_tx_descriptor *txdesc;
722729
struct dma_slave_config slave_config;
723730
dma_cookie_t cookie;
724-
u32 len = *plen;
725731

726732
dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_dma_submit\n");
727733

@@ -732,34 +738,22 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
732738
/* release lock for DMA operations */
733739
atmel_spi_unlock(as);
734740

735-
/* prepare the RX dma transfer */
736-
sg_init_table(&as->dma.sgrx, 1);
737-
as->dma.sgrx.dma_address = xfer->rx_dma + xfer->len - *plen;
738-
739-
/* prepare the TX dma transfer */
740-
sg_init_table(&as->dma.sgtx, 1);
741-
as->dma.sgtx.dma_address = xfer->tx_dma + xfer->len - *plen;
742-
743-
if (len > master->max_dma_len)
744-
len = master->max_dma_len;
745-
746-
sg_dma_len(&as->dma.sgtx) = len;
747-
sg_dma_len(&as->dma.sgrx) = len;
748-
749-
*plen = len;
741+
*plen = xfer->len;
750742

751743
if (atmel_spi_dma_slave_config(as, &slave_config,
752744
xfer->bits_per_word))
753745
goto err_exit;
754746

755747
/* Send both scatterlists */
756-
rxdesc = dmaengine_prep_slave_sg(rxchan, &as->dma.sgrx, 1,
748+
rxdesc = dmaengine_prep_slave_sg(rxchan,
749+
xfer->rx_sg.sgl, xfer->rx_sg.nents,
757750
DMA_FROM_DEVICE,
758751
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
759752
if (!rxdesc)
760753
goto err_dma;
761754

762-
txdesc = dmaengine_prep_slave_sg(txchan, &as->dma.sgtx, 1,
755+
txdesc = dmaengine_prep_slave_sg(txchan,
756+
xfer->tx_sg.sgl, xfer->tx_sg.nents,
763757
DMA_TO_DEVICE,
764758
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
765759
if (!txdesc)
@@ -805,15 +799,10 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
805799
dma_addr_t *rx_dma,
806800
u32 *plen)
807801
{
808-
struct atmel_spi *as = spi_master_get_devdata(master);
809-
u32 len = *plen;
810-
811802
*rx_dma = xfer->rx_dma + xfer->len - *plen;
812803
*tx_dma = xfer->tx_dma + xfer->len - *plen;
813-
if (len > master->max_dma_len)
814-
len = master->max_dma_len;
815-
816-
*plen = len;
804+
if (*plen > master->max_dma_len)
805+
*plen = master->max_dma_len;
817806
}
818807

819808
static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
@@ -1253,7 +1242,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
12531242
* better fault reporting.
12541243
*/
12551244
if ((!msg->is_dma_mapped)
1256-
&& (atmel_spi_use_dma(as, xfer) || as->use_pdc)) {
1245+
&& as->use_pdc) {
12571246
if (atmel_spi_dma_map_xfer(as, xfer) < 0)
12581247
return -ENOMEM;
12591248
}
@@ -1330,7 +1319,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
13301319
}
13311320

13321321
if (!msg->is_dma_mapped
1333-
&& (atmel_spi_use_dma(as, xfer) || as->use_pdc))
1322+
&& as->use_pdc)
13341323
atmel_spi_dma_unmap_xfer(master, xfer);
13351324

13361325
return 0;
@@ -1341,7 +1330,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
13411330
}
13421331

13431332
if (!msg->is_dma_mapped
1344-
&& (atmel_spi_use_dma(as, xfer) || as->use_pdc))
1333+
&& as->use_pdc)
13451334
atmel_spi_dma_unmap_xfer(master, xfer);
13461335

13471336
if (xfer->delay_usecs)
@@ -1519,6 +1508,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
15191508
master->cleanup = atmel_spi_cleanup;
15201509
master->auto_runtime_pm = true;
15211510
master->max_dma_len = SPI_MAX_DMA_XFER;
1511+
master->can_dma = atmel_spi_can_dma;
15221512
platform_set_drvdata(pdev, master);
15231513

15241514
as = spi_master_get_devdata(master);
@@ -1555,10 +1545,13 @@ static int atmel_spi_probe(struct platform_device *pdev)
15551545
as->use_pdc = false;
15561546
if (as->caps.has_dma_support) {
15571547
ret = atmel_spi_configure_dma(as);
1558-
if (ret == 0)
1548+
if (ret == 0) {
1549+
master->dma_tx = as->dma.chan_tx;
1550+
master->dma_rx = as->dma.chan_rx;
15591551
as->use_dma = true;
1560-
else if (ret == -EPROBE_DEFER)
1552+
} else if (ret == -EPROBE_DEFER) {
15611553
return ret;
1554+
}
15621555
} else {
15631556
as->use_pdc = true;
15641557
}

0 commit comments

Comments
 (0)