From patchwork Tue Jul 7 16:00:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xander Huff X-Patchwork-Id: 492369 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id CF6321402C8 for ; Wed, 8 Jul 2015 02:02:59 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZCVIn-0005jB-UE; Tue, 07 Jul 2015 16:00:57 +0000 Received: from skprod2.natinst.com ([130.164.80.23] helo=ni.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZCVIm-0005gT-8u; Tue, 07 Jul 2015 16:00:56 +0000 Received: from us-aus-mgwout1.amer.corp.natinst.com (nb-chan1-1338.natinst.com [130.164.19.134]) by us-aus-skprod2.natinst.com (8.15.0.59/8.15.0.59) with ESMTP id t67G0VcM012926; Tue, 7 Jul 2015 11:00:31 -0500 Received: from xander-mint.amer.corp.natinst.com ([130.164.14.198]) by us-aus-mgwout1.amer.corp.natinst.com (Lotus Domino Release 8.5.3FP6 HF1218) with ESMTP id 2015070711003101-720636 ; Tue, 7 Jul 2015 11:00:31 -0500 From: Xander Huff To: dwmw2@infradead.org, computersforpeace@gmail.com Subject: [PATCH v2] mtd: nand_bbt: scan for next free bbt block if writing bbt fails Date: Tue, 7 Jul 2015 11:00:03 -0500 Message-Id: <1436284803-16081-1-git-send-email-xander.huff@ni.com> X-Mailer: git-send-email 1.9.1 X-MIMETrack: Itemize by SMTP Server on US-AUS-MGWOut1/AUS/H/NIC(Release 8.5.3FP6 HF1218|December 12, 2014) at 07/07/2015 11:00:31 AM, Serialize by Router on US-AUS-MGWOut1/AUS/H/NIC(Release 8.5.3FP6 HF1218|December 12, 2014) at 07/07/2015 11:00:31 AM, Serialize complete at 07/07/2015 11:00:31 AM X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2015-07-07_06:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150707_090056_433427_FE2411A4 X-CRM114-Status: GOOD ( 14.61 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [130.164.80.23 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H4 RBL: Very Good reputation (+4) [130.164.80.23 listed in wl.mailspike.net] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ben Shelton , jaeden.amero@ni.com, linux-mtd@lists.infradead.org, jeff.westfahl@ni.com, joshc@ni.com MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Ben Shelton If erasing or writing the BBT fails, we should mark the current BBT block as bad and use the BBT descriptor to scan for the next available unused block in the BBT. We should only return a failure if there isn't any space left. Based on original code implemented by Jeff Westfahl . Signed-off-by: Ben Shelton Reviewed-by: Jaeden Amero Suggested-by: Jeff Westfahl --- This v2 patch is in reply to comments from Brian Norris on 7/22/13. See the following links for context: http://lists.infradead.org/pipermail/linux-mtd/2013-July/047596.html http://patchwork.ozlabs.org/patch/244324/ --- drivers/mtd/nand/nand_base.c | 4 ++++ drivers/mtd/nand/nand_bbt.c | 34 ++++++++++++++++++++++++++++++++-- include/linux/mtd/nand.h | 7 +++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ceb68ca..48299dc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2761,6 +2761,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, pr_debug("%s: device is write protected!\n", __func__); instr->state = MTD_ERASE_FAILED; + instr->priv = NAND_ERASE_WRITE_PROTECTED; goto erase_exit; } @@ -2776,6 +2777,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", __func__, page); instr->state = MTD_ERASE_FAILED; + instr->priv = NAND_ERASE_BAD_BLOCK; goto erase_exit; } @@ -2802,6 +2804,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, pr_debug("%s: failed erase, page 0x%08x\n", __func__, page); instr->state = MTD_ERASE_FAILED; + instr->priv = NAND_ERASE_BLOCK_ERASE_FAILED; instr->fail_addr = ((loff_t)page << chip->page_shift); goto erase_exit; @@ -2819,6 +2822,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, } } instr->state = MTD_ERASE_DONE; + instr->priv = NAND_ERASE_OK; erase_exit: diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 63a1a36..09f9e62 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -662,6 +662,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, page = td->pages[chip]; goto write; } +next: /* * Automatic placement of the bad block table. Search direction @@ -787,13 +788,42 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, einfo.addr = to; einfo.len = 1 << this->bbt_erase_shift; res = nand_erase_nand(mtd, &einfo, 1); - if (res < 0) + if (res == -EIO && einfo.state == MTD_ERASE_FAILED + && einfo.priv == NAND_ERASE_BLOCK_ERASE_FAILED) { + /* This block is bad. Mark it as such and see if + * there's another block available in the BBT area. */ + int block = page >> + (this->bbt_erase_shift - this->page_shift); + pr_info("nand_bbt: failed to erase block %d when writing BBT\n", + block); + bbt_mark_entry(this, block, BBT_BLOCK_WORN); + + res = this->block_markbad(mtd, block); + if (res) + pr_warn("nand_bbt: error %d while marking block %d bad\n", + res, block); + goto next; + } else if (res < 0) goto outerr; res = scan_write_bbt(mtd, to, len, buf, td->options & NAND_BBT_NO_OOB ? NULL : &buf[len]); - if (res < 0) + if (res == -EIO) { + /* This block is bad. Mark it as such and see if + * there's another block available in the BBT area. */ + int block = page >> + (this->bbt_erase_shift - this->page_shift); + pr_info("nand_bbt: failed to erase block %d when writing BBT\n", + block); + bbt_mark_entry(this, block, BBT_BLOCK_WORN); + + res = this->block_markbad(mtd, block); + if (res) + pr_warn("nand_bbt: error %d while marking block %d bad\n", + res, block); + goto next; + } else if (res < 0) goto outerr; pr_info("Bad block table written to 0x%012llx, version 0x%02X\n", diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index f25e2bd..fba8d5a 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1030,4 +1030,11 @@ struct nand_sdr_timings { /* get timing characteristics from ONFI timing mode. */ const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode); + +/* reasons for erase failures */ +#define NAND_ERASE_OK 0 +#define NAND_ERASE_WRITE_PROTECTED 1 +#define NAND_ERASE_BAD_BLOCK 2 +#define NAND_ERASE_BLOCK_ERASE_FAILED 3 + #endif /* __LINUX_MTD_NAND_H */