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 A70C1C433F5 for ; Sun, 15 May 2022 09:36:13 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A0EAF84011; Sun, 15 May 2022 11:35:59 +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="pgGeQV7n"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 55AE283FC8; Sun, 15 May 2022 11:35:52 +0200 (CEST) Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) (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 EE10B840D8 for ; Sun, 15 May 2022 11:35:45 +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-ej1-x635.google.com with SMTP id l18so23521510ejc.7 for ; Sun, 15 May 2022 02:35:45 -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=YWmXIADIm9JSh8WtxwkqZljfFa3HcMwbtQZcEBjjleo=; b=pgGeQV7n5uAuqb0vxuqCrJDQ105viU8PpPyek/Kw12wOHRzdn+BOYFta3wiyzHPWsu cfsSR5nZwUCSwZ6+45JjQYJBHxZ73aB/yYqwBTRKTn18nZY2Gsc193FYX4uTlQDuXtGl deNT56TPKyP/QoFO8HumcVp20PlPY2ODUBJZM= 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=YWmXIADIm9JSh8WtxwkqZljfFa3HcMwbtQZcEBjjleo=; b=UBxHVxWYhmsdEjqtMeyKev02q3PcpuKfs2VLmJXZwfCiWQtHkmtg2FEX0HekykxeQC QfAWXa3nZHzGdsDFFSxFP6ODDLjJjiq8n5YPA2Sncb4TakSdRLjaFdDepPZu9bal+IAK TrtgUEu3pTpoDPZ4sWXYshUMP/avuxdqIdF6pKkAtAIsLEg5yMf1Blz55cRHAOu38sg/ JE/lEcO59xiZdToxdV/4b8bqIztDaZaGk9ohMXQ6n98OR381Pk6EkxPwxilU7Mqdu8b/ jouGT9nqNDXj0aVmYZLqb6U2h8l5HILrwv5gXqi4WiS2jVIHyURr2Hz9szJmCGchYnSP Vv+Q== X-Gm-Message-State: AOAM532WnbVC8DZFown/InNG/MmFa0sJvAYgeyYxaRNWxEVngj+OqOjK Gj/xX7gXAzN1/Q2aPD9yKvMpo9egH8VB0qBd X-Google-Smtp-Source: ABdhPJyeY6nnbJNdci+R+B7eYO5L1MG5cik1Hq1yTJBiaasCVNO4wteIGcVcX1LGVh61tv3PSoKh2A== X-Received: by 2002:a17:906:c114:b0:6f5:db6f:71a1 with SMTP id do20-20020a170906c11400b006f5db6f71a1mr10866183ejc.338.1652607344534; Sun, 15 May 2022 02:35:44 -0700 (PDT) Received: from localhost.localdomain (mob-109-118-140-232.net.vodafone.it. [109.118.140.232]) by smtp.gmail.com with ESMTPSA id p6-20020a17090664c600b006f3ef214de8sm2516582ejn.78.2022.05.15.02.35.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 May 2022 02:35:43 -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-amarula@amarulasolutions.com, Jagan Teki , Ariel D'Alessandro , Tom Rini , Fabio Estevam , Tim Harvey Subject: [PATCH V4 2/5] mtd: nand: mxs_nand_spl: Fix bad block skipping Date: Sun, 15 May 2022 11:35:31 +0200 Message-Id: <20220515093534.1737172-3-michael@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220515093534.1737172-1-michael@amarulasolutions.com> References: <20220515093534.1737172-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 already experience this bug in their SPL code. This bug can be more visible on architecture that has complicated boot process like imx8mn. Older version of uboot can be affected if the bad block appear in correspoding of the beginning of u-boot image. In order to adjust the function we scan from the first erase block. 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. This code is used by other architecures like imx6 and imx8mm Cc: Han Xu Cc: Fabio Estevam Acked-by: Han Xu Tested-By: Tim Harvey Signed-off-by: Michael Trimarchi --- V3->V4: - none V2->V3: - Add tested-by from Tim - Add ack from Han Xu - Rework english of commit message 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