From patchwork Tue Mar 25 08:19:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 27010 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f197.google.com (mail-ve0-f197.google.com [209.85.128.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 05A5620062 for ; Tue, 25 Mar 2014 08:46:06 +0000 (UTC) Received: by mail-ve0-f197.google.com with SMTP id pa12sf352733veb.0 for ; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=uMo0zacGCWhgJx+rGmFrri384NWbt7L3fSIoOI8sKZ0=; b=hL32u3WEs0+Oip5qFN7o+CXSKJHb4gFtZ2ELsPJGXcywU6c32SXByAWOwebZVsMFpW WSFTQLQCI6QNy1n3LetxwgiW3rqVqdlOGmwpEnMuBMTOohe097n7vATeFOFKgo+kXQ/F UT6FN0Ic/hsweKzgGNP3i3rr1CHA8M3dzCFLggS95rRfSZ4kt03Hl3hpeXRKFprN6jm2 lYYGNi9WqSe3O29l1CPfOCKVBNycJotn1mUM5EDJbS0s++H+7+1kfoMBCs/4+3BTwjDj Ia+3JVm/7v7u4JeW2olCocGEOBR/MdL5m+6a9FtMSvHnmFvfITqk3UGn9NKa5GTQnFvd u7Yg== X-Gm-Message-State: ALoCoQmYP60FGNjVqIR2dsukSQz1fN0TAgT3HPaZmTY77KKUB7gEomzj/P8JMmCz0f8Etv6DEtuA X-Received: by 10.52.236.231 with SMTP id ux7mr24413554vdc.7.1395737166741; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.25.196 with SMTP id 62ls125817qgt.76.gmail; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) X-Received: by 10.221.61.210 with SMTP id wx18mr291833vcb.27.1395737166618; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) Received: from mail-vc0-f170.google.com (mail-vc0-f170.google.com [209.85.220.170]) by mx.google.com with ESMTPS id dl6si3589873veb.127.2014.03.25.01.46.06 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 01:46:06 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.170 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.170; Received: by mail-vc0-f170.google.com with SMTP id hu19so157199vcb.15 for ; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) X-Received: by 10.220.88.204 with SMTP id b12mr53934233vcm.3.1395737166540; Tue, 25 Mar 2014 01:46:06 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.78.9 with SMTP id i9csp286658vck; Tue, 25 Mar 2014 01:46:05 -0700 (PDT) X-Received: by 10.68.216.101 with SMTP id op5mr9310728pbc.148.1395737165183; Tue, 25 Mar 2014 01:46:05 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f8si10947188pbc.71.2014.03.25.01.46.04; Tue, 25 Mar 2014 01:46:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754433AbaCYIpw (ORCPT + 26 others); Tue, 25 Mar 2014 04:45:52 -0400 Received: from mail-wg0-f46.google.com ([74.125.82.46]:44347 "EHLO mail-wg0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753023AbaCYIVN (ORCPT ); Tue, 25 Mar 2014 04:21:13 -0400 Received: by mail-wg0-f46.google.com with SMTP id b13so79287wgh.29 for ; Tue, 25 Mar 2014 01:21:12 -0700 (PDT) X-Received: by 10.180.72.239 with SMTP id g15mr21513169wiv.45.1395735671897; Tue, 25 Mar 2014 01:21:11 -0700 (PDT) Received: from lee--X1.home (host109-148-113-193.range109-148.btcentralplus.com. [109.148.113.193]) by mx.google.com with ESMTPSA id k4sm5567676wib.19.2014.03.25.01.21.09 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 01:21:10 -0700 (PDT) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: lee.jones@linaro.org, kernel@stlinux.com, computersforpeace@gmail.com, linux-mtd@lists.infradead.org, dwmw2@infradead.org, angus.clark@st.com, pekon@ti.com Subject: [RFC 28/47] mtd: nand: stm_nand_bch: update flash-resident BBT(s) Date: Tue, 25 Mar 2014 08:19:45 +0000 Message-Id: <1395735604-26706-29-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395735604-26706-1-git-send-email-lee.jones@linaro.org> References: <1395735604-26706-1-git-send-email-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lee.jones@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.170 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Search for suitable block, erase and write table data to flash. If any errors occur on selected block, mark it as bad and select another one. Keep trying until both the Primary and Mirror BBTs are a) synced and b) written successfully to flash. Signed-off-by: Lee Jones --- drivers/mtd/nand/stm_nand_bch.c | 143 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/drivers/mtd/nand/stm_nand_bch.c b/drivers/mtd/nand/stm_nand_bch.c index 76ed99b..a4f3e46 100644 --- a/drivers/mtd/nand/stm_nand_bch.c +++ b/drivers/mtd/nand/stm_nand_bch.c @@ -59,6 +59,11 @@ static uint8_t ibbt_sigs[2][NAND_IBBT_SIGLEN] = { {'1', 't', 'b', 'B'}, }; +static char *bbt_strs[] = { + "primary", + "mirror", +}; + /* IBBT header */ struct nand_ibbt_header { uint8_t signature[4]; /* "Bbt0" or "1tbB" signature */ @@ -570,6 +575,144 @@ static int bch_write_bbt_data(struct nandi_controller *nandi, return 0; } +/* + * Update Flash-resident BBT: + * erase/search suitable block, and write table data to Flash + */ +static int bch_update_bbt(struct nandi_controller *nandi, + struct nandi_bbt_info *bbt_info, + int bak, uint8_t vers) +{ + loff_t offs; + uint32_t block; + uint32_t block_lower; + uint32_t block_other; + + block_other = bbt_info->bbt_block[(bak+1)%2]; + block_lower = nandi->blocks_per_device - NAND_IBBT_NBLOCKS; + + for (block = bbt_info->bbt_block[bak]; block >= block_lower; block--) { + offs = (loff_t)block << nandi->block_shift; + + /* Skip if block used by other table */ + if (block == block_other) + continue; + + /* Skip if block is marked bad */ + if (bbt_is_block_bad(bbt_info->bbt, block)) + continue; + + /* Erase block, mark bad and skip on failure */ + if (bch_erase_block(nandi, offs) & NAND_STATUS_FAIL) { + dev_info(nandi->dev, + "failed to erase block [%u:0x%012llx] while updating BBT\n", + block, offs); + vers++; + bbt_set_block_mark(bbt_info->bbt, block, + BBT_MARK_BAD_WEAR); + continue; + } + + /* Write BBT, mark bad and skip on failure */ + if (bch_write_bbt_data(nandi, bbt_info, block, bak, vers)) { + dev_info(nandi->dev, + "failed to write BBT to block [%u:0x%012llx]\n", + block, offs); + vers++; + bbt_set_block_mark(bbt_info->bbt, block, + BBT_MARK_BAD_WEAR); + continue; + } + + /* Success */ + bbt_info->bbt_block[bak] = block; + bbt_info->bbt_vers[bak] = vers; + break; + } + + /* No space in BBT area */ + if (block < block_lower) { + dev_err(nandi->dev, "no space left in BBT area\n"); + dev_err(nandi->dev, "failed to update %s BBT\n", bbt_strs[bak]); + return -ENOSPC; + } + + dev_info(nandi->dev, "wrote BBT [%s:%u] at 0x%012llx [%u]\n", + bbt_strs[bak], vers, offs, block); + + return 0; +} + +#define NAND_IBBT_UPDATE_PRIMARY 0x1 +#define NAND_IBBT_UPDATE_MIRROR 0x2 +#define NAND_IBBT_UPDATE_BOTH (NAND_IBBT_UPDATE_PRIMARY | \ + NAND_IBBT_UPDATE_MIRROR) +static char *bbt_update_strs[] = { + "", + "primary", + "mirror", + "both", +}; + +/* + * Update Flash-resident BBT(s): + * incrementing 'vers' number if required, and ensuring Primary + * and Mirror are kept in sync + */ +static int bch_update_bbts(struct nandi_controller *nandi, + struct nandi_bbt_info *bbt_info, + unsigned int update, uint8_t vers) +{ + int err; + + dev_info(nandi->dev, "updating %s BBT(s)\n", bbt_update_strs[update]); + + do { + /* Update Primary if specified */ + if (update & NAND_IBBT_UPDATE_PRIMARY) { + err = bch_update_bbt(nandi, bbt_info, NAND_IBBT_PRIMARY, + vers); + /* Bail out on error (e.g. no space left in BBT area) */ + if (err) + return err; + + /* + * If update resulted in a new BBT version + * (e.g. Erase/Write fail on BBT block) update version + * here, and force update of other table. + */ + if (bbt_info->bbt_vers[NAND_IBBT_PRIMARY] != vers) { + vers = bbt_info->bbt_vers[NAND_IBBT_PRIMARY]; + update = NAND_IBBT_UPDATE_MIRROR; + } + } + + /* Update Mirror if specified */ + if (update & NAND_IBBT_UPDATE_MIRROR) { + err = bch_update_bbt(nandi, bbt_info, NAND_IBBT_MIRROR, + vers); + /* Bail out on error (e.g. no space left in BBT area) */ + if (err) + return err; + + /* + * If update resulted in a new BBT version + * (e.g. Erase/Write fail on BBT block) update version + * here, and force update of other table. + */ + if (bbt_info->bbt_vers[NAND_IBBT_MIRROR] != vers) { + vers = bbt_info->bbt_vers[NAND_IBBT_MIRROR]; + update = NAND_IBBT_UPDATE_PRIMARY; + } + } + + /* Continue, until Primary and Mirror versions are in sync */ + } while (bbt_info->bbt_vers[NAND_IBBT_PRIMARY] != + bbt_info->bbt_vers[NAND_IBBT_MIRROR]); + + return 0; +} + /* Scan block for IBBT signature */ static int bch_find_ibbt_sig(struct nandi_controller *nandi, uint32_t block, int *bak, uint8_t *vers,