From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AEC9EC433EF for ; Wed, 27 Apr 2022 05:51:07 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A926C83EA1; Wed, 27 Apr 2022 07:50:56 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=amarulasolutions.com header.i=@amarulasolutions.com header.b="YGzmpWO6"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 16C6883EAB; Wed, 27 Apr 2022 07:50:41 +0200 (CEST) Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 12AA983E58 for ; Wed, 27 Apr 2022 07:50:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=michael@amarulasolutions.com Received: by mail-wr1-x431.google.com with SMTP id t6so936732wra.4 for ; Tue, 26 Apr 2022 22:50:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=slBEq+VJu8+Rnjie67otHcADstqycRrEYW0dYS2dtX0=; b=YGzmpWO69aKHc32oq42B63z9j7ZybfAUOI9ae0WjOg7LdNoK/UU1hpc1Rg93RyCiia vtVAK4j9ryaCYJAlf7DExPW12Q3XTNuJGbtu0AwFZg+kWc7Cz8flAnSOE7OUWiEI/TDY 3AZtNShol4XJhn63uoRhWDRNpgnb2TTxAaHy8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=slBEq+VJu8+Rnjie67otHcADstqycRrEYW0dYS2dtX0=; b=QK1ghgGcAdzQ7KT5TPucyuJW8yTJgnFzV2kzNuOtTT0l52csrgWRSvQNPBfwbQQwaP b4Kj366eMiWvwh7MnWiYi2rG/szhQ9v+gbwJWd6UtQKAKQ6fyo29jLbcRkDsTIdYHyWn Usn5Rw25jkPf1zPV79W7fpiLqYWmjzXqqKcKKt0J/sYEp8CCltRwtHJ2JwtuSUi3E/8M uluDsEDc8+9dKAaRGMxcBHJ9GfEQj1jCSaHm4RXTp4j5tfpxkbDQDbieVv4K7zJ0vmVG I2KaO/9/Rg08f6I57qQ+triIMce1lg6vWVDlF3oLc8J2jzGB7w3yXzsc7Ji0ze6zNCLx l7ig== X-Gm-Message-State: AOAM531kTXFqUlzlt/PFO6tcemlVgLeR7qLR1ZBxx9F2ytKLCydCP0P4 wvl8q1vE4Wj4i3Com5Dx7P8oTMIZJyv/kw== X-Google-Smtp-Source: ABdhPJymVlb8hVXZXtlBOGR44ospU95sdDUfiwYFtbGcrATqJkVX6PSFcBiguCl1+oxRhJgTikBOMQ== X-Received: by 2002:adf:f845:0:b0:20a:d120:4af1 with SMTP id d5-20020adff845000000b0020ad1204af1mr15974849wrq.644.1651038635580; Tue, 26 Apr 2022 22:50:35 -0700 (PDT) Received: from panicking.amarulasolutions.com ([5.171.215.247]) by smtp.gmail.com with ESMTPSA id f11-20020a7bcc0b000000b0037e0c362b6dsm769827wmh.31.2022.04.26.22.50.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Apr 2022 22:50:35 -0700 (PDT) From: Michael Trimarchi To: Han Xu , U-Boot-Denx Cc: Ye Li , Stefano Babic , Miquel Raynal , Fabio Estevam , Dario Binacchi , Sean Anderson , linux-kernel@amarulasolutions.com, Jagan Teki , Ariel D'Alessandro , Fabio Estevam Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Date: Wed, 27 Apr 2022 07:50:23 +0200 Message-Id: <20220427055025.231586-3-michael@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220427055025.231586-1-michael@amarulasolutions.com> References: <20220427055025.231586-1-michael@amarulasolutions.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean The specific implementation was having bug. Those bugs are since the beginning of the implementation. Some manufactures can receive this bug in their SPL code. This bug start to be more visible on architecture that has complicated boot process like imx8mn. Older version of uboot has the same problem only if the bad block appear in correspoding of befine of u-boot image. In order to adjust the function we scan from the first block. The logic is not changed to have a simple way to fix without get regression. The problematic part of old code was in this part: while (is_badblock(mtd, offs, 1)) { page = page + nand_page_per_block; /* Check i we've reached the end of flash. */ if (page >= mtd->size >> chip->page_shift) { free(page_buf); return -ENOMEM; } } Even we fix it adding increment of the offset of one erase block size we don't fix the problem, because the first erase block where the image start is not checked. The code was tested on an imx8mn where the boot rom api was not able to skip it. Apart of that other architecure are using this code and all boards that has nand as boot device can be affected Cc: Han Xu Cc: Fabio Estevam Signed-off-by: Michael Trimarchi --- V1->V2: - Adjust the commit message - Add Cc Han Xu and Fabio - fix size >= 0 to > 0 --- drivers/mtd/nand/raw/mxs_nand_spl.c | 90 ++++++++++++++++------------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c index 59a67ee414..2bfb181007 100644 --- a/drivers/mtd/nand/raw/mxs_nand_spl.c +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c @@ -218,14 +218,14 @@ void nand_init(void) mxs_nand_setup_ecc(mtd); } -int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf) +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) { - struct nand_chip *chip; - unsigned int page; + unsigned int sz; + unsigned int block, lastblock; + unsigned int page, page_offset; unsigned int nand_page_per_block; - unsigned int sz = 0; + struct nand_chip *chip; u8 *page_buf = NULL; - u32 page_off; chip = mtd_to_nand(mtd); if (!chip->numchips) @@ -235,47 +235,42 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf) if (!page_buf) return -ENOMEM; - page = offs >> chip->page_shift; - page_off = offs & (mtd->writesize - 1); + /* offs has to be aligned to a page address! */ + block = offs / mtd->erasesize; + lastblock = (offs + size - 1) / mtd->erasesize; + page = (offs % mtd->erasesize) / mtd->writesize; + page_offset = offs % mtd->writesize; nand_page_per_block = mtd->erasesize / mtd->writesize; - debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page); - - while (size) { - if (mxs_read_page_ecc(mtd, page_buf, page) < 0) - return -1; - - if (size > (mtd->writesize - page_off)) - sz = (mtd->writesize - page_off); - else - sz = size; - - memcpy(buf, page_buf + page_off, sz); - - offs += mtd->writesize; - page++; - buf += (mtd->writesize - page_off); - page_off = 0; - size -= sz; - - /* - * Check if we have crossed a block boundary, and if so - * check for bad block. - */ - if (!(page % nand_page_per_block)) { - /* - * Yes, new block. See if this block is good. If not, - * loop until we find a good block. - */ - while (is_badblock(mtd, offs, 1)) { - page = page + nand_page_per_block; - /* Check i we've reached the end of flash. */ - if (page >= mtd->size >> chip->page_shift) { + while (block <= lastblock && size > 0) { + if (!is_badblock(mtd, mtd->erasesize * block, 1)) { + /* Skip bad blocks */ + while (page < nand_page_per_block) { + int curr_page = nand_page_per_block * block + page; + + if (mxs_read_page_ecc(mtd, page_buf, curr_page) < 0) { free(page_buf); - return -ENOMEM; + return -EIO; } + + if (size > (mtd->writesize - page_offset)) + sz = (mtd->writesize - page_offset); + else + sz = size; + + memcpy(dst, page_buf + page_offset, sz); + dst += sz; + size -= sz; + page_offset = 0; + page++; } + + page = 0; + } else { + lastblock++; } + + block++; } free(page_buf); @@ -294,6 +289,19 @@ void nand_deselect(void) u32 nand_spl_adjust_offset(u32 sector, u32 offs) { - /* Handle the offset adjust in nand_spl_load_image,*/ + unsigned int block, lastblock; + + block = sector / mtd->erasesize; + lastblock = (sector + offs) / mtd->erasesize; + + while (block <= lastblock) { + if (is_badblock(mtd, block * mtd->erasesize, 1)) { + offs += mtd->erasesize; + lastblock++; + } + + block++; + } + return offs; } -- 2.25.1