Commit 3c9c6d65 authored by Mike Dunn's avatar Mike Dunn Committed by Artem Bityutskiy

mtd: nand/docg4: fix and improve read of factory bbt

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: default avatarMike Dunn <mikedunn@newsguy.com>
Acked-by: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
parent 440b1d73
...@@ -212,6 +212,7 @@ struct docg4_priv { ...@@ -212,6 +212,7 @@ struct docg4_priv {
#define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ #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_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. * Bytes 0, 1 are used as badblock marker.
...@@ -1020,16 +1021,15 @@ static int __init read_factory_bbt(struct mtd_info *mtd) ...@@ -1020,16 +1021,15 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
struct docg4_priv *doc = nand->priv; struct docg4_priv *doc = nand->priv;
uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
uint8_t *buf; uint8_t *buf;
int i, block, status; int i, block;
__u32 eccfailed_stats = mtd->ecc_stats.failed;
buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
if (buf == NULL) if (buf == NULL)
return -ENOMEM; return -ENOMEM;
read_page_prologue(mtd, g4_addr); read_page_prologue(mtd, g4_addr);
status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
if (status)
goto exit;
/* /*
* If no memory-based bbt was created, exit. This will happen if module * 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) ...@@ -1041,6 +1041,20 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
if (nand->bbt == NULL) /* no memory-based bbt */ if (nand->bbt == NULL) /* no memory-based bbt */
goto exit; 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 * Parse factory bbt and update memory-based bbt. Factory bbt format is
* simple: one bit per block, block numbers increase left to right (msb * 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) ...@@ -1060,7 +1074,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
} }
exit: exit:
kfree(buf); kfree(buf);
return status; return 0;
} }
static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment