Patchwork [3/3] mtd: nand/docg4: fix and improve read of factory bbt

login
register
mail settings
Submitter Mike Dunn
Date Dec. 7, 2012, 8:07 p.m.
Message ID <1354910843-5598-4-git-send-email-mikedunn@newsguy.com>
Download mbox | patch
Permalink /patch/204602/
State Accepted
Commit 3c9c6d657a94f9b9aae498cb5951659cc67fd6ad
Headers show

Comments

Mike Dunn - Dec. 7, 2012, 8:07 p.m.
This patch does two things related to reading the factory badblock table during
initialization: (1) fix error where a non-zero return code from
docg4_read_page() is assumed to be an error (it was later changed to be
max_bitflips; thanks to Brian Norris for bringing this to my attention a while
back), and (2) if there is an error reading the factory bbt, it tries reading
another (redundant) factory bbt table.

Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
---
 drivers/mtd/nand/docg4.c |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)

Patch

diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 04e5fa9..18fa448 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -212,6 +212,7 @@  struct docg4_priv {
 #define DOCG4_T                4   /* BCH alg corrects up to 4 bit errors */
 
 #define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */
+#define DOCG4_REDUNDANT_BBT_PAGE 24 /* page where redundant factory bbt lives */
 
 /*
  * Bytes 0, 1 are used as badblock marker.
@@ -1020,16 +1021,15 @@  static int __init read_factory_bbt(struct mtd_info *mtd)
 	struct docg4_priv *doc = nand->priv;
 	uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
 	uint8_t *buf;
-	int i, block, status;
+	int i, block;
+	__u32 eccfailed_stats = mtd->ecc_stats.failed;
 
 	buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
 
 	read_page_prologue(mtd, g4_addr);
-	status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
-	if (status)
-		goto exit;
+	docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
 
 	/*
 	 * If no memory-based bbt was created, exit.  This will happen if module
@@ -1041,6 +1041,20 @@  static int __init read_factory_bbt(struct mtd_info *mtd)
 	if (nand->bbt == NULL)  /* no memory-based bbt */
 		goto exit;
 
+	if (mtd->ecc_stats.failed > eccfailed_stats) {
+		/*
+		 * Whoops, an ecc failure ocurred reading the factory bbt.
+		 * It is stored redundantly, so we get another chance.
+		 */
+		eccfailed_stats = mtd->ecc_stats.failed;
+		docg4_read_page(mtd, nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE);
+		if (mtd->ecc_stats.failed > eccfailed_stats) {
+			dev_warn(doc->dev,
+				 "The factory bbt could not be read!\n");
+			goto exit;
+		}
+	}
+
 	/*
 	 * Parse factory bbt and update memory-based bbt.  Factory bbt format is
 	 * simple: one bit per block, block numbers increase left to right (msb
@@ -1060,7 +1074,7 @@  static int __init read_factory_bbt(struct mtd_info *mtd)
 	}
  exit:
 	kfree(buf);
-	return status;
+	return 0;
 }
 
 static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)