@@ -808,23 +808,28 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
if (!master->can_dma(master, msg->spi, xfer))
continue;
- if (xfer->tx_buf != NULL) {
+ if (xfer->tx_buf != NULL && !xfer->tx_sg.nents) {
ret = spi_map_buf(master, tx_dev, &xfer->tx_sg,
(void *)xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
if (ret != 0)
return ret;
+
+ xfer->tx_sg_core_mapped = true;
}
- if (xfer->rx_buf != NULL) {
+ if (xfer->rx_buf != NULL && !xfer->rx_sg.nents) {
ret = spi_map_buf(master, rx_dev, &xfer->rx_sg,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE);
if (ret != 0) {
spi_unmap_buf(master, tx_dev, &xfer->tx_sg,
DMA_TO_DEVICE);
+ xfer->tx_sg_core_mapped = false;
return ret;
}
+
+ xfer->rx_sg_core_mapped = true;
}
}
@@ -852,11 +857,16 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
rx_dev = &master->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (!master->can_dma(master, msg->spi, xfer))
- continue;
-
- spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
- spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
+ if (xfer->rx_sg_core_mapped) {
+ spi_unmap_buf(master, rx_dev, &xfer->rx_sg,
+ DMA_FROM_DEVICE);
+ xfer->rx_sg.nents = 0;
+ }
+ if (xfer->tx_sg_core_mapped) {
+ spi_unmap_buf(master, tx_dev, &xfer->tx_sg,
+ DMA_TO_DEVICE);
+ xfer->tx_sg.nents = 0;
+ }
}
return 0;
@@ -682,6 +682,8 @@ extern void spi_res_release(struct spi_master *master,
* @transfer_list: transfers are sequenced through @spi_message.transfers
* @tx_sg: Scatterlist for transmit, currently not for client use
* @rx_sg: Scatterlist for receive, currently not for client use
+ * @tx_sg_core_mapped: Scatterlist has been mapped by spi core
+ * @rx_sg_core_mapped: Scatterlist has been mapped by spi core
*
* SPI transfers always write the same number of bytes as they read.
* Protocol drivers should always provide @rx_buf and/or @tx_buf.
@@ -751,6 +753,8 @@ struct spi_transfer {
dma_addr_t rx_dma;
struct sg_table tx_sg;
struct sg_table rx_sg;
+ bool tx_sg_core_mapped;
+ bool rx_sg_core_mapped;
unsigned cs_change:1;
unsigned tx_nbits:3;
Just a hack. Someone probably has an idea about how this should be done. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> --- drivers/spi/spi.c | 24 +++++++++++++++++------- include/linux/spi/spi.h | 4 ++++ 2 files changed, 21 insertions(+), 7 deletions(-)