Skip to content

Commit

Permalink
mtd: nand/docg4: fix and improve read of factory bbt
Browse files Browse the repository at this point in the history
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>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
  • Loading branch information
Mike Dunn authored and Artem Bityutskiy committed Dec 12, 2012
1 parent 440b1d7 commit 3c9c6d6
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions drivers/mtd/nand/docg4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down

0 comments on commit 3c9c6d6

Please sign in to comment.