aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorMike Dunn <mikedunn@newsguy.com>2012-12-07 15:07:23 -0500
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-12-12 10:03:42 -0500
commit3c9c6d657a94f9b9aae498cb5951659cc67fd6ad (patch)
treef4969efdec7109ca179865f5839242a952141cf9 /drivers/mtd
parent440b1d73b1b49bc08e1709ee6f6ef7ba2fc1f8ba (diff)
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: Mike Dunn <mikedunn@newsguy.com> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/docg4.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 04e5fa93735e..18fa4489e52e 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -212,6 +212,7 @@ struct docg4_priv {
212#define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ 212#define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */
213 213
214#define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */ 214#define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */
215#define DOCG4_REDUNDANT_BBT_PAGE 24 /* page where redundant factory bbt lives */
215 216
216/* 217/*
217 * Bytes 0, 1 are used as badblock marker. 218 * Bytes 0, 1 are used as badblock marker.
@@ -1020,16 +1021,15 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
1020 struct docg4_priv *doc = nand->priv; 1021 struct docg4_priv *doc = nand->priv;
1021 uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); 1022 uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
1022 uint8_t *buf; 1023 uint8_t *buf;
1023 int i, block, status; 1024 int i, block;
1025 __u32 eccfailed_stats = mtd->ecc_stats.failed;
1024 1026
1025 buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); 1027 buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
1026 if (buf == NULL) 1028 if (buf == NULL)
1027 return -ENOMEM; 1029 return -ENOMEM;
1028 1030
1029 read_page_prologue(mtd, g4_addr); 1031 read_page_prologue(mtd, g4_addr);
1030 status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); 1032 docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
1031 if (status)
1032 goto exit;
1033 1033
1034 /* 1034 /*
1035 * If no memory-based bbt was created, exit. This will happen if module 1035 * 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 if (nand->bbt == NULL) /* no memory-based bbt */ 1041 if (nand->bbt == NULL) /* no memory-based bbt */
1042 goto exit; 1042 goto exit;
1043 1043
1044 if (mtd->ecc_stats.failed > eccfailed_stats) {
1045 /*
1046 * Whoops, an ecc failure ocurred reading the factory bbt.
1047 * It is stored redundantly, so we get another chance.
1048 */
1049 eccfailed_stats = mtd->ecc_stats.failed;
1050 docg4_read_page(mtd, nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE);
1051 if (mtd->ecc_stats.failed > eccfailed_stats) {
1052 dev_warn(doc->dev,
1053 "The factory bbt could not be read!\n");
1054 goto exit;
1055 }
1056 }
1057
1044 /* 1058 /*
1045 * Parse factory bbt and update memory-based bbt. Factory bbt format is 1059 * Parse factory bbt and update memory-based bbt. Factory bbt format is
1046 * simple: one bit per block, block numbers increase left to right (msb 1060 * 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 } 1074 }
1061 exit: 1075 exit:
1062 kfree(buf); 1076 kfree(buf);
1063 return status; 1077 return 0;
1064} 1078}
1065 1079
1066static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) 1080static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)