mtd: nand: wait to set BBT version

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Mon Nov 7 11:59:35 EST 2011


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=dadc17a3e34810ed411a62e6b4cafdf3e5e1d5c8
Commit:     dadc17a3e34810ed411a62e6b4cafdf3e5e1d5c8
Parent:     623978de362a5faeb18d8395fa86089650642626
Author:     Brian Norris <computersforpeace at gmail.com>
AuthorDate: Tue Sep 20 18:35:57 2011 -0700
Committer:  Artem Bityutskiy <artem.bityutskiy at intel.com>
CommitDate: Wed Sep 21 09:19:08 2011 +0300

    mtd: nand: wait to set BBT version
    
    Because there are so many cases of checking, writing, and re-writing of
    the bad block table(s), we might as well wait until the we've settled on
    a valid, clean copy of the table. This also prevents us from falsely
    incrementing the table version. For example, we may have the following:
    
      Primary table, with version 0x02
      Mirror table, with version 0x01
      Primary table has uncorrectable ECC errors
    
    If we don't have this fix applied, then we will:
    
      Choose to read the primary table (higher version)
      Set mirror table version to 0x02
      Read back primary table
      Invalidate table because of ECC errors
      Retry readback operation with mirror table, now version 0x02
      Mirrored table reads cleanly
      Writeback BBT to primary table location (with "version 0x02")
    
    However, the mirrored table shouldn't have a new version number.
    Instead, we actually want:
    
      Choose to read the primary table (higher version)
      Read back primary table
      Invalidate table because of ECC errors
      Retry readback with mirror table (version 0x01)
      Mirrored table reads cleanly
      Set both tables to version 0x01
      Writeback BBT to primary table location (version 0x01)
    
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
    Signed-off-by: Artem Bityutskiy <artem.bityutskiy at intel.com>
---
 drivers/mtd/nand/nand_bbt.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 11185aa..e7976c7 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -909,11 +909,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 				writeops = 0x03;
 			} else if (td->pages[i] == -1) {
 				rd = md;
-				td->version[i] = md->version[i];
 				writeops = 0x01;
 			} else if (md->pages[i] == -1) {
 				rd = td;
-				md->version[i] = td->version[i];
 				writeops = 0x02;
 			} else if (td->version[i] == md->version[i]) {
 				rd = td;
@@ -921,11 +919,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 					rd2 = md;
 			} else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
 				rd = td;
-				md->version[i] = td->version[i];
 				writeops = 0x02;
 			} else {
 				rd = md;
-				td->version[i] = md->version[i];
 				writeops = 0x01;
 			}
 		} else {
@@ -957,6 +953,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 			if (mtd_is_eccerr(res)) {
 				/* Mark table as invalid */
 				rd->pages[i] = -1;
+				rd->version[i] = 0;
 				i--;
 				continue;
 			}
@@ -967,6 +964,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 			if (mtd_is_eccerr(res2)) {
 				/* Mark table as invalid */
 				rd2->pages[i] = -1;
+				rd2->version[i] = 0;
 				i--;
 				continue;
 			}
@@ -976,6 +974,12 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 		if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
 			writeops = 0x03;
 
+		/* Update version numbers before writing */
+		if (md) {
+			td->version[i] = max(td->version[i], md->version[i]);
+			md->version[i] = td->version[i];
+		}
+
 		/* Write the bad block table to the device? */
 		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
 			res = write_bbt(mtd, buf, td, md, chipsel);



More information about the linux-mtd-cvs mailing list