From patchwork Mon Dec 19 22:03:51 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Norris X-Patchwork-Id: 132324 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:4978:20e::2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9A6A8B705D for ; Tue, 20 Dec 2011 09:07:30 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1RclLd-0007N6-4z; Mon, 19 Dec 2011 22:06:17 +0000 Received: from mail-iy0-f177.google.com ([209.85.210.177]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1RclLa-0007Ms-Qz for linux-mtd@lists.infradead.org; Mon, 19 Dec 2011 22:06:15 +0000 Received: by iadk27 with SMTP id k27so9184427iad.36 for ; Mon, 19 Dec 2011 14:06:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; bh=EjZ5ck7P8+bHE/u2RJUQI3SbouOd4FTn6psLvQiDYGc=; b=eMac+gNt4oq2kN/gB7TYvbIxnGMRLn8aZtJ2+X3iQbdgBBQbIS2ZjGT8IzapKcCqE9 H0QeX1pbUijHbrVMzohZn/I/YrKaLRMZlmRBBo4rVHDdHrIrUSxD4oM9Q/jZsu6GYBi1 q92qU9nQNMeBnR9gg4P7uup0q4tHmCQEuYKdo= Received: by 10.50.188.129 with SMTP id ga1mr28946474igc.69.1324332371501; Mon, 19 Dec 2011 14:06:11 -0800 (PST) Received: from localhost.localdomain (cpe-76-174-190-12.socal.res.rr.com. [76.174.190.12]) by mx.google.com with ESMTPS id f2sm59384482ibg.9.2011.12.19.14.06.04 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Dec 2011 14:06:10 -0800 (PST) From: Brian Norris To: Subject: [PATCH v2] mtd: nand: write bad block marker even with BBT Date: Mon, 19 Dec 2011 14:03:51 -0800 Message-Id: <1324332231-30884-1-git-send-email-computersforpeace@gmail.com> X-Mailer: git-send-email 1.7.5.4 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (computersforpeace[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 SINGLE_HEADER_1K A single header contains 1K-2K characters 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 X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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 --- 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++;