diff options
author | Brian Norris <computersforpeace@gmail.com> | 2011-09-20 21:35:34 -0400 |
---|---|---|
committer | Artem Bityutskiy <artem.bityutskiy@intel.com> | 2011-09-21 02:19:07 -0400 |
commit | 623978de362a5faeb18d8395fa86089650642626 (patch) | |
tree | f5f6b3b77b5a25f438f0b1b90bf591986a1fa489 /drivers/mtd | |
parent | 167a8d52509a0f7d6728a79e2588b800e866c147 (diff) |
mtd: nand: scrub BBT on ECC errors
Now that `read_bbt()' returns ECC error codes properly, we handle those
codes when checking the integrity of our flash-based BBT.
The modifications can be described by this new policy:
*) On any uncorrected ECC error, we invalidate the corresponding table
and retry our version-checking integrity logic.
*) On corrected bitflips, we mark both tables for re-writing to flash
(a.k.a. scrubbing).
Current integrity checks (i.e., comparing version numbers, etc.) should
take care of all the cases that result in rescanning the device for bad
blocks or falling back to the BBT as found in the mirror descriptor.
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 0ed8591dbd26..11185aa6273c 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -882,7 +882,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b | |||
882 | */ | 882 | */ |
883 | static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) | 883 | static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) |
884 | { | 884 | { |
885 | int i, chips, writeops, create, chipsel, res; | 885 | int i, chips, writeops, create, chipsel, res, res2; |
886 | struct nand_chip *this = mtd->priv; | 886 | struct nand_chip *this = mtd->priv; |
887 | struct nand_bbt_descr *td = this->bbt_td; | 887 | struct nand_bbt_descr *td = this->bbt_td; |
888 | struct nand_bbt_descr *md = this->bbt_md; | 888 | struct nand_bbt_descr *md = this->bbt_md; |
@@ -899,6 +899,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
899 | create = 0; | 899 | create = 0; |
900 | rd = NULL; | 900 | rd = NULL; |
901 | rd2 = NULL; | 901 | rd2 = NULL; |
902 | res = res2 = 0; | ||
902 | /* Per chip or per device? */ | 903 | /* Per chip or per device? */ |
903 | chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; | 904 | chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; |
904 | /* Mirrored table available? */ | 905 | /* Mirrored table available? */ |
@@ -951,11 +952,29 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
951 | } | 952 | } |
952 | 953 | ||
953 | /* Read back first? */ | 954 | /* Read back first? */ |
954 | if (rd) | 955 | if (rd) { |
955 | read_abs_bbt(mtd, buf, rd, chipsel); | 956 | res = read_abs_bbt(mtd, buf, rd, chipsel); |
957 | if (mtd_is_eccerr(res)) { | ||
958 | /* Mark table as invalid */ | ||
959 | rd->pages[i] = -1; | ||
960 | i--; | ||
961 | continue; | ||
962 | } | ||
963 | } | ||
956 | /* If they weren't versioned, read both */ | 964 | /* If they weren't versioned, read both */ |
957 | if (rd2) | 965 | if (rd2) { |
958 | read_abs_bbt(mtd, buf, rd2, chipsel); | 966 | res2 = read_abs_bbt(mtd, buf, rd2, chipsel); |
967 | if (mtd_is_eccerr(res2)) { | ||
968 | /* Mark table as invalid */ | ||
969 | rd2->pages[i] = -1; | ||
970 | i--; | ||
971 | continue; | ||
972 | } | ||
973 | } | ||
974 | |||
975 | /* Scrub the flash table(s)? */ | ||
976 | if (mtd_is_bitflip(res) || mtd_is_bitflip(res2)) | ||
977 | writeops = 0x03; | ||
959 | 978 | ||
960 | /* Write the bad block table to the device? */ | 979 | /* Write the bad block table to the device? */ |
961 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | 980 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { |