public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v2] mtd: nand: write bad block marker even with BBT
@ 2011-12-19 22:03 Brian Norris
  2011-12-19 22:16 ` Brian Norris
  2011-12-20  8:49 ` Sebastian Andrzej Siewior
  0 siblings, 2 replies; 8+ messages in thread
From: Brian Norris @ 2011-12-19 22:03 UTC (permalink / raw)
  To: linux-mtd
  Cc: Randy Dunlap, Baruch Siach, Dan Carpenter,
	Sebastian Andrzej Siewior, Nicolas Ferre, Dominik Brodowski,
	Barry Song, Gabor Juhos, Guillaume LECERF, Jonas Gorski,
	Jamie Iles, Ivan Djelic, Robert Jarzmik, David Woodhouse,
	Maxim Levitsky, Dmitry Eremin-Solenikov, Kevin Cernekee,
	Kulikov Vasiliy, Jim Quinlan, Andres Salomon, Axel Lin,
	Anatolij Gustschin, Mike Frysinger, Arnd Bergmann, Lei Wen,
	Sascha Hauer, Sukumar Ghorai, Artem Bityutskiy, Florian Fainelli,
	Peter Wippich, Matthieu CASTET, Kyungmin Park, Shmulik Ladkani,
	Wolfram Sang, Chuanxiao Dong, Joe Perches, Brian Norris,
	Roman Tereshonkov, Adrian Hunter

Currently, the flash-based BBT implementation writes bad block data only
to its flash-based table and not to the OOB marker area. Then, as new
bad blocks are marked over time, the OOB markers become out of date and
the flash-based table becomes the only source of current bad block
information. This can be a problem when:

 * bootloader cannot read the flash-based BBT format
 * BBT is corrupted and the flash must be rescanned for bad
   blocks; we want to remember bad blocks that were marked from Linux

In an attempt to keep the bad block markers in sync with the flash-based
BBT, this patch changes the default so that we write bad block markers
to the proper OOB area on each block in addition to flash-based BBT.

Theoretically, the bad block table and the OOB markers can still get out
of sync if the system experiences a power cut between writing the BBT to
flash and writing the OOB marker to a newly-marked bad block. However,
this is a relatively unlikely event, as new bad blocks shouldn't appear
frequently.

Note that this is a change from the previous default flash-based BBT
behavior. If any contributors rely on the old behavior, they are welcome
to introduce an option flag for it.

Adapted from code by Matthieu Castet.

Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
v2: Explain potential power cut issues and remove option for retaining
    old behavior. I CC'd various MTD contributors; speak up if the new
    default is unacceptable!

drivers/mtd/nand/nand_base.c |   59 +++++++++++++++++++++++------------------
 1 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 35b4565..dfa017e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -393,6 +393,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	struct nand_chip *chip = mtd->priv;
 	uint8_t buf[2] = { 0, 0 };
 	int block, ret, i = 0;
+	struct mtd_oob_ops ops;
 
 	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
@@ -403,34 +404,40 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
 	/* Do we have a flash based bad block table? */
-	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
 		ret = nand_update_bbt(mtd, ofs);
-	else {
-		struct mtd_oob_ops ops;
+		if (ret)
+			return ret;
+	}
 
-		nand_get_device(chip, mtd, FL_WRITING);
+	/*
+	 * Write bad block marker to OOB
+	 * Note that a flash-based BBT (when used) can become out of sync with
+	 * OOB markers if a power cut occurs here. See:
+	 *   http://lists.infradead.org/pipermail/linux-mtd/2011-December/038851.html
+	 */
 
-		/*
-		 * Write to first two pages if necessary. If we write to more
-		 * than one location, the first error encountered quits the
-		 * procedure. We write two bytes per location, so we dont have
-		 * to mess with 16 bit access.
-		 */
-		ops.len = ops.ooblen = 2;
-		ops.datbuf = NULL;
-		ops.oobbuf = buf;
-		ops.ooboffs = chip->badblockpos & ~0x01;
-		ops.mode = MTD_OPS_PLACE_OOB;
-		do {
-			ret = nand_do_write_oob(mtd, ofs, &ops);
-
-			i++;
-			ofs += mtd->writesize;
-		} while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) &&
-				i < 2);
+	nand_get_device(chip, mtd, FL_WRITING);
+
+	/*
+	 * Write to first two pages if necessary. If we write to more than one
+	 * location, the first error encountered quits the procedure. We write
+	 * two bytes per location, so we dont have to mess with 16 bit access.
+	 */
+	ops.len = ops.ooblen = 2;
+	ops.datbuf = NULL;
+	ops.oobbuf = buf;
+	ops.ooboffs = chip->badblockpos & ~0x01;
+	ops.mode = MTD_OPS_PLACE_OOB;
+	do {
+		ret = nand_do_write_oob(mtd, ofs, &ops);
+
+		i++;
+		ofs += mtd->writesize;
+	} while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+
+	nand_release_device(mtd);
 
-		nand_release_device(mtd);
-	}
 	if (!ret)
 		mtd->ecc_stats.badblocks++;
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-01-06  3:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-19 22:03 [PATCH v2] mtd: nand: write bad block marker even with BBT Brian Norris
2011-12-19 22:16 ` Brian Norris
2011-12-20  8:49 ` Sebastian Andrzej Siewior
2011-12-20 18:17   ` Brian Norris
2011-12-20 20:49     ` Artem Bityutskiy
2011-12-22  1:15       ` Brian Norris
2011-12-23  8:13         ` Shmulik Ladkani
2012-01-06  3:10           ` Brian Norris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox