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

Submitted by Kyungmin Park on Aug. 30, 2010, 11:48 p.m.

Details

Message ID 20100830234801.GA16862@july
State New, archived
Headers show

Commit Message

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

Comments

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 hide | download patch | download mbox

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