linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] spi: When no dma_chan map buffers with spi_master's parent
@ 2017-01-26 16:21 Daniel Kurtz
  2017-01-28 22:17 ` Andy Shevchenko
       [not found] ` <20170126162154.124287-1-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  0 siblings, 2 replies; 7+ messages in thread
From: Daniel Kurtz @ 2017-01-26 16:21 UTC (permalink / raw)
  Cc: dtor, groeck, drinkcat, Robin Murphy, Daniel Kurtz, Leilk Liu,
	Mark Brown, Matthias Brugger, open list:SPI SUBSYSTEM, open list,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support

Back before commit 1dccb598df54 ("arm64: simplify dma_get_ops"), for
arm64, devices for which dma_ops were not explicitly set were automatically
configured to use swiotlb_dma_ops, since this was hard-coded as the
global "dma_ops" in arm64_dma_init().

Now that global "dma_ops" has been removed, all devices much have their
dma_ops explicitly set by a call to arch_setup_dma_ops(), otherwise the
device is assigned dummy_dma_ops, and thus calls to map_sg for such a
device will fail (return 0).

Mediatek SPI uses DMA but does not use a dma channel.  Support for this
was added by commit c37f45b5f1cd ("spi: support spi without dma channel
to use can_dma()"), which uses the master_spi dev to DMA map buffers.

The master_spi device is not a platform device, rather it is created
in spi_alloc_device(), and therefore its dma_ops are never set.

Therefore, when the mediatek SPI driver when it does DMA (for large SPI
transactions > 32 bytes), SPI will use spi_map_buf()->dma_map_sg() to
map the buffer for use in DMA.  But dma_map_sg()->dma_map_sg_attrs() returns
0, because ops->map_sg is dummy_dma_ops->__dummy_map_sg, and hence
spi_map_buf() returns -ENOMEM (-12).

Fix this by using the real spi_master's parent device which should be a
real physical device with DMA properties.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Fixes: c37f45b5f1cd ("spi: support spi without dma channel to use can_dma()")
Cc: Leilk Liu <leilk.liu@mediatek.com>
---
 drivers/spi/spi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 656dd3e3220c..f4d412e48e1c 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -805,12 +805,12 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -852,12 +852,12 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
-- 
2.11.0.483.g087da7b7c-goog

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

* [PATCH 2/2] spi: mediatek: Only do dma for 4-byte aligned buffers
       [not found] ` <20170126162154.124287-1-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2017-01-26 16:21   ` Daniel Kurtz
       [not found]     ` <20170126162154.124287-2-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2017-01-31 20:02     ` Applied "spi: mediatek: Only do dma for 4-byte aligned buffers" to the spi tree Mark Brown
  2017-01-31 20:02   ` Applied "spi: When no dma_chan map buffers with spi_master's parent" " Mark Brown
  1 sibling, 2 replies; 7+ messages in thread
From: Daniel Kurtz @ 2017-01-26 16:21 UTC (permalink / raw)
  Cc: dtor-F7+t8E8rja9g9hUCZPvPmw, groeck-F7+t8E8rja9g9hUCZPvPmw,
	drinkcat-F7+t8E8rja9g9hUCZPvPmw, Robin Murphy, Daniel Kurtz,
	Leilk Liu, Mark Brown, Matthias Brugger, open list:SPI SUBSYSTEM,
	open list, moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support

Mediatek SPI DMA only works when tx and rx buffer addresses are 4-byte
aligned.

Unaligned DMA transactions appeared to work previously, since we the
spi core was incorrectly using the spi_master device for dma, which
had a 0 dma_mask, and therefore the swiotlb dma map operations were
falling back to using bounce buffers.  Since each DMA transaction would
use its own buffer, the mapped starting address of each transaction was
always aligned.  When doing real DMA, the mapped address will share the
alignment of the raw tx/rx buffer provided by the SPI user, which may or
may not be aligned.

If a buffer is not aligned, we cannot use DMA, and must use FIFO based
transaction instead.

So, this patch implements a scheme that allows using the FIFO for
arbitrary length transactions (larger than the 32-byte FIFO size) by
reloading the FIFO in the interrupt handler.

Signed-off-by: Daniel Kurtz <djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Cc: Leilk Liu <leilk.liu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/spi/spi-mt65xx.c | 37 +++++++++++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 899d7a8f0889..4b592fc25194 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -73,7 +73,7 @@
 #define MTK_SPI_IDLE 0
 #define MTK_SPI_PAUSED 1
 
-#define MTK_SPI_MAX_FIFO_SIZE 32
+#define MTK_SPI_MAX_FIFO_SIZE 32U
 #define MTK_SPI_PACKET_SIZE 1024
 
 struct mtk_spi_compatible {
@@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 	struct mtk_spi *mdata = spi_master_get_devdata(master);
 
 	mdata->cur_transfer = xfer;
-	mdata->xfer_len = xfer->len;
+	mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
 	mtk_spi_prepare_transfer(master, xfer);
 	mtk_spi_setup_packet(master);
 
@@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master,
 			    struct spi_device *spi,
 			    struct spi_transfer *xfer)
 {
-	return xfer->len > MTK_SPI_MAX_FIFO_SIZE;
+	/* Buffers for DMA transactions must be 4-byte aligned */
+	return (xfer->len > MTK_SPI_MAX_FIFO_SIZE &&
+		(unsigned long)xfer->tx_buf % 4 == 0 &&
+		(unsigned long)xfer->rx_buf % 4 == 0);
 }
 
 static int mtk_spi_setup(struct spi_device *spi)
@@ -451,7 +454,33 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 					&reg_val, remainder);
 			}
 		}
-		spi_finalize_current_transfer(master);
+
+		trans->len -= mdata->xfer_len;
+		if (!trans->len) {
+			spi_finalize_current_transfer(master);
+			return IRQ_HANDLED;
+		}
+
+		if (trans->tx_buf)
+			trans->tx_buf += mdata->xfer_len;
+		if (trans->rx_buf)
+			trans->rx_buf += mdata->xfer_len;
+
+		mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+		mtk_spi_setup_packet(master);
+
+		cnt = trans->len / 4;
+		iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, cnt);
+
+		remainder = trans->len % 4;
+		if (remainder > 0) {
+			reg_val = 0;
+			memcpy(&reg_val, trans->tx_buf + (cnt * 4), remainder);
+			writel(reg_val, mdata->base + SPI_TX_DATA_REG);
+		}
+
+		mtk_spi_enable_transfer(master);
+
 		return IRQ_HANDLED;
 	}
 
-- 
2.11.0.483.g087da7b7c-goog

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/2] spi: mediatek: Only do dma for 4-byte aligned buffers
       [not found]     ` <20170126162154.124287-2-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2017-01-26 16:42       ` Dmitry Torokhov
  0 siblings, 0 replies; 7+ messages in thread
From: Dmitry Torokhov @ 2017-01-26 16:42 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: drinkcat-F7+t8E8rja9g9hUCZPvPmw, Leilk Liu, Dmitry Torokhov,
	open list, open list:SPI SUBSYSTEM, Matthias Brugger, Mark Brown,
	moderated list:ARM/Mediatek SoC support, Guenter Roeck,
	Robin Murphy, moderated list:ARM/Mediatek SoC support

Hi Daniel,

On Thu, Jan 26, 2017 at 8:21 AM, Daniel Kurtz <djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> Mediatek SPI DMA only works when tx and rx buffer addresses are 4-byte
> aligned.
>
> Unaligned DMA transactions appeared to work previously, since we the
> spi core was incorrectly using the spi_master device for dma, which
> had a 0 dma_mask, and therefore the swiotlb dma map operations were
> falling back to using bounce buffers.  Since each DMA transaction would
> use its own buffer, the mapped starting address of each transaction was
> always aligned.  When doing real DMA, the mapped address will share the
> alignment of the raw tx/rx buffer provided by the SPI user, which may or
> may not be aligned.
>
> If a buffer is not aligned, we cannot use DMA, and must use FIFO based
> transaction instead.

>From spi.h:

/**
 * struct spi_transfer - a read/write buffer pair
 * @tx_buf: data to be written (dma-safe memory), or NULL
 * @rx_buf: data to be read (dma-safe memory), or NULL

DMA-safe memory is ___cacheline_aligned, so it appears to be user (of
the SPI) error providing "bad" memory for transfers.

Thanks,
Dmitry

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

* Re: [PATCH 1/2] spi: When no dma_chan map buffers with spi_master's parent
  2017-01-26 16:21 [PATCH 1/2] spi: When no dma_chan map buffers with spi_master's parent Daniel Kurtz
@ 2017-01-28 22:17 ` Andy Shevchenko
  2017-01-30 11:44   ` Robin Murphy
       [not found] ` <20170126162154.124287-1-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  1 sibling, 1 reply; 7+ messages in thread
From: Andy Shevchenko @ 2017-01-28 22:17 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: dtor, groeck, Nicolas Boichat, Robin Murphy, Leilk Liu,
	Mark Brown, Matthias Brugger, open list:SPI SUBSYSTEM, open list,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support

On Thu, Jan 26, 2017 at 6:21 PM, Daniel Kurtz <djkurtz@chromium.org> wrote:
> Back before commit 1dccb598df54 ("arm64: simplify dma_get_ops"), for
> arm64, devices for which dma_ops were not explicitly set were automatically
> configured to use swiotlb_dma_ops, since this was hard-coded as the
> global "dma_ops" in arm64_dma_init().
>
> Now that global "dma_ops" has been removed, all devices much have their
> dma_ops explicitly set by a call to arch_setup_dma_ops(), otherwise the
> device is assigned dummy_dma_ops, and thus calls to map_sg for such a
> device will fail (return 0).
>
> Mediatek SPI uses DMA but does not use a dma channel.  Support for this
> was added by commit c37f45b5f1cd ("spi: support spi without dma channel
> to use can_dma()"), which uses the master_spi dev to DMA map buffers.
>
> The master_spi device is not a platform device, rather it is created
> in spi_alloc_device(), and therefore its dma_ops are never set.
>
> Therefore, when the mediatek SPI driver when it does DMA (for large SPI
> transactions > 32 bytes), SPI will use spi_map_buf()->dma_map_sg() to
> map the buffer for use in DMA.  But dma_map_sg()->dma_map_sg_attrs() returns
> 0, because ops->map_sg is dummy_dma_ops->__dummy_map_sg, and hence
> spi_map_buf() returns -ENOMEM (-12).
>
> Fix this by using the real spi_master's parent device which should be a
> real physical device with DMA properties.

Wouldn't be better to copy necessary stuff from parent device to its
child? Like DMA mask propagation (I dunno if there are such in SPI,
but at least many other drivers are doing that).

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 1/2] spi: When no dma_chan map buffers with spi_master's parent
  2017-01-28 22:17 ` Andy Shevchenko
@ 2017-01-30 11:44   ` Robin Murphy
  0 siblings, 0 replies; 7+ messages in thread
From: Robin Murphy @ 2017-01-30 11:44 UTC (permalink / raw)
  To: Andy Shevchenko, Daniel Kurtz
  Cc: Nicolas Boichat, Leilk Liu, open list, open list:SPI SUBSYSTEM,
	Matthias Brugger, Mark Brown,
	moderated list:ARM/Mediatek SoC support, groeck, dtor,
	moderated list:ARM/Mediatek SoC support

On 28/01/17 22:17, Andy Shevchenko wrote:
> On Thu, Jan 26, 2017 at 6:21 PM, Daniel Kurtz <djkurtz@chromium.org> wrote:
>> Back before commit 1dccb598df54 ("arm64: simplify dma_get_ops"), for
>> arm64, devices for which dma_ops were not explicitly set were automatically
>> configured to use swiotlb_dma_ops, since this was hard-coded as the
>> global "dma_ops" in arm64_dma_init().
>>
>> Now that global "dma_ops" has been removed, all devices much have their
>> dma_ops explicitly set by a call to arch_setup_dma_ops(), otherwise the
>> device is assigned dummy_dma_ops, and thus calls to map_sg for such a
>> device will fail (return 0).
>>
>> Mediatek SPI uses DMA but does not use a dma channel.  Support for this
>> was added by commit c37f45b5f1cd ("spi: support spi without dma channel
>> to use can_dma()"), which uses the master_spi dev to DMA map buffers.
>>
>> The master_spi device is not a platform device, rather it is created
>> in spi_alloc_device(), and therefore its dma_ops are never set.
>>
>> Therefore, when the mediatek SPI driver when it does DMA (for large SPI
>> transactions > 32 bytes), SPI will use spi_map_buf()->dma_map_sg() to
>> map the buffer for use in DMA.  But dma_map_sg()->dma_map_sg_attrs() returns
>> 0, because ops->map_sg is dummy_dma_ops->__dummy_map_sg, and hence
>> spi_map_buf() returns -ENOMEM (-12).
>>
>> Fix this by using the real spi_master's parent device which should be a
>> real physical device with DMA properties.
> 
> Wouldn't be better to copy necessary stuff from parent device to its
> child? Like DMA mask propagation (I dunno if there are such in SPI,
> but at least many other drivers are doing that).

Absolutely not. The "necessary stuff" includes arch-specific things
which would require filling the SPI code with arch-specific #ifdefs, and
may go as far as private data structures held by other drivers (e.g.
IOMMUs) which the SPI code cannot even touch, let alone know what to do
with. The "parent device" here *is* the real DMA master device (as
described by firmware and configured by the arch code accordingly), so
using any other device for DMA is just plain wrong.

Robin.

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

* Applied "spi: mediatek: Only do dma for 4-byte aligned buffers" to the spi tree
  2017-01-26 16:21   ` [PATCH 2/2] spi: mediatek: Only do dma for 4-byte aligned buffers Daniel Kurtz
       [not found]     ` <20170126162154.124287-2-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2017-01-31 20:02     ` Mark Brown
  1 sibling, 0 replies; 7+ messages in thread
From: Mark Brown @ 2017-01-31 20:02 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: , drinkcat, Leilk Liu, Robin Murphy, open list, linux-spi,
	Matthias Brugger, Mark Brown, moderated list:ARM/Mediatek SoC,
	support, groeck, dtor, moderated list:ARM/Mediatek SoC, support

The patch

   spi: mediatek: Only do dma for 4-byte aligned buffers

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 1ce24864bff40e11500a699789412115fdf244bf Mon Sep 17 00:00:00 2001
From: Daniel Kurtz <djkurtz@chromium.org>
Date: Fri, 27 Jan 2017 00:21:54 +0800
Subject: [PATCH] spi: mediatek: Only do dma for 4-byte aligned buffers

Mediatek SPI DMA only works when tx and rx buffer addresses are 4-byte
aligned.

Unaligned DMA transactions appeared to work previously, since we the
spi core was incorrectly using the spi_master device for dma, which
had a 0 dma_mask, and therefore the swiotlb dma map operations were
falling back to using bounce buffers.  Since each DMA transaction would
use its own buffer, the mapped starting address of each transaction was
always aligned.  When doing real DMA, the mapped address will share the
alignment of the raw tx/rx buffer provided by the SPI user, which may or
may not be aligned.

If a buffer is not aligned, we cannot use DMA, and must use FIFO based
transaction instead.

So, this patch implements a scheme that allows using the FIFO for
arbitrary length transactions (larger than the 32-byte FIFO size) by
reloading the FIFO in the interrupt handler.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Cc: Leilk Liu <leilk.liu@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi-mt65xx.c | 37 +++++++++++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 899d7a8f0889..278867a31950 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -73,7 +73,7 @@
 #define MTK_SPI_IDLE 0
 #define MTK_SPI_PAUSED 1
 
-#define MTK_SPI_MAX_FIFO_SIZE 32
+#define MTK_SPI_MAX_FIFO_SIZE 32U
 #define MTK_SPI_PACKET_SIZE 1024
 
 struct mtk_spi_compatible {
@@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 	struct mtk_spi *mdata = spi_master_get_devdata(master);
 
 	mdata->cur_transfer = xfer;
-	mdata->xfer_len = xfer->len;
+	mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
 	mtk_spi_prepare_transfer(master, xfer);
 	mtk_spi_setup_packet(master);
 
@@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master,
 			    struct spi_device *spi,
 			    struct spi_transfer *xfer)
 {
-	return xfer->len > MTK_SPI_MAX_FIFO_SIZE;
+	/* Buffers for DMA transactions must be 4-byte aligned */
+	return (xfer->len > MTK_SPI_MAX_FIFO_SIZE &&
+		(unsigned long)xfer->tx_buf % 4 == 0 &&
+		(unsigned long)xfer->rx_buf % 4 == 0);
 }
 
 static int mtk_spi_setup(struct spi_device *spi)
@@ -451,7 +454,33 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 					&reg_val, remainder);
 			}
 		}
-		spi_finalize_current_transfer(master);
+
+		trans->len -= mdata->xfer_len;
+		if (!trans->len) {
+			spi_finalize_current_transfer(master);
+			return IRQ_HANDLED;
+		}
+
+		if (trans->tx_buf)
+			trans->tx_buf += mdata->xfer_len;
+		if (trans->rx_buf)
+			trans->rx_buf += mdata->xfer_len;
+
+		mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+		mtk_spi_setup_packet(master);
+
+		cnt = trans->len / 4;
+		iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, cnt);
+
+		remainder = trans->len % 4;
+		if (remainder > 0) {
+			reg_val = 0;
+			memcpy(&reg_val, trans->tx_buf + (cnt * 4), remainder);
+			writel(reg_val, mdata->base + SPI_TX_DATA_REG);
+		}
+
+		mtk_spi_enable_transfer(master);
+
 		return IRQ_HANDLED;
 	}
 
-- 
2.11.0

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

* Applied "spi: When no dma_chan map buffers with spi_master's parent" to the spi tree
       [not found] ` <20170126162154.124287-1-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2017-01-26 16:21   ` [PATCH 2/2] spi: mediatek: Only do dma for 4-byte aligned buffers Daniel Kurtz
@ 2017-01-31 20:02   ` Mark Brown
  1 sibling, 0 replies; 7+ messages in thread
From: Mark Brown @ 2017-01-31 20:02 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: , drinkcat-F7+t8E8rja9g9hUCZPvPmw, Leilk Liu, Robin Murphy,
	open list, linux-spi-u79uwXL29TY76Z2rM5mHXA, Matthias Brugger,
	Mark Brown, moderated list:ARM/Mediatek SoC, support,
	groeck-F7+t8E8rja9g9hUCZPvPmw, dtor-F7+t8E8rja9g9hUCZPvPmw,
	moderated list:ARM/Mediatek SoC, support

The patch

   spi: When no dma_chan map buffers with spi_master's parent

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 88b0aa544af58ce3be125a1845a227264ec9ab89 Mon Sep 17 00:00:00 2001
From: Daniel Kurtz <djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Date: Fri, 27 Jan 2017 00:21:53 +0800
Subject: [PATCH] spi: When no dma_chan map buffers with spi_master's parent

Back before commit 1dccb598df54 ("arm64: simplify dma_get_ops"), for
arm64, devices for which dma_ops were not explicitly set were automatically
configured to use swiotlb_dma_ops, since this was hard-coded as the
global "dma_ops" in arm64_dma_init().

Now that global "dma_ops" has been removed, all devices much have their
dma_ops explicitly set by a call to arch_setup_dma_ops(), otherwise the
device is assigned dummy_dma_ops, and thus calls to map_sg for such a
device will fail (return 0).

Mediatek SPI uses DMA but does not use a dma channel.  Support for this
was added by commit c37f45b5f1cd ("spi: support spi without dma channel
to use can_dma()"), which uses the master_spi dev to DMA map buffers.

The master_spi device is not a platform device, rather it is created
in spi_alloc_device(), and therefore its dma_ops are never set.

Therefore, when the mediatek SPI driver when it does DMA (for large SPI
transactions > 32 bytes), SPI will use spi_map_buf()->dma_map_sg() to
map the buffer for use in DMA.  But dma_map_sg()->dma_map_sg_attrs() returns
0, because ops->map_sg is dummy_dma_ops->__dummy_map_sg, and hence
spi_map_buf() returns -ENOMEM (-12).

Fix this by using the real spi_master's parent device which should be a
real physical device with DMA properties.

Signed-off-by: Daniel Kurtz <djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Fixes: c37f45b5f1cd ("spi: support spi without dma channel to use can_dma()")
Cc: Leilk Liu <leilk.liu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 656dd3e3220c..f4d412e48e1c 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -805,12 +805,12 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -852,12 +852,12 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
-- 
2.11.0

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

end of thread, other threads:[~2017-01-31 20:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-26 16:21 [PATCH 1/2] spi: When no dma_chan map buffers with spi_master's parent Daniel Kurtz
2017-01-28 22:17 ` Andy Shevchenko
2017-01-30 11:44   ` Robin Murphy
     [not found] ` <20170126162154.124287-1-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2017-01-26 16:21   ` [PATCH 2/2] spi: mediatek: Only do dma for 4-byte aligned buffers Daniel Kurtz
     [not found]     ` <20170126162154.124287-2-djkurtz-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2017-01-26 16:42       ` Dmitry Torokhov
2017-01-31 20:02     ` Applied "spi: mediatek: Only do dma for 4-byte aligned buffers" to the spi tree Mark Brown
2017-01-31 20:02   ` Applied "spi: When no dma_chan map buffers with spi_master's parent" " Mark Brown

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