From patchwork Fri Aug 12 17:54:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyle Roeschley X-Patchwork-Id: 658746 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 3s9sy667d6z9sXy for ; Sat, 13 Aug 2016 03:56:14 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bYGfC-0002l4-NB; Fri, 12 Aug 2016 17:54:34 +0000 Received: from skprod3.natinst.com ([130.164.80.24] helo=ni.com) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bYGf9-0002g2-GV for linux-mtd@lists.infradead.org; Fri, 12 Aug 2016 17:54:32 +0000 Received: from us-aus-mgwout2.amer.corp.natinst.com (nb-snip2-1338.natinst.com [130.164.19.135]) by us-aus-skprod3.natinst.com (8.15.0.59/8.15.0.59) with ESMTP id u7CHrelL008268; Fri, 12 Aug 2016 12:53:40 -0500 Received: from senary.amer.corp.natinst.com ([130.164.14.198]) by us-aus-mgwout2.amer.corp.natinst.com (Lotus Domino Release 8.5.3FP6 HF1218) with ESMTP id 2016081212534049-995240 ; Fri, 12 Aug 2016 12:53:40 -0500 From: Kyle Roeschley To: boris.brezillon@free-electrons.com, richard@nod.at Subject: [PATCH v6 1/2] mtd: nand_bbt: Move BBT block selection logic out of write_bbt() Date: Fri, 12 Aug 2016 12:54:49 -0500 Message-Id: <1471024490-32348-1-git-send-email-kyle.roeschley@ni.com> X-Mailer: git-send-email 2.8.1 X-MIMETrack: Itemize by SMTP Server on US-AUS-MGWOut2/AUS/H/NIC(Release 8.5.3FP6 HF1218|December 12, 2014) at 08/12/2016 12:53:40 PM, Serialize by Router on US-AUS-MGWOut2/AUS/H/NIC(Release 8.5.3FP6 HF1218|December 12, 2014) at 08/12/2016 12:53:40 PM, Serialize complete at 08/12/2016 12:53:40 PM X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-08-12_08:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160812_105431_710145_27DE137F X-CRM114-Status: GOOD ( 18.24 ) 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.24 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 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: nathan.sullivan@ni.com, xander.huff@ni.com, linux-kernel@vger.kernel.org, peterpansjtu@gmail.com, linux-mtd@lists.infradead.org, computersforpeace@gmail.com, dwmw2@infradead.org, beanhuo@micron.com MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Boris Brezillon This clarifies the write_bbt() by removing the write label and clarifying the error/exit path. Signed-off-by: Boris Brezillon --- v6: Split functionality of write_bbt out into new functions v5: De-duplicate bad block handling v4: Don't ignore write protection while marking bad BBT blocks Correctly call block_markbad Minor cleanups v3: Don't overload mtd->priv Keep nand_erase_nand from erroring on protected BBT blocks v2: Mark OOB area in each block as well as BBT Avoid marking read-only, bad address, or known bad blocks as bad drivers/mtd/nand/nand_bbt.c | 108 ++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 2fbb523..19f97e9 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -605,6 +605,69 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf, } /** + * get_bbt_block - Get the first valid eraseblock suitable to store a BBT + * @this: the NAND device + * @td: the BBT description + * @md: the mirror BBT descriptor + * @chip: the CHIP selector + * + * This functions returns a positive block number pointing a valid eraseblock + * suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if + * all blocks are already used of marked bad. If td->pages[chip] was already + * pointing to a valid block we re-use it, otherwise we search for the next + * valid one. + */ +static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, + struct nand_bbt_descr *md, int chip) +{ + int startblock, dir, page, numblocks, i; + + /* + * There was already a version of the table, reuse the page. This + * applies for absolute placement too, as we have the page number in + * td->pages. + */ + if (td->pages[chip] != -1) + return td->pages[chip] >> + (this->bbt_erase_shift - this->page_shift); + + numblocks = (int)(this->chipsize >> this->bbt_erase_shift); + if (!(td->options & NAND_BBT_PERCHIP)) + numblocks *= this->numchips; + + /* + * Automatic placement of the bad block table. Search direction + * top -> down? + */ + if (td->options & NAND_BBT_LASTBLOCK) { + startblock = numblocks * (chip + 1) - 1; + dir = -1; + } else { + startblock = chip * numblocks; + dir = 1; + } + + for (i = 0; i < td->maxblocks; i++) { + int block = startblock + dir * i; + + /* Check, if the block is bad */ + switch (bbt_get_entry(this, block)) { + case BBT_BLOCK_WORN: + case BBT_BLOCK_FACTORY_BAD: + continue; + } + + page = block << (this->bbt_erase_shift - this->page_shift); + + /* Check, if the block is used by the mirror table */ + if (!md || md->pages[chip] != page) + return block; + } + + return -ENOSPC; +} + +/** * write_bbt - [GENERIC] (Re)write the bad block table * @mtd: MTD device structure * @buf: temporary buffer @@ -621,7 +684,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_chip *this = mtd_to_nand(mtd); struct erase_info einfo; int i, res, chip = 0; - int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; + int bits, page, offs, numblocks, sft, sftmsk; int nrchips, pageoffs, ooboffs; uint8_t msk[4]; uint8_t rcode = td->reserved_block_code; @@ -653,45 +716,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, /* Loop through the chips */ for (; chip < nrchips; chip++) { - /* - * There was already a version of the table, reuse the page - * This applies for absolute placement too, as we have the - * page nr. in td->pages. - */ - if (td->pages[chip] != -1) { - page = td->pages[chip]; - goto write; - } - - /* - * Automatic placement of the bad block table. Search direction - * top -> down? - */ - if (td->options & NAND_BBT_LASTBLOCK) { - startblock = numblocks * (chip + 1) - 1; - dir = -1; - } else { - startblock = chip * numblocks; - dir = 1; - } + int block; - for (i = 0; i < td->maxblocks; i++) { - int block = startblock + dir * i; - /* Check, if the block is bad */ - switch (bbt_get_entry(this, block)) { - case BBT_BLOCK_WORN: - case BBT_BLOCK_FACTORY_BAD: - continue; - } - page = block << - (this->bbt_erase_shift - this->page_shift); - /* Check, if the block is used by the mirror table */ - if (!md || md->pages[chip] != page) - goto write; + block = get_bbt_block(this, td, md, chip); + if (block < 0) { + pr_err("No space left to write bad block table\n"); + res = block; + goto outerr; } - pr_err("No space left to write bad block table\n"); - return -ENOSPC; - write: /* Set up shift count and masks for the flash table */ bits = td->options & NAND_BBT_NRBITS_MSK;