]> git.karo-electronics.de Git - linux-beck.git/commitdiff
mtd: nand: wait to set BBT version
authorBrian Norris <computersforpeace@gmail.com>
Wed, 21 Sep 2011 01:35:57 +0000 (18:35 -0700)
committerArtem Bityutskiy <artem.bityutskiy@intel.com>
Wed, 21 Sep 2011 06:19:08 +0000 (09:19 +0300)
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@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
drivers/mtd/nand/nand_bbt.c

index 11185aa6273c8764ffed2148542a2e18f49401d4..e7976c7a7bb01f14dd57f45ba7a4056d987e50c7 100644 (file)
@@ -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);