Patchwork [v2] MTD: OneNAND: Fix loop hang when DMA error at Samsung SoCs

login
register
mail settings
Submitter Kyungmin Park
Date Aug. 30, 2010, 11:48 p.m.
Message ID <20100830234801.GA16862@july>
Download mbox | patch
Permalink /patch/63144/
State New
Headers show

Comments

Kyungmin Park - Aug. 30, 2010, 11:48 p.m.
From: Kyungmin Park <kyungmin.park@samsung.com>

When DMA error occurs. it's loop hang since it can't exit the loop.
and it's the right DMA handling code as Spec.

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changelog v1
	Add the timeout as Artem comment
	
 drivers/mtd/onenand/samsung.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
Artem Bityutskiy - Aug. 31, 2010, 11:02 p.m.
On Tue, 2010-08-31 at 08:48 +0900, Kyungmin Park wrote:
>  	writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
>  
> +	timeout = jiffies + msec_to_jiffies(20);

Are you completely absolutely 100% totally sure 20msecs is enough?
Kyungmin Park - Sept. 1, 2010, 2:28 a.m.
On Wed, Sep 1, 2010 at 8:02 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Tue, 2010-08-31 at 08:48 +0900, Kyungmin Park wrote:
>>       writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
>>
>> +     timeout = jiffies + msec_to_jiffies(20);
>
> Are you completely absolutely 100% totally sure 20msecs is enough?

Actually there's no mention about the timeout time in the Spec. but I
tested it both s5pc110 and s5pc210. and working well.

No matter increase the time but I give the 4 chance to the DMA
routine. since we got the 5msec times. and in case of s5pc110 it's
implemented the HRT. so it's really enough.

If the DMA takes more time than 20msec, it's really slow devices and
can't use it. as you know the real transfer size is 2KiB or 4KiB.

Thank you,
Kyungmin Park
>
> --
> Best Regards,
> Artem Bityutskiy (Битюцкий Артём)
>
>

Patch

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index d604629..bdaa228 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -535,6 +535,7 @@  static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
 {
 	void __iomem *base = onenand->dma_addr;
 	int status;
+	unsigned long timeout;
 
 	writel(src, base + S5PC110_DMA_SRC_ADDR);
 	writel(dst, base + S5PC110_DMA_DST_ADDR);
@@ -552,15 +553,17 @@  static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
 
 	writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
 
+	timeout = jiffies + msec_to_jiffies(20);
+
 	do {
 		status = readl(base + S5PC110_DMA_TRANS_STATUS);
-	} while (!(status & S5PC110_DMA_TRANS_STATUS_TD));
-
-	if (status & S5PC110_DMA_TRANS_STATUS_TE) {
-		writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD);
-		writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
-		return -EIO;
-	}
+		if (status & S5PC110_DMA_TRANS_STATUS_TE) {
+			writel(S5PC110_DMA_TRANS_CMD_TEC,
+					base + S5PC110_DMA_TRANS_CMD);
+			return -EIO;
+		}
+	} while (!(status & S5PC110_DMA_TRANS_STATUS_TD) &&
+		time_before(jiffies, timeout));
 
 	writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);