Message ID | 1459828192-5531-2-git-send-email-vigneshr@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Apr 05, 2016 at 09:19:51AM +0530, Vignesh R wrote: > mutex_lock(&master->bus_lock_mutex); > + if (master->dma_rx) { > + rx_dev = master->dma_rx->device->dev; > + ret = spi_map_buf(master, rx_dev, &msg->rx_sg, > + msg->buf, msg->len, > + DMA_FROM_DEVICE); > + if (ret != 0) > + goto err; > + } This is unconditionally DMA mapping the buffer if DMA is supported. That's going to be common but I'm not sure it'll be universal, we need to think of something better here. I'm not immediately seeing what though. Possibly a flag...
On 04/12/2016 10:01 AM, Mark Brown wrote: > On Tue, Apr 05, 2016 at 09:19:51AM +0530, Vignesh R wrote: > >> mutex_lock(&master->bus_lock_mutex); >> + if (master->dma_rx) { >> + rx_dev = master->dma_rx->device->dev; >> + ret = spi_map_buf(master, rx_dev, &msg->rx_sg, >> + msg->buf, msg->len, >> + DMA_FROM_DEVICE); >> + if (ret != 0) >> + goto err; >> + } > > This is unconditionally DMA mapping the buffer if DMA is supported. > That's going to be common but I'm not sure it'll be universal, we need > to think of something better here. I'm not immediately seeing what > though. Possibly a flag... > Ok, I will introduced a flag along the lines of cur_msg_mapped currently part of spi_message struct. This reminds me the issue of possible kmap'd buffers(falling in PKMAP_BASE - PAGE_OFFSET-1 region) that might be passed to spi_map_buf() which are not currently being handled properly. Boris attempted to fix this in generic way[1] but was rejected as it couldn't handle all type of caches. I was wondering whether you would accept a patch returning error when kmap'd buffers are passed to spi_map_buf()? Or would it still make sense to port changes from that series to handle kmap'd buffers to SPI core alone? [1]https://lkml.org/lkml/2016/3/31/462
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index de2f2f90d799..2fb97f5b79ab 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2722,6 +2722,7 @@ int spi_flash_read(struct spi_device *spi, { struct spi_master *master = spi->master; + struct device *rx_dev = NULL; int ret; if ((msg->opcode_nbits == SPI_NBITS_DUAL || @@ -2747,8 +2748,22 @@ int spi_flash_read(struct spi_device *spi, return ret; } } + mutex_lock(&master->bus_lock_mutex); + if (master->dma_rx) { + rx_dev = master->dma_rx->device->dev; + ret = spi_map_buf(master, rx_dev, &msg->rx_sg, + msg->buf, msg->len, + DMA_FROM_DEVICE); + if (ret != 0) + goto err; + } ret = master->spi_flash_read(spi, msg); + if (master->dma_rx) + spi_unmap_buf(master, rx_dev, &msg->rx_sg, + DMA_FROM_DEVICE); + +err: mutex_unlock(&master->bus_lock_mutex); if (master->auto_runtime_pm) pm_runtime_put(master->dev.parent); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 857a9a1d82b5..5b9c745eda92 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1141,6 +1141,7 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) * @opcode_nbits: number of lines to send opcode * @addr_nbits: number of lines to send address * @data_nbits: number of lines for data + * @rx_sg: Scatterlist for receive data */ struct spi_flash_read_message { void *buf; @@ -1153,6 +1154,7 @@ struct spi_flash_read_message { u8 opcode_nbits; u8 addr_nbits; u8 data_nbits; + struct sg_table rx_sg; }; /* SPI core interface for flash read support */
Few SPI devices provide accelerated read interfaces to read from SPI-NOR flash devices. These hardwares also support DMA to transfer data from flash to memory either via mem-to-mem DMA or dedicated slave DMA channels. Hence, add support for DMA in order to improve throughput and reduce CPU load. Use spi_map_buf() to get sg table for the buffer and pass it to SPI driver. Signed-off-by: Vignesh R <vigneshr@ti.com> --- drivers/spi/spi.c | 15 +++++++++++++++ include/linux/spi/spi.h | 2 ++ 2 files changed, 17 insertions(+)