[U-Boot] [PATCH] mtd: nand: denali: Nuke unbounded loop

Marek Vasut marex at denx.de
Sun Dec 20 03:59:08 CET 2015


This particular unbounded loop in the Denali NAND reset routine can
lead to a system hang in case neither of the Timeout and Completed
bits get set.

Refactor the code a bit so it's readable and implement timer so the
loop is bounded instead. This way the complete hang can be prevented
even if the NAND fails to reset.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Scott Wood <scottwood at freescale.com>
---
 drivers/mtd/nand/denali.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 192be7d..8a8cca9 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -199,6 +199,7 @@ static void reset_bank(struct denali_nand_info *denali)
 static uint32_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	int i;
+	u32 start, reg;
 
 	for (i = 0; i < denali->max_banks; i++)
 		writel(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
@@ -206,12 +207,25 @@ static uint32_t denali_nand_reset(struct denali_nand_info *denali)
 
 	for (i = 0; i < denali->max_banks; i++) {
 		writel(1 << i, denali->flash_reg + DEVICE_RESET);
-		while (!(readl(denali->flash_reg + INTR_STATUS(i)) &
-			(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT)))
-			if (readl(denali->flash_reg + INTR_STATUS(i)) &
-				INTR_STATUS__TIME_OUT)
-				debug("NAND Reset operation timed out on bank"
-				      " %d\n", i);
+
+		start = get_timer(0);
+		while (1) {
+			reg = readl(denali->flash_reg + INTR_STATUS(i));
+			if (reg & INTR_STATUS__TIME_OUT) {
+				debug("NAND Reset operation timed out on bank %d\n",
+				      i);
+				break;
+			}
+
+			/* Reset completed and did not time out, all good. */
+			if (reg & INTR_STATUS__RST_COMP)
+				break;
+
+			if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+				debug("%s: Reset timed out!\n", __func__);
+				break;
+			}
+		}
 	}
 
 	for (i = 0; i < denali->max_banks; i++)
-- 
2.1.4



More information about the U-Boot mailing list