public inbox for dmaengine@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed
@ 2022-01-17  9:19 Tomasz Moń
  2022-01-17  9:19 ` [PATCH 2/2] dmaengine: imx-sdma: fix cyclic buffer race condition Tomasz Moń
  2022-02-15  5:41 ` [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Vinod Koul
  0 siblings, 2 replies; 3+ messages in thread
From: Tomasz Moń @ 2022-01-17  9:19 UTC (permalink / raw)
  To: dmaengine
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, k.drobinski, Tomasz Moń

Under heavy load resulting in high interrupt latencies, it is possible
for imx UART requests to completely fill DMA buffer. When DMA channel
is triggered and no SDMA owned buffer is available, SDMA stops. Thanks
to the autoRTS feature, there is no data loss due to the SDMA stop if
the UART is using hardware flow control.

According to DMA Engine API Guide, DMA cyclic operation is performed
until explicitly stopped. Restart the buffer after handling channel loop
if the channel was stopped by SDMA.

Signed-off-by: Tomasz Moń <tomasz.mon@camlingroup.com>
---
 drivers/dma/imx-sdma.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 75ec0754d4ad..330ff41cd614 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -701,6 +701,11 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
 	return 0;
 }
 
+static int is_sdma_channel_enabled(struct sdma_engine *sdma, int channel)
+{
+	return !!(readl(sdma->regs + SDMA_H_STATSTOP) & BIT(channel));
+}
+
 static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
 {
 	writel(BIT(channel), sdma->regs + SDMA_H_START);
@@ -860,6 +865,15 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 		if (error)
 			sdmac->status = old_status;
 	}
+
+	/*
+	 * SDMA stops cyclic channel when DMA request triggers a channel and no SDMA
+	 * owned buffer is available (i.e. BD_DONE was set too late).
+	 */
+	if (!is_sdma_channel_enabled(sdmac->sdma, sdmac->channel)) {
+		dev_warn(sdmac->sdma->dev, "restart cyclic channel %d\n", sdmac->channel);
+		sdma_enable_channel(sdmac->sdma, sdmac->channel);
+	}
 }
 
 static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)
-- 
2.25.1


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

* [PATCH 2/2] dmaengine: imx-sdma: fix cyclic buffer race condition
  2022-01-17  9:19 [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Tomasz Moń
@ 2022-01-17  9:19 ` Tomasz Moń
  2022-02-15  5:41 ` [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Vinod Koul
  1 sibling, 0 replies; 3+ messages in thread
From: Tomasz Moń @ 2022-01-17  9:19 UTC (permalink / raw)
  To: dmaengine
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, k.drobinski, Tomasz Moń

Assign buffer ownership to SDMA after invoking descriptor callback to
make sure that SDMA does not write to the buffer before it is read by
the CPU.

Signed-off-by: Tomasz Moń <tomasz.mon@camlingroup.com>
---
 drivers/dma/imx-sdma.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 330ff41cd614..8cc5103193c3 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -847,7 +847,6 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 		*/
 
 		desc->chn_real_count = bd->mode.count;
-		bd->mode.status |= BD_DONE;
 		bd->mode.count = desc->period_len;
 		desc->buf_ptail = desc->buf_tail;
 		desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
@@ -862,6 +861,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 		dmaengine_desc_get_callback_invoke(&desc->vd.tx, NULL);
 		spin_lock(&sdmac->vc.lock);
 
+		/* Assign buffer ownership to SDMA */
+		bd->mode.status |= BD_DONE;
+
 		if (error)
 			sdmac->status = old_status;
 	}
-- 
2.25.1


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

* Re: [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed
  2022-01-17  9:19 [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Tomasz Moń
  2022-01-17  9:19 ` [PATCH 2/2] dmaengine: imx-sdma: fix cyclic buffer race condition Tomasz Moń
@ 2022-02-15  5:41 ` Vinod Koul
  1 sibling, 0 replies; 3+ messages in thread
From: Vinod Koul @ 2022-02-15  5:41 UTC (permalink / raw)
  To: Tomasz Moń
  Cc: dmaengine, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, k.drobinski

On 17-01-22, 10:19, Tomasz Moń wrote:
> Under heavy load resulting in high interrupt latencies, it is possible
> for imx UART requests to completely fill DMA buffer. When DMA channel
> is triggered and no SDMA owned buffer is available, SDMA stops. Thanks
> to the autoRTS feature, there is no data loss due to the SDMA stop if
> the UART is using hardware flow control.
> 
> According to DMA Engine API Guide, DMA cyclic operation is performed
> until explicitly stopped. Restart the buffer after handling channel loop
> if the channel was stopped by SDMA.

Applied all, thanks

-- 
~Vinod

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

end of thread, other threads:[~2022-02-15  5:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-01-17  9:19 [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Tomasz Moń
2022-01-17  9:19 ` [PATCH 2/2] dmaengine: imx-sdma: fix cyclic buffer race condition Tomasz Moń
2022-02-15  5:41 ` [PATCH 1/2] dmaengine: imx-sdma: restart cyclic channel if needed Vinod Koul

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox