linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] spi: Add DMA support for ti-qspi
@ 2016-04-25  9:43 Vignesh R
  2016-04-25  9:44 ` [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf() Vignesh R
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Vignesh R @ 2016-04-25  9:43 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-omap, linux-kernel, Vignesh R



This series adds support for DMA during QSPI flash read via memory
mapped mode.
The first patch adds a check to spi_map_buf() API to return error when
kmap'd buffers are passed for DMA mapping. Second patch adds support for
using DMA on top of spi_flash_read() API using  DMA sg_table mapping
support in SPI core. Third map adds DMA support for TI QSPI in memory
mapped read mode.

Tested on DRA74 EVM and DRA72 EVM on linux-next.

v1: https://lkml.org/lkml/2016/4/4/855



Vignesh R (3):
  spi: return error if kmap'd buffers passed to spi_map_buf()
  spi: Add DMA support for spi_flash_read()
  spi: spi-ti-qspi: Add DMA support for QSPI mmap read

 drivers/spi/spi-ti-qspi.c | 196 +++++++++++++++++++++++++++++++++++++++++++---
 drivers/spi/spi.c         |  18 ++++-
 include/linux/spi/spi.h   |   4 +
 3 files changed, 204 insertions(+), 14 deletions(-)

-- 
2.8.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf()
  2016-04-25  9:43 [PATCH v2 0/3] spi: Add DMA support for ti-qspi Vignesh R
@ 2016-04-25  9:44 ` Vignesh R
  2016-04-25 17:57   ` Applied "spi: return error if kmap'd buffers passed to spi_map_buf()" to the spi tree Mark Brown
  2016-04-25  9:44 ` [PATCH v2 2/3] spi: Add DMA support for spi_flash_read() Vignesh R
  2016-04-25  9:44 ` [PATCH v2 3/3] spi: spi-ti-qspi: Add DMA support for QSPI mmap read Vignesh R
  2 siblings, 1 reply; 7+ messages in thread
From: Vignesh R @ 2016-04-25  9:44 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-omap, linux-kernel, Vignesh R

Current spi_map_buf() implementation supports creates sg_table for
vmalloc'd and kmalloc'd buffers. Therefore return error if kmap'd buffer
(or any other buffer) is passed to spi_map_buf().

Signed-off-by: Vignesh R <vigneshr@ti.com>
---

v2: New patch

 drivers/spi/spi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a7ab330d0640..82126bbe69cf 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -717,9 +717,11 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
 	if (vmalloced_buf) {
 		desc_len = min_t(int, max_seg_size, PAGE_SIZE);
 		sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
-	} else {
+	} else if (virt_addr_valid(buf)) {
 		desc_len = min_t(int, max_seg_size, master->max_dma_len);
 		sgs = DIV_ROUND_UP(len, desc_len);
+	} else {
+		return -EINVAL;
 	}
 
 	ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] spi: Add DMA support for spi_flash_read()
  2016-04-25  9:43 [PATCH v2 0/3] spi: Add DMA support for ti-qspi Vignesh R
  2016-04-25  9:44 ` [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf() Vignesh R
@ 2016-04-25  9:44 ` Vignesh R
  2016-06-08  9:25   ` Applied "spi: Add DMA support for spi_flash_read()" to the spi tree Mark Brown
  2016-04-25  9:44 ` [PATCH v2 3/3] spi: spi-ti-qspi: Add DMA support for QSPI mmap read Vignesh R
  2 siblings, 1 reply; 7+ messages in thread
From: Vignesh R @ 2016-04-25  9:44 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-omap, linux-kernel, Vignesh R

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>
---

v2: use cur_msg_mapped flag to indicate success/failure of spi_map_buf()

 drivers/spi/spi.c       | 14 ++++++++++++++
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 82126bbe69cf..f98c19addc07 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2725,6 +2725,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 ||
@@ -2750,9 +2751,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)
+			msg->cur_msg_mapped = true;
+	}
 	ret = master->spi_flash_read(spi, msg);
+	if (msg->cur_msg_mapped)
+		spi_unmap_buf(master, rx_dev, &msg->rx_sg,
+			      DMA_FROM_DEVICE);
 	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..b51ea761b5c8 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -1141,6 +1141,8 @@ 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 read from flash
+ * @cur_msg_mapped: message has been mapped for DMA
  */
 struct spi_flash_read_message {
 	void *buf;
@@ -1153,6 +1155,8 @@ struct spi_flash_read_message {
 	u8 opcode_nbits;
 	u8 addr_nbits;
 	u8 data_nbits;
+	struct sg_table rx_sg;
+	bool cur_msg_mapped;
 };
 
 /* SPI core interface for flash read support */
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] spi: spi-ti-qspi: Add DMA support for QSPI mmap read
  2016-04-25  9:43 [PATCH v2 0/3] spi: Add DMA support for ti-qspi Vignesh R
  2016-04-25  9:44 ` [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf() Vignesh R
  2016-04-25  9:44 ` [PATCH v2 2/3] spi: Add DMA support for spi_flash_read() Vignesh R
@ 2016-04-25  9:44 ` Vignesh R
  2 siblings, 0 replies; 7+ messages in thread
From: Vignesh R @ 2016-04-25  9:44 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-omap, linux-kernel, Vignesh R

Use mem-to-mem DMA to read from flash when reading in mmap mode. This
gives improved read performance and reduces CPU load.

With this patch the raw-read throughput is ~16MB/s on DRA74 EVM. And CPU
load is <20%. UBIFS read ~13 MB/s.

Signed-off-by: Vignesh R <vigneshr@ti.com>
---

v2: Handle kmap'd buffers of JFFS2 FS.

 drivers/spi/spi-ti-qspi.c | 196 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 183 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 443f664534e1..97e574034ecd 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -33,6 +33,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/highmem.h>
 
 #include <linux/spi/spi.h>
 
@@ -41,6 +42,8 @@ struct ti_qspi_regs {
 };
 
 struct ti_qspi {
+	struct completion	transfer_complete;
+
 	/* list synchronization */
 	struct mutex            list_lock;
 
@@ -54,6 +57,9 @@ struct ti_qspi {
 
 	struct ti_qspi_regs     ctx_reg;
 
+	dma_addr_t		mmap_phys_base;
+	struct dma_chan		*rx_chan;
+
 	u32 spi_max_frequency;
 	u32 cmd;
 	u32 dc;
@@ -379,6 +385,78 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
 	return 0;
 }
 
+static void ti_qspi_dma_callback(void *param)
+{
+	struct ti_qspi *qspi = param;
+
+	complete(&qspi->transfer_complete);
+}
+
+static int ti_qspi_dma_xfer(struct ti_qspi *qspi, dma_addr_t dma_dst,
+			    dma_addr_t dma_src, size_t len)
+{
+	struct dma_chan *chan = qspi->rx_chan;
+	struct dma_device *dma_dev = chan->device;
+	dma_cookie_t cookie;
+	enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+	struct dma_async_tx_descriptor *tx = NULL;
+	int ret;
+
+	tx = dma_dev->device_prep_dma_memcpy(chan, dma_dst, dma_src,
+					     len, flags);
+	if (!tx) {
+		dev_err(qspi->dev, "device_prep_dma_memcpy error\n");
+		ret = -EIO;
+		goto err;
+	}
+
+	tx->callback = ti_qspi_dma_callback;
+	tx->callback_param = qspi;
+	cookie = tx->tx_submit(tx);
+
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dev_err(qspi->dev, "dma_submit_error %d\n", cookie);
+		goto err;
+	}
+
+	dma_async_issue_pending(chan);
+	ret = wait_for_completion_timeout(&qspi->transfer_complete,
+					  msecs_to_jiffies(len));
+	if (ret <= 0) {
+		dmaengine_terminate_all(chan);
+		dev_err(qspi->dev, "DMA wait_for_completion_timeout\n");
+		if (!ret)
+			ret = -ETIMEDOUT;
+		goto err;
+	}
+
+	ret = 0;
+
+err:
+	return ret;
+}
+
+static int ti_qspi_dma_xfer_sg(struct ti_qspi *qspi, struct sg_table rx_sg,
+			       loff_t from)
+{
+	struct scatterlist *sg;
+	dma_addr_t dma_src = qspi->mmap_phys_base + from;
+	dma_addr_t dma_dst;
+	int i, len, ret = 0;
+
+	for_each_sg(rx_sg.sgl, sg, rx_sg.nents, i) {
+		dma_dst = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		ret = ti_qspi_dma_xfer(qspi, dma_dst, dma_src, len);
+		if (ret)
+			return ret;
+		dma_src += len;
+	}
+
+	return ret;
+}
+
 static void ti_qspi_enable_memory_map(struct spi_device *spi)
 {
 	struct ti_qspi  *qspi = spi_master_get_devdata(spi->master);
@@ -426,7 +504,40 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi,
 		      QSPI_SPI_SETUP_REG(spi->chip_select));
 }
 
-static int ti_qspi_spi_flash_read(struct  spi_device *spi,
+#ifdef CONFIG_HIGHMEM
+static int ti_qspi_map_buf(struct ti_qspi *qspi, void *buf,
+			   unsigned int len, struct sg_table *sgt)
+{
+	unsigned int max_seg_size =
+		dma_get_max_seg_size(qspi->rx_chan->device->dev);
+	unsigned int desc_len = min_t(int, max_seg_size, PAGE_SIZE);
+	int sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
+	struct page *vm_page;
+	size_t min;
+	int i, ret;
+
+	ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < sgs; i++) {
+		min = min_t(size_t, len, desc_len -
+			    offset_in_page(buf));
+		vm_page = kmap_to_page(buf);
+		if (!vm_page) {
+			sg_free_table(sgt);
+			return -ENOMEM;
+		}
+		sg_set_page(&sgt->sgl[i], vm_page, min,
+			    offset_in_page(buf));
+		buf += min;
+		len -= min;
+	}
+	return 0;
+}
+#endif
+
+static int ti_qspi_spi_flash_read(struct spi_device *spi,
 				  struct spi_flash_read_message *msg)
 {
 	struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
@@ -437,9 +548,45 @@ static int ti_qspi_spi_flash_read(struct  spi_device *spi,
 	if (!qspi->mmap_enabled)
 		ti_qspi_enable_memory_map(spi);
 	ti_qspi_setup_mmap_read(spi, msg);
-	memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len);
+
+	if (qspi->rx_chan) {
+		struct device *dev = qspi->rx_chan->device->dev;
+		void *buf = msg->buf;
+		struct sg_table sgt;
+
+		if (msg->cur_msg_mapped) {
+			ret = ti_qspi_dma_xfer_sg(qspi, msg->rx_sg, msg->from);
+			if (ret)
+				goto err;
+#ifdef CONFIG_HIGHMEM
+		} else if ((unsigned long)buf >= PKMAP_BASE &&
+				(unsigned long)buf < (PKMAP_BASE +
+					(LAST_PKMAP * PAGE_SIZE))) {
+			/* Generate sg_table for kmap buffers */
+			ret = ti_qspi_map_buf(qspi, buf, msg->len, &sgt);
+			if (ret)
+				goto err;
+			ret = dma_map_sg(dev, sgt.sgl, sgt.nents,
+					 DMA_FROM_DEVICE);
+			if (!ret) {
+				ret = -ENOMEM;
+				goto err;
+			}
+			ret = ti_qspi_dma_xfer_sg(qspi, sgt, msg->from);
+			dma_unmap_sg(dev, sgt.sgl, sgt.orig_nents,
+				     DMA_FROM_DEVICE);
+			sg_free_table(&sgt);
+#endif
+		} else {
+			dev_err(qspi->dev, "Invalid address for DMA\n");
+			return -EIO;
+		}
+	} else {
+		memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len);
+	}
 	msg->retlen = msg->len;
 
+err:
 	mutex_unlock(&qspi->list_lock);
 
 	return ret;
@@ -536,6 +683,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	u32 max_freq;
 	int ret = 0, num_cs, irq;
+	dma_cap_mask_t mask;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*qspi));
 	if (!master)
@@ -550,6 +698,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
 	master->dev.of_node = pdev->dev.of_node;
 	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
 				     SPI_BPW_MASK(8);
+	master->spi_flash_read = ti_qspi_spi_flash_read;
 
 	if (!of_property_read_u32(np, "num-cs", &num_cs))
 		master->num_chipselect = num_cs;
@@ -592,17 +741,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
 		goto free_master;
 	}
 
-	if (res_mmap) {
-		qspi->mmap_base = devm_ioremap_resource(&pdev->dev,
-							res_mmap);
-		master->spi_flash_read = ti_qspi_spi_flash_read;
-		if (IS_ERR(qspi->mmap_base)) {
-			dev_err(&pdev->dev,
-				"falling back to PIO mode\n");
-			master->spi_flash_read = NULL;
-		}
-	}
-	qspi->mmap_enabled = false;
 
 	if (of_property_read_bool(np, "syscon-chipselects")) {
 		qspi->ctrl_base =
@@ -637,6 +775,33 @@ static int ti_qspi_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_master;
 
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_MEMCPY, mask);
+
+	qspi->rx_chan = dma_request_channel(mask, NULL, NULL);
+	if (!qspi->rx_chan) {
+		dev_err(qspi->dev,
+			"No Rx DMA available, trying mmap mode\n");
+		ret = 0;
+		goto no_dma;
+	}
+	master->dma_rx = qspi->rx_chan;
+	init_completion(&qspi->transfer_complete);
+	if (res_mmap)
+		qspi->mmap_phys_base = (dma_addr_t)res_mmap->start;
+
+no_dma:
+	if (!qspi->rx_chan && res_mmap) {
+		qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap);
+		if (IS_ERR(qspi->mmap_base)) {
+			dev_info(&pdev->dev,
+				 "mmap failed with error %ld using PIO mode\n",
+				 PTR_ERR(qspi->mmap_base));
+			qspi->mmap_base = NULL;
+			master->spi_flash_read = NULL;
+		}
+	}
+	qspi->mmap_enabled = false;
 	return 0;
 
 free_master:
@@ -646,9 +811,14 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
+	struct ti_qspi *qspi = platform_get_drvdata(pdev);
+
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
+	if (qspi->rx_chan)
+		dma_release_channel(qspi->rx_chan);
+
 	return 0;
 }
 
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Applied "spi: return error if kmap'd buffers passed to spi_map_buf()" to the spi tree
  2016-04-25  9:44 ` [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf() Vignesh R
@ 2016-04-25 17:57   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2016-04-25 17:57 UTC (permalink / raw)
  To: Vignesh R; +Cc: Mark Brown, Mark Brown, linux-spi, linux-omap, linux-kernel

The patch

   spi: return error if kmap'd buffers passed to spi_map_buf()

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 0569a88f3d1ffed94b15569d53872f16e2351099 Mon Sep 17 00:00:00 2001
From: Vignesh R <vigneshr@ti.com>
Date: Mon, 25 Apr 2016 15:14:00 +0530
Subject: [PATCH] spi: return error if kmap'd buffers passed to spi_map_buf()

Current spi_map_buf() implementation supports creates sg_table for
vmalloc'd and kmalloc'd buffers. Therefore return error if kmap'd buffer
(or any other buffer) is passed to spi_map_buf().

Signed-off-by: Vignesh R <vigneshr@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6c4c050e6b65..a50f880a5036 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -717,9 +717,11 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
 	if (vmalloced_buf) {
 		desc_len = min_t(int, max_seg_size, PAGE_SIZE);
 		sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
-	} else {
+	} else if (virt_addr_valid(buf)) {
 		desc_len = min_t(int, max_seg_size, master->max_dma_len);
 		sgs = DIV_ROUND_UP(len, desc_len);
+	} else {
+		return -EINVAL;
 	}
 
 	ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
-- 
2.8.0.rc3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Applied "spi: Add DMA support for spi_flash_read()" to the spi tree
  2016-04-25  9:44 ` [PATCH v2 2/3] spi: Add DMA support for spi_flash_read() Vignesh R
@ 2016-06-08  9:25   ` Mark Brown
  2016-06-08  9:27     ` Vignesh R
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Brown @ 2016-06-08  9:25 UTC (permalink / raw)
  To: Vignesh R; +Cc: Mark Brown, Mark Brown, linux-spi, linux-omap, linux-kernel

The patch

   spi: Add DMA support for spi_flash_read()

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 12107f2fcc1dd832ebe0b8a61da2145eaea8730d Mon Sep 17 00:00:00 2001
From: Vignesh R <vigneshr@ti.com>
Date: Tue, 7 Jun 2016 13:48:09 +0530
Subject: [PATCH] spi: Add DMA support for spi_flash_read()

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>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi.c       | 14 ++++++++++++++
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 77e6e45951f4..da2cbe205654 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2725,6 +2725,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 ||
@@ -2750,9 +2751,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)
+			msg->cur_msg_mapped = true;
+	}
 	ret = master->spi_flash_read(spi, msg);
+	if (msg->cur_msg_mapped)
+		spi_unmap_buf(master, rx_dev, &msg->rx_sg,
+			      DMA_FROM_DEVICE);
 	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 1f03483f61e5..7b53af4ba5f8 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -1143,6 +1143,8 @@ 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 read from flash
+ * @cur_msg_mapped: message has been mapped for DMA
  */
 struct spi_flash_read_message {
 	void *buf;
@@ -1155,6 +1157,8 @@ struct spi_flash_read_message {
 	u8 opcode_nbits;
 	u8 addr_nbits;
 	u8 data_nbits;
+	struct sg_table rx_sg;
+	bool cur_msg_mapped;
 };
 
 /* SPI core interface for flash read support */
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: Applied "spi: Add DMA support for spi_flash_read()" to the spi tree
  2016-06-08  9:25   ` Applied "spi: Add DMA support for spi_flash_read()" to the spi tree Mark Brown
@ 2016-06-08  9:27     ` Vignesh R
  0 siblings, 0 replies; 7+ messages in thread
From: Vignesh R @ 2016-06-08  9:27 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-omap, linux-kernel



On Wednesday 08 June 2016 02:55 PM, Mark Brown wrote:
> The patch
> 
>    spi: Add DMA support for spi_flash_read()
> 
> has been applied to the spi tree at
> 
>    git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 
> 
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.  
> 
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
> 
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
> 
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.
> 
> Thanks,
> Mark

Could you please drop this and pick v4 instead? There were some build
errors reported by kbuild test bot for this version? Or you want me to
sent incremental patch?


> 
> From 12107f2fcc1dd832ebe0b8a61da2145eaea8730d Mon Sep 17 00:00:00 2001
> From: Vignesh R <vigneshr@ti.com>
> Date: Tue, 7 Jun 2016 13:48:09 +0530
> Subject: [PATCH] spi: Add DMA support for spi_flash_read()
> 
> 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>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  drivers/spi/spi.c       | 14 ++++++++++++++
>  include/linux/spi/spi.h |  4 ++++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index 77e6e45951f4..da2cbe205654 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -2725,6 +2725,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 ||
> @@ -2750,9 +2751,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)
> +			msg->cur_msg_mapped = true;
> +	}
>  	ret = master->spi_flash_read(spi, msg);
> +	if (msg->cur_msg_mapped)
> +		spi_unmap_buf(master, rx_dev, &msg->rx_sg,
> +			      DMA_FROM_DEVICE);
>  	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 1f03483f61e5..7b53af4ba5f8 100644
> --- a/include/linux/spi/spi.h
> +++ b/include/linux/spi/spi.h
> @@ -1143,6 +1143,8 @@ 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 read from flash
> + * @cur_msg_mapped: message has been mapped for DMA
>   */
>  struct spi_flash_read_message {
>  	void *buf;
> @@ -1155,6 +1157,8 @@ struct spi_flash_read_message {
>  	u8 opcode_nbits;
>  	u8 addr_nbits;
>  	u8 data_nbits;
> +	struct sg_table rx_sg;
> +	bool cur_msg_mapped;
>  };
>  
>  /* SPI core interface for flash read support */
> 

-- 
Regards
Vignesh

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-06-08  9:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-25  9:43 [PATCH v2 0/3] spi: Add DMA support for ti-qspi Vignesh R
2016-04-25  9:44 ` [PATCH v2 1/3] spi: return error if kmap'd buffers passed to spi_map_buf() Vignesh R
2016-04-25 17:57   ` Applied "spi: return error if kmap'd buffers passed to spi_map_buf()" to the spi tree Mark Brown
2016-04-25  9:44 ` [PATCH v2 2/3] spi: Add DMA support for spi_flash_read() Vignesh R
2016-06-08  9:25   ` Applied "spi: Add DMA support for spi_flash_read()" to the spi tree Mark Brown
2016-06-08  9:27     ` Vignesh R
2016-04-25  9:44 ` [PATCH v2 3/3] spi: spi-ti-qspi: Add DMA support for QSPI mmap read Vignesh R

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).