All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/4] MXS nand fixes in SPL
@ 2022-04-27  5:50 Michael Trimarchi
  2022-04-27  5:50 ` [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Michael Trimarchi @ 2022-04-27  5:50 UTC (permalink / raw)
  To: Han Xu, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro

Those patches come after some testing of failing in factory on some
unit. We found out that the bootrom imx loader was not able to handling
badblock. This can be a limit of the implementation right now in imx8mn.
Anyway not all the imx platform has the support of this loader. I found
some problems on the implementation so I have fixed it up according the
experience of Sitara. I tested only using a Fit Image as a flash
container. This version add in the series the fix of cmd_nandbcb and
the fix of spl_nand load. I can imagine that a lot of boards and users
are affected. I have started to backport this changes in some older
uboot and adapt it

Michael Trimarchi (4):
  nand: raw: mxs_nand: Fix specific hook registration
  mtd: nand: mxs_nand_spl: Fix bad block skipping
  arm: mach-imx: cmd_nandbcb fix bad block handling
  spl: spl_nand: Fix bad block handling in fitImage

 arch/arm/mach-imx/cmd_nandbcb.c     | 21 +++----
 common/spl/spl_nand.c               |  5 +-
 drivers/mtd/nand/raw/mxs_nand.c     | 32 +++++-----
 drivers/mtd/nand/raw/mxs_nand_spl.c | 90 ++++++++++++++++-------------
 4 files changed, 73 insertions(+), 75 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration
  2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
@ 2022-04-27  5:50 ` Michael Trimarchi
  2022-05-06 14:40   ` Han Xu
  2022-04-27  5:50 ` [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Michael Trimarchi
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Michael Trimarchi @ 2022-04-27  5:50 UTC (permalink / raw)
  To: Han Xu, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Move the hook after nand_scan_tail is called. The hook must be replaced
to the mxs specific one but those must to be assignment later in the
probe function.

With this fix markbad is working again. Before this change:

nand markbad 0xDEC00
NXS NAND: Writing OOB isn't supported
NXS NAND: Writing OOB isn't supported
block 0x000dec00 NOT marked as bad! ERROR 0

Cc: Han Xu <han.xu@nxp.com>
Cc: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- Adjust the commit message
	- Add Cc Han Xu and Fabio
---
 drivers/mtd/nand/raw/mxs_nand.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index ee5d7fde9c..53f24b9c4b 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -1246,22 +1246,6 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	/* Enable BCH complete interrupt */
 	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
 
-	/* Hook some operations at the MTD level. */
-	if (mtd->_read_oob != mxs_nand_hook_read_oob) {
-		nand_info->hooked_read_oob = mtd->_read_oob;
-		mtd->_read_oob = mxs_nand_hook_read_oob;
-	}
-
-	if (mtd->_write_oob != mxs_nand_hook_write_oob) {
-		nand_info->hooked_write_oob = mtd->_write_oob;
-		mtd->_write_oob = mxs_nand_hook_write_oob;
-	}
-
-	if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
-		nand_info->hooked_block_markbad = mtd->_block_markbad;
-		mtd->_block_markbad = mxs_nand_hook_block_markbad;
-	}
-
 	return 0;
 }
 
@@ -1467,6 +1451,22 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
 	if (err)
 		goto err_free_buffers;
 
+	/* Hook some operations at the MTD level. */
+	if (mtd->_read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->_read_oob;
+		mtd->_read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->_write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->_write_oob;
+		mtd->_write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->_block_markbad;
+		mtd->_block_markbad = mxs_nand_hook_block_markbad;
+	}
+
 	err = nand_register(0, mtd);
 	if (err)
 		goto err_free_buffers;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
  2022-04-27  5:50 ` [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
@ 2022-04-27  5:50 ` Michael Trimarchi
  2022-04-28  0:27   ` Han Xu
  2022-05-06 14:41   ` Han Xu
  2022-04-27  5:50 ` [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling Michael Trimarchi
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 20+ messages in thread
From: Michael Trimarchi @ 2022-04-27  5:50 UTC (permalink / raw)
  To: Han Xu, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

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 <han.xu@nxp.com>
Cc: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
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


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling
  2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
  2022-04-27  5:50 ` [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
  2022-04-27  5:50 ` [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Michael Trimarchi
@ 2022-04-27  5:50 ` Michael Trimarchi
  2022-05-06 14:41   ` Han Xu
  2022-04-27  5:50 ` [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
  2022-05-11 15:16 ` [PATCH V2 0/4] MXS nand fixes in SPL Tim Harvey
  4 siblings, 1 reply; 20+ messages in thread
From: Michael Trimarchi @ 2022-04-27  5:50 UTC (permalink / raw)
  To: Han Xu, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

The badblock should be skipped properly in reading and writing.
Fix the logic. The bcb struct is written, skipping the bad block,
so we need to read using the same logic. This was tested create
bad block in the area and then flash it and read it back.

Cc: Han Xu <han.xu@nxp.com>
Cc: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- Adjust the commit message
	- Add Cc Han Xu and Fabio
	- move out from RFC
---
 arch/arm/mach-imx/cmd_nandbcb.c | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index f119e9f88d..c54f52b343 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -506,10 +506,6 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
 	int ret = 0;
 
 	mtd = boot_cfg->mtd;
-	if (mtd_block_isbad(mtd, off)) {
-		printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
-		return 1;
-	}
 
 	fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
 	if (!fcb_raw_page) {
@@ -530,7 +526,7 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
 		else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
 			mxs_nand_mode_fcb_40bit(mtd);
 
-		ret = nand_read(mtd, off, &size, (u_char *)fcb);
+		ret = nand_read_skip_bad(mtd, off, &size, NULL, mtd->size, (u_char *)fcb);
 
 		/* switch BCH back */
 		mxs_nand_mode_normal(mtd);
@@ -617,6 +613,7 @@ static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
 	for (i = 0; i < g_boot_search_count; i++) {
 		if (mtd_block_isbad(mtd, off)) {
 			printf("Block %d is bad, skipped\n", i);
+			off += mtd->erasesize;
 			continue;
 		}
 
@@ -676,20 +673,15 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
 		      void *dbbt_data_page, loff_t off)
 {
 	size_t size;
+	size_t actual_size;
 	struct mtd_info *mtd;
 	loff_t to;
 	int ret;
 
 	mtd = boot_cfg->mtd;
 
-	if (mtd_block_isbad(mtd, off)) {
-		printf("Block %d is bad, skipped\n",
-		       (int)CONV_TO_BLOCKS(off));
-		return 1;
-	}
-
 	size = sizeof(struct dbbt_block);
-	ret = nand_read(mtd, off, &size, (u_char *)dbbt);
+	ret = nand_read_skip_bad(mtd, off, &size, &actual_size, mtd->size, (u_char *)dbbt);
 	printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
 	       off, size, ret ? "ERROR" : "OK");
 	if (ret)
@@ -697,9 +689,9 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
 
 	/* dbbtpages == 0 if no bad blocks */
 	if (dbbt->dbbtpages > 0) {
-		to = off + 4 * mtd->writesize;
+		to = off + 4 * mtd->writesize + actual_size - size;
 		size = mtd->writesize;
-		ret = nand_read(mtd, to, &size, dbbt_data_page);
+		ret = nand_read_skip_bad(mtd, to, &size, NULL, mtd->size, dbbt_data_page);
 		printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
 		       to, size, ret ? "ERROR" : "OK");
 
@@ -729,6 +721,7 @@ static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
 		if (mtd_block_isbad(mtd, off)) {
 			printf("Block %d is bad, skipped\n",
 			       (int)(i + CONV_TO_BLOCKS(off)));
+			off += mtd->erasesize;
 			continue;
 		}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage
  2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
                   ` (2 preceding siblings ...)
  2022-04-27  5:50 ` [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling Michael Trimarchi
@ 2022-04-27  5:50 ` Michael Trimarchi
  2022-04-28 12:45   ` Tom Rini
  2022-05-06 14:42   ` Han Xu
  2022-05-11 15:16 ` [PATCH V2 0/4] MXS nand fixes in SPL Tim Harvey
  4 siblings, 2 replies; 20+ messages in thread
From: Michael Trimarchi @ 2022-04-27  5:50 UTC (permalink / raw)
  To: Han Xu, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

If the fitImage has some bad block in fit image area, the
offset must be recalulcated. This should be done always.
After implementing it in mxs now is possible to call the function
even for that platform.

Cc: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- move out from RFC
---
 common/spl/spl_nand.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
index fc61b447a5..82a10ffa63 100644
--- a/common/spl/spl_nand.c
+++ b/common/spl/spl_nand.c
@@ -43,15 +43,12 @@ static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
 			       ulong size, void *dst)
 {
 	int err;
-#ifdef CONFIG_SYS_NAND_BLOCK_SIZE
 	ulong sector;
 
 	sector = *(int *)load->priv;
-	offs = sector + nand_spl_adjust_offset(sector, offs - sector);
-#else
 	offs *= load->bl_len;
 	size *= load->bl_len;
-#endif
+	offs = sector + nand_spl_adjust_offset(sector, offs - sector);
 	err = nand_spl_load_image(offs, size, dst);
 	if (err)
 		return 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* RE: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-04-27  5:50 ` [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Michael Trimarchi
@ 2022-04-28  0:27   ` Han Xu
  2022-04-28  5:01     ` Michael Nazzareno Trimarchi
  2022-05-06 14:41   ` Han Xu
  1 sibling, 1 reply; 20+ messages in thread
From: Han Xu @ 2022-04-28  0:27 UTC (permalink / raw)
  To: Michael Trimarchi, U-Boot-Denx
  Cc: Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam



> -----Original Message-----
> From: Michael Trimarchi <michael@amarulasolutions.com>
> Sent: Wednesday, April 27, 2022 12:50 AM
> To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> <jagan@amarulasolutions.com>; Ariel D'Alessandro
> <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> 
> 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.

Could you please describe more details about your test? Thanks.

> 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 <han.xu@nxp.com>
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> ---
> 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-04-28  0:27   ` Han Xu
@ 2022-04-28  5:01     ` Michael Nazzareno Trimarchi
  2022-05-01  6:36       ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-04-28  5:01 UTC (permalink / raw)
  To: Han Xu
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Hi

On Thu, Apr 28, 2022 at 2:27 AM Han Xu <han.xu@nxp.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Michael Trimarchi <michael@amarulasolutions.com>
> > Sent: Wednesday, April 27, 2022 12:50 AM
> > To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> > Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> > <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> > Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> > <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> > <jagan@amarulasolutions.com>; Ariel D'Alessandro
> > <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> >
> > 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.
>
> Could you please describe more details about your test? Thanks.

Suppose you have a badblock on 5 or 6. Let's start to have only 6
and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 7, 8


Case 1)
When you write the block 6 the code will skip it as bad during
programming. THe image of uboot (or flash.bin) will
be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
read (from raw offset the 5) and then he will found the
bad block on next erase block in the while loop and will exists at the
end of the flash because the test
is done on the offset and not on the page that is not incremented

Case 2)

Now same example but let's suppose to have block 5 bad. So you write
your image and it will start
from a raw offset 5 but it will be written starting from 6. The spl
loader will fail because it will not skip
the first block and then will fail anyway to read the image. The patch
try to fix the above behavior

Case 3) can be any combination

Michael



>
> > 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 <han.xu@nxp.com>
> > Cc: Fabio Estevam <festevam@gmail.com>
> > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > ---
> > 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->e
Copy Link
MA
Copy Link
NA
Copy Link
rasesize / 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
>


-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage
  2022-04-27  5:50 ` [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
@ 2022-04-28 12:45   ` Tom Rini
  2022-05-06 14:42   ` Han Xu
  1 sibling, 0 replies; 20+ messages in thread
From: Tom Rini @ 2022-04-28 12:45 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: Han Xu, U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal,
	Fabio Estevam, Dario Binacchi, Sean Anderson, linux-kernel,
	Jagan Teki, Ariel D'Alessandro, Fabio Estevam

[-- Attachment #1: Type: text/plain, Size: 458 bytes --]

On Wed, Apr 27, 2022 at 07:50:25AM +0200, Michael Trimarchi wrote:

> If the fitImage has some bad block in fit image area, the
> offset must be recalulcated. This should be done always.
> After implementing it in mxs now is possible to call the function
> even for that platform.
> 
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-04-28  5:01     ` Michael Nazzareno Trimarchi
@ 2022-05-01  6:36       ` Michael Nazzareno Trimarchi
  2022-05-02 21:32         ` Han Xu
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-05-01  6:36 UTC (permalink / raw)
  To: Han Xu
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Dear Han and Fabio

On Thu, Apr 28, 2022 at 7:01 AM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi
>
> On Thu, Apr 28, 2022 at 2:27 AM Han Xu <han.xu@nxp.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: Michael Trimarchi <michael@amarulasolutions.com>
> > > Sent: Wednesday, April 27, 2022 12:50 AM
> > > To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> > > Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> > > <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> > > Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> > > <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> > > <jagan@amarulasolutions.com>; Ariel D'Alessandro
> > > <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> > > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> > >
> > > 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.
> >
> > Could you please describe more details about your test? Thanks.
>
> Suppose you have a badblock on 5 or 6. Let's start to have only 6
> and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 7, 8
>
>
> Case 1)
> When you write the block 6 the code will skip it as bad during
> programming. THe image of uboot (or flash.bin) will
> be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
> read (from raw offset the 5) and then he will found the
> bad block on next erase block in the while loop and will exists at the
> end of the flash because the test
> is done on the offset and not on the page that is not incremented
>
> Case 2)
>
> Now same example but let's suppose to have block 5 bad. So you write
> your image and it will start
> from a raw offset 5 but it will be written starting from 6. The spl
> loader will fail because it will not skip
> the first block and then will fail anyway to read the image. The patch
> try to fix the above behavior
>
> Case 3) can be any combination
>

Do I need to resend v3?

Michael

> Michael
>
>
>
> >
> > > 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 <han.xu@nxp.com>
> > > Cc: Fabio Estevam <festevam@gmail.com>
> > > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > > ---
> > > 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->e
> Copy Link
> MA
> Copy Link
> NA
> Copy Link
> rasesize / 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
> >
>
>
> --
> Michael Nazzareno Trimarchi
> Co-Founder & Chief Executive Officer
> M. +39 347 913 2170
> michael@amarulasolutions.com
> __________________________________
>
> Amarula Solutions BV
> Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> T. +31 (0)85 111 9172
> info@amarulasolutions.com
> www.amarulasolutions.com



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-05-01  6:36       ` Michael Nazzareno Trimarchi
@ 2022-05-02 21:32         ` Han Xu
  2022-05-03  5:14           ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 20+ messages in thread
From: Han Xu @ 2022-05-02 21:32 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

On 22/05/01 08:36AM, Michael Nazzareno Trimarchi wrote:
> Dear Han and Fabio
> 
> On Thu, Apr 28, 2022 at 7:01 AM Michael Nazzareno Trimarchi
> <michael@amarulasolutions.com> wrote:
> >
> > Hi
> >
> > On Thu, Apr 28, 2022 at 2:27 AM Han Xu <han.xu@nxp.com> wrote:
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Michael Trimarchi <michael@amarulasolutions.com>
> > > > Sent: Wednesday, April 27, 2022 12:50 AM
> > > > To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> > > > Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> > > > <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> > > > Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> > > > <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> > > > <jagan@amarulasolutions.com>; Ariel D'Alessandro
> > > > <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> > > > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> > > >
> > > > 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.
> > >
> > > Could you please describe more details about your test? Thanks.
> >
> > Suppose you have a badblock on 5 or 6. Let's start to have only 6
> > and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 7, 8
> >
> >
> > Case 1)
> > When you write the block 6 the code will skip it as bad during
> > programming. THe image of uboot (or flash.bin) will
> > be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
> > read (from raw offset the 5) and then he will found the
> > bad block on next erase block in the while loop and will exists at the
> > end of the flash because the test
> > is done on the offset and not on the page that is not incremented
> >
> > Case 2)
> >
> > Now same example but let's suppose to have block 5 bad. So you write
> > your image and it will start
> > from a raw offset 5 but it will be written starting from 6. The spl
> > loader will fail because it will not skip
> > the first block and then will fail anyway to read the image. The patch
> > try to fix the above behavior
> >
> > Case 3) can be any combination
> >
> 
> Do I need to resend v3?
> 
> Michael

It's not about the v3. I need to discuss some details with ROM team but
unfortunately they are all in vacation till May 5th. I will respond after the
discussion.

> 
> > Michael
> >
> >
> >
> > >
> > > > 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 <han.xu@nxp.com>
> > > > Cc: Fabio Estevam <festevam@gmail.com>
> > > > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > > > ---
> > > > 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->e
> > Copy Link
> > MA
> > Copy Link
> > NA
> > Copy Link
> > rasesize / 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
> > >
> >
> >
> > --
> > Michael Nazzareno Trimarchi
> > Co-Founder & Chief Executive Officer
> > M. +39 347 913 2170
> > michael@amarulasolutions.com
> > __________________________________
> >
> > Amarula Solutions BV
> > Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> > T. +31 (0)85 111 9172
> > info@amarulasolutions.com
> > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0
> 
> 
> 
> -- 
> Michael Nazzareno Trimarchi
> Co-Founder & Chief Executive Officer
> M. +39 347 913 2170
> michael@amarulasolutions.com
> __________________________________
> 
> Amarula Solutions BV
> Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> T. +31 (0)85 111 9172
> info@amarulasolutions.com
> https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-05-02 21:32         ` Han Xu
@ 2022-05-03  5:14           ` Michael Nazzareno Trimarchi
  2022-05-06  8:21             ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-05-03  5:14 UTC (permalink / raw)
  To: Han Xu
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Hi Han

On Mon, May 2, 2022 at 11:32 PM Han Xu <han.xu@nxp.com> wrote:
>
> On 22/05/01 08:36AM, Michael Nazzareno Trimarchi wrote:
> > Dear Han and Fabio
> >
> > On Thu, Apr 28, 2022 at 7:01 AM Michael Nazzareno Trimarchi
> > <michael@amarulasolutions.com> wrote:
> > >
> > > Hi
> > >
> > > On Thu, Apr 28, 2022 at 2:27 AM Han Xu <han.xu@nxp.com> wrote:
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Michael Trimarchi <michael@amarulasolutions.com>
> > > > > Sent: Wednesday, April 27, 2022 12:50 AM
> > > > > To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> > > > > Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> > > > > <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> > > > > Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> > > > > <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> > > > > <jagan@amarulasolutions.com>; Ariel D'Alessandro
> > > > > <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> > > > > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> > > > >
> > > > > 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.
> > > >
> > > > Could you please describe more details about your test? Thanks.
> > >
> > > Suppose you have a badblock on 5 or 6. Let's start to have only 6
> > > and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 7, 8
> > >
> > >
> > > Case 1)
> > > When you write the block 6 the code will skip it as bad during
> > > programming. THe image of uboot (or flash.bin) will
> > > be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
> > > read (from raw offset the 5) and then he will found the
> > > bad block on next erase block in the while loop and will exists at the
> > > end of the flash because the test
> > > is done on the offset and not on the page that is not incremented
> > >
> > > Case 2)
> > >
> > > Now same example but let's suppose to have block 5 bad. So you write
> > > your image and it will start
> > > from a raw offset 5 but it will be written starting from 6. The spl
> > > loader will fail because it will not skip
> > > the first block and then will fail anyway to read the image. The patch
> > > try to fix the above behavior
> > >
> > > Case 3) can be any combination
> > >
> >
> > Do I need to resend v3?
> >
> > Michael
>
> It's not about the v3. I need to discuss some details with ROM team but
> unfortunately they are all in vacation till May 5th. I will respond after the
> discussion.
>

No problem I will wait, but the code is used by other nxp
architectures that don't use the
rom api.

Michael

Definit
> >
> > > Michael
> > >
> > >
> > >
> > > >
> > > > > 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 <han.xu@nxp.com>
> > > > > Cc: Fabio Estevam <festevam@gmail.com>
> > > > > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > > > > ---
> > > > > 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->e
> > > Copy Link
> > > MA
> > > Copy Link
> > > NA
> > > Copy Link
> > > rasesize / 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
> > > >
> > >
> > >
> > > --
> > > Michael Nazzareno Trimarchi
> > > Co-Founder & Chief Executive Officer
> > > M. +39 347 913 2170
> > > michael@amarulasolutions.com
> > > __________________________________
> > >
> > > Amarula Solutions BV
> > > Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> > > T. +31 (0)85 111 9172
> > > info@amarulasolutions.com
> > > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0
> >
> >
> >
> > --
> > Michael Nazzareno Trimarchi
> > Co-Founder & Chief Executive Officer
> > M. +39 347 913 2170
> > michael@amarulasolutions.com
> > __________________________________
> >
> > Amarula Solutions BV
> > Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> > T. +31 (0)85 111 9172
> > info@amarulasolutions.com
> > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-05-03  5:14           ` Michael Nazzareno Trimarchi
@ 2022-05-06  8:21             ` Michael Nazzareno Trimarchi
  0 siblings, 0 replies; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-05-06  8:21 UTC (permalink / raw)
  To: Han Xu
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Hi Han

Any update?

Michael

On Tue, May 3, 2022 at 7:14 AM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi Han
>
> On Mon, May 2, 2022 at 11:32 PM Han Xu <han.xu@nxp.com> wrote:
> >
> > On 22/05/01 08:36AM, Michael Nazzareno Trimarchi wrote:
> > > Dear Han and Fabio
> > >
> > > On Thu, Apr 28, 2022 at 7:01 AM Michael Nazzareno Trimarchi
> > > <michael@amarulasolutions.com> wrote:
> > > >
> > > > Hi
> > > >
> > > > On Thu, Apr 28, 2022 at 2:27 AM Han Xu <han.xu@nxp.com> wrote:
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Michael Trimarchi <michael@amarulasolutions.com>
> > > > > > Sent: Wednesday, April 27, 2022 12:50 AM
> > > > > > To: Han Xu <han.xu@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>
> > > > > > Cc: Ye Li <ye.li@nxp.com>; Stefano Babic <sbabic@denx.de>; Miquel Raynal
> > > > > > <miquel.raynal@bootlin.com>; Fabio Estevam <festevam@denx.de>; Dario
> > > > > > Binacchi <dario.binacchi@amarulasolutions.com>; Sean Anderson
> > > > > > <sean.anderson@seco.com>; linux-kernel@amarulasolutions.com; Jagan Teki
> > > > > > <jagan@amarulasolutions.com>; Ariel D'Alessandro
> > > > > > <ariel.dalessandro@collabora.com>; Fabio Estevam <festevam@gmail.com>
> > > > > > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> > > > > >
> > > > > > 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.
> > > > >
> > > > > Could you please describe more details about your test? Thanks.
> > > >
> > > > Suppose you have a badblock on 5 or 6. Let's start to have only 6
> > > > and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 7, 8
> > > >
> > > >
> > > > Case 1)
> > > > When you write the block 6 the code will skip it as bad during
> > > > programming. THe image of uboot (or flash.bin) will
> > > > be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
> > > > read (from raw offset the 5) and then he will found the
> > > > bad block on next erase block in the while loop and will exists at the
> > > > end of the flash because the test
> > > > is done on the offset and not on the page that is not incremented
> > > >
> > > > Case 2)
> > > >
> > > > Now same example but let's suppose to have block 5 bad. So you write
> > > > your image and it will start
> > > > from a raw offset 5 but it will be written starting from 6. The spl
> > > > loader will fail because it will not skip
> > > > the first block and then will fail anyway to read the image. The patch
> > > > try to fix the above behavior
> > > >
> > > > Case 3) can be any combination
> > > >
> > >
> > > Do I need to resend v3?
> > >
> > > Michael
> >
> > It's not about the v3. I need to discuss some details with ROM team but
> > unfortunately they are all in vacation till May 5th. I will respond after the
> > discussion.
> >
>
> No problem I will wait, but the code is used by other nxp
> architectures that don't use the
> rom api.
>
> Michael
>
> Definit
> > >
> > > > Michael
> > > >
> > > >
> > > >
> > > > >
> > > > > > 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 <han.xu@nxp.com>
> > > > > > Cc: Fabio Estevam <festevam@gmail.com>
> > > > > > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > > > > > ---
> > > > > > 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->e
> > > > Copy Link
> > > > MA
> > > > Copy Link
> > > > NA
> > > > Copy Link
> > > > rasesize / 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
> > > > >
> > > >
> > > >
> > > > --
> > > > Michael Nazzareno Trimarchi
> > > > Co-Founder & Chief Executive Officer
> > > > M. +39 347 913 2170
> > > > michael@amarulasolutions.com
> > > > __________________________________
> > > >
> > > > Amarula Solutions BV
> > > > Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> > > > T. +31 (0)85 111 9172
> > > > info@amarulasolutions.com
> > > > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0
> > >
> > >
> > >
> > > --
> > > Michael Nazzareno Trimarchi
> > > Co-Founder & Chief Executive Officer
> > > M. +39 347 913 2170
> > > michael@amarulasolutions.com
> > > __________________________________
> > >
> > > Amarula Solutions BV
> > > Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> > > T. +31 (0)85 111 9172
> > > info@amarulasolutions.com
> > > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.amarulasolutions.com%2F&amp;data=05%7C01%7Chan.xu%40nxp.com%7C81091e4443d745ce460708da2b3cec6a%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637869837927785927%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=I5jvEx5qmQLzO8QrQT9aMYttDPZhdvbGi0Z2lk77bio%3D&amp;reserved=0
>
>
>
> --
> Michael Nazzareno Trimarchi
> Co-Founder & Chief Executive Officer
> M. +39 347 913 2170
> michael@amarulasolutions.com
> __________________________________
>
> Amarula Solutions BV
> Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> T. +31 (0)85 111 9172
> info@amarulasolutions.com
> www.amarulasolutions.com



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration
  2022-04-27  5:50 ` [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
@ 2022-05-06 14:40   ` Han Xu
  0 siblings, 0 replies; 20+ messages in thread
From: Han Xu @ 2022-05-06 14:40 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

On 22/04/27 07:50AM, Michael Trimarchi wrote:
> Move the hook after nand_scan_tail is called. The hook must be replaced
> to the mxs specific one but those must to be assignment later in the
> probe function.
> 
> With this fix markbad is working again. Before this change:
> 
> nand markbad 0xDEC00
> NXS NAND: Writing OOB isn't supported
> NXS NAND: Writing OOB isn't supported
> block 0x000dec00 NOT marked as bad! ERROR 0
> 
> Cc: Han Xu <han.xu@nxp.com>
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

Acked-by: Han Xu <han.xu@nxp.com>

> ---
> V1->V2:
> 	- Adjust the commit message
> 	- Add Cc Han Xu and Fabio
> ---
>  drivers/mtd/nand/raw/mxs_nand.c | 32 ++++++++++++++++----------------
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index ee5d7fde9c..53f24b9c4b 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -1246,22 +1246,6 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	/* Enable BCH complete interrupt */
>  	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
>  
> -	/* Hook some operations at the MTD level. */
> -	if (mtd->_read_oob != mxs_nand_hook_read_oob) {
> -		nand_info->hooked_read_oob = mtd->_read_oob;
> -		mtd->_read_oob = mxs_nand_hook_read_oob;
> -	}
> -
> -	if (mtd->_write_oob != mxs_nand_hook_write_oob) {
> -		nand_info->hooked_write_oob = mtd->_write_oob;
> -		mtd->_write_oob = mxs_nand_hook_write_oob;
> -	}
> -
> -	if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
> -		nand_info->hooked_block_markbad = mtd->_block_markbad;
> -		mtd->_block_markbad = mxs_nand_hook_block_markbad;
> -	}
> -
>  	return 0;
>  }
>  
> @@ -1467,6 +1451,22 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
>  	if (err)
>  		goto err_free_buffers;
>  
> +	/* Hook some operations at the MTD level. */
> +	if (mtd->_read_oob != mxs_nand_hook_read_oob) {
> +		nand_info->hooked_read_oob = mtd->_read_oob;
> +		mtd->_read_oob = mxs_nand_hook_read_oob;
> +	}
> +
> +	if (mtd->_write_oob != mxs_nand_hook_write_oob) {
> +		nand_info->hooked_write_oob = mtd->_write_oob;
> +		mtd->_write_oob = mxs_nand_hook_write_oob;
> +	}
> +
> +	if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
> +		nand_info->hooked_block_markbad = mtd->_block_markbad;
> +		mtd->_block_markbad = mxs_nand_hook_block_markbad;
> +	}
> +
>  	err = nand_register(0, mtd);
>  	if (err)
>  		goto err_free_buffers;
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-04-27  5:50 ` [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Michael Trimarchi
  2022-04-28  0:27   ` Han Xu
@ 2022-05-06 14:41   ` Han Xu
  2022-05-06 14:44     ` Michael Nazzareno Trimarchi
  1 sibling, 1 reply; 20+ messages in thread
From: Han Xu @ 2022-05-06 14:41 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

On 22/04/27 07:50AM, Michael Trimarchi wrote:
> 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 <han.xu@nxp.com>
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

Acked-by: Han Xu <han.xu@nxp.com>

> ---
> 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
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling
  2022-04-27  5:50 ` [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling Michael Trimarchi
@ 2022-05-06 14:41   ` Han Xu
  2022-05-11  6:49     ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 20+ messages in thread
From: Han Xu @ 2022-05-06 14:41 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

On 22/04/27 07:50AM, Michael Trimarchi wrote:
> The badblock should be skipped properly in reading and writing.
> Fix the logic. The bcb struct is written, skipping the bad block,
> so we need to read using the same logic. This was tested create
> bad block in the area and then flash it and read it back.
> 
> Cc: Han Xu <han.xu@nxp.com>
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

Acked-by: Han Xu <han.xu@nxp.com>

> ---
> V1->V2:
> 	- Adjust the commit message
> 	- Add Cc Han Xu and Fabio
> 	- move out from RFC
> ---
>  arch/arm/mach-imx/cmd_nandbcb.c | 21 +++++++--------------
>  1 file changed, 7 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index f119e9f88d..c54f52b343 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -506,10 +506,6 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
>  	int ret = 0;
>  
>  	mtd = boot_cfg->mtd;
> -	if (mtd_block_isbad(mtd, off)) {
> -		printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
> -		return 1;
> -	}
>  
>  	fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
>  	if (!fcb_raw_page) {
> @@ -530,7 +526,7 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
>  		else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
>  			mxs_nand_mode_fcb_40bit(mtd);
>  
> -		ret = nand_read(mtd, off, &size, (u_char *)fcb);
> +		ret = nand_read_skip_bad(mtd, off, &size, NULL, mtd->size, (u_char *)fcb);
>  
>  		/* switch BCH back */
>  		mxs_nand_mode_normal(mtd);
> @@ -617,6 +613,7 @@ static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
>  	for (i = 0; i < g_boot_search_count; i++) {
>  		if (mtd_block_isbad(mtd, off)) {
>  			printf("Block %d is bad, skipped\n", i);
> +			off += mtd->erasesize;
>  			continue;
>  		}
>  
> @@ -676,20 +673,15 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
>  		      void *dbbt_data_page, loff_t off)
>  {
>  	size_t size;
> +	size_t actual_size;
>  	struct mtd_info *mtd;
>  	loff_t to;
>  	int ret;
>  
>  	mtd = boot_cfg->mtd;
>  
> -	if (mtd_block_isbad(mtd, off)) {
> -		printf("Block %d is bad, skipped\n",
> -		       (int)CONV_TO_BLOCKS(off));
> -		return 1;
> -	}
> -
>  	size = sizeof(struct dbbt_block);
> -	ret = nand_read(mtd, off, &size, (u_char *)dbbt);
> +	ret = nand_read_skip_bad(mtd, off, &size, &actual_size, mtd->size, (u_char *)dbbt);
>  	printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
>  	       off, size, ret ? "ERROR" : "OK");
>  	if (ret)
> @@ -697,9 +689,9 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
>  
>  	/* dbbtpages == 0 if no bad blocks */
>  	if (dbbt->dbbtpages > 0) {
> -		to = off + 4 * mtd->writesize;
> +		to = off + 4 * mtd->writesize + actual_size - size;
>  		size = mtd->writesize;
> -		ret = nand_read(mtd, to, &size, dbbt_data_page);
> +		ret = nand_read_skip_bad(mtd, to, &size, NULL, mtd->size, dbbt_data_page);
>  		printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
>  		       to, size, ret ? "ERROR" : "OK");
>  
> @@ -729,6 +721,7 @@ static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
>  		if (mtd_block_isbad(mtd, off)) {
>  			printf("Block %d is bad, skipped\n",
>  			       (int)(i + CONV_TO_BLOCKS(off)));
> +			off += mtd->erasesize;
>  			continue;
>  		}
>  
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage
  2022-04-27  5:50 ` [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
  2022-04-28 12:45   ` Tom Rini
@ 2022-05-06 14:42   ` Han Xu
  1 sibling, 0 replies; 20+ messages in thread
From: Han Xu @ 2022-05-06 14:42 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

On 22/04/27 07:50AM, Michael Trimarchi wrote:
> If the fitImage has some bad block in fit image area, the
> offset must be recalulcated. This should be done always.
> After implementing it in mxs now is possible to call the function
> even for that platform.
> 
> Cc: Fabio Estevam <festevam@gmail.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

Acked-by: Han Xu <han.xu@nxp.com>

> ---
> V1->V2:
> 	- move out from RFC
> ---
>  common/spl/spl_nand.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
> index fc61b447a5..82a10ffa63 100644
> --- a/common/spl/spl_nand.c
> +++ b/common/spl/spl_nand.c
> @@ -43,15 +43,12 @@ static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
>  			       ulong size, void *dst)
>  {
>  	int err;
> -#ifdef CONFIG_SYS_NAND_BLOCK_SIZE
>  	ulong sector;
>  
>  	sector = *(int *)load->priv;
> -	offs = sector + nand_spl_adjust_offset(sector, offs - sector);
> -#else
>  	offs *= load->bl_len;
>  	size *= load->bl_len;
> -#endif
> +	offs = sector + nand_spl_adjust_offset(sector, offs - sector);
>  	err = nand_spl_load_image(offs, size, dst);
>  	if (err)
>  		return 0;
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
  2022-05-06 14:41   ` Han Xu
@ 2022-05-06 14:44     ` Michael Nazzareno Trimarchi
  0 siblings, 0 replies; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-05-06 14:44 UTC (permalink / raw)
  To: Han Xu
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Hi

Thank you. What is the reply from bootrom team?

Michael

On Fri, May 6, 2022 at 4:41 PM Han Xu <han.xu@nxp.com> wrote:
>
> On 22/04/27 07:50AM, Michael Trimarchi wrote:
> > 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 <han.xu@nxp.com>
> > Cc: Fabio Estevam <festevam@gmail.com>
> > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>
> Acked-by: Han Xu <han.xu@nxp.com>
>
> > ---
> > 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
> >



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling
  2022-05-06 14:41   ` Han Xu
@ 2022-05-11  6:49     ` Michael Nazzareno Trimarchi
  2022-05-11 15:17       ` Tim Harvey
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Nazzareno Trimarchi @ 2022-05-11  6:49 UTC (permalink / raw)
  To: Han Xu, Tim Harvey
  Cc: U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal, Fabio Estevam,
	Dario Binacchi, Sean Anderson, linux-kernel, Jagan Teki,
	Ariel D'Alessandro, Fabio Estevam

Hi Tim

Do you have an alternative board to test?

Michael

On Fri, May 6, 2022 at 4:41 PM Han Xu <han.xu@nxp.com> wrote:
>
> On 22/04/27 07:50AM, Michael Trimarchi wrote:
> > The badblock should be skipped properly in reading and writing.
> > Fix the logic. The bcb struct is written, skipping the bad block,
> > so we need to read using the same logic. This was tested create
> > bad block in the area and then flash it and read it back.
> >
> > Cc: Han Xu <han.xu@nxp.com>
> > Cc: Fabio Estevam <festevam@gmail.com>
> > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>
> Acked-by: Han Xu <han.xu@nxp.com>
>
> > ---
> > V1->V2:
> >       - Adjust the commit message
> >       - Add Cc Han Xu and Fabio
> >       - move out from RFC
> > ---
> >  arch/arm/mach-imx/cmd_nandbcb.c | 21 +++++++--------------
> >  1 file changed, 7 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> > index f119e9f88d..c54f52b343 100644
> > --- a/arch/arm/mach-imx/cmd_nandbcb.c
> > +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> > @@ -506,10 +506,6 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
> >       int ret = 0;
> >
> >       mtd = boot_cfg->mtd;
> > -     if (mtd_block_isbad(mtd, off)) {
> > -             printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
> > -             return 1;
> > -     }
> >
> >       fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> >       if (!fcb_raw_page) {
> > @@ -530,7 +526,7 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
> >               else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
> >                       mxs_nand_mode_fcb_40bit(mtd);
> >
> > -             ret = nand_read(mtd, off, &size, (u_char *)fcb);
> > +             ret = nand_read_skip_bad(mtd, off, &size, NULL, mtd->size, (u_char *)fcb);
> >
> >               /* switch BCH back */
> >               mxs_nand_mode_normal(mtd);
> > @@ -617,6 +613,7 @@ static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
> >       for (i = 0; i < g_boot_search_count; i++) {
> >               if (mtd_block_isbad(mtd, off)) {
> >                       printf("Block %d is bad, skipped\n", i);
> > +                     off += mtd->erasesize;
> >                       continue;
> >               }
> >
> > @@ -676,20 +673,15 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> >                     void *dbbt_data_page, loff_t off)
> >  {
> >       size_t size;
> > +     size_t actual_size;
> >       struct mtd_info *mtd;
> >       loff_t to;
> >       int ret;
> >
> >       mtd = boot_cfg->mtd;
> >
> > -     if (mtd_block_isbad(mtd, off)) {
> > -             printf("Block %d is bad, skipped\n",
> > -                    (int)CONV_TO_BLOCKS(off));
> > -             return 1;
> > -     }
> > -
> >       size = sizeof(struct dbbt_block);
> > -     ret = nand_read(mtd, off, &size, (u_char *)dbbt);
> > +     ret = nand_read_skip_bad(mtd, off, &size, &actual_size, mtd->size, (u_char *)dbbt);
> >       printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
> >              off, size, ret ? "ERROR" : "OK");
> >       if (ret)
> > @@ -697,9 +689,9 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> >
> >       /* dbbtpages == 0 if no bad blocks */
> >       if (dbbt->dbbtpages > 0) {
> > -             to = off + 4 * mtd->writesize;
> > +             to = off + 4 * mtd->writesize + actual_size - size;
> >               size = mtd->writesize;
> > -             ret = nand_read(mtd, to, &size, dbbt_data_page);
> > +             ret = nand_read_skip_bad(mtd, to, &size, NULL, mtd->size, dbbt_data_page);
> >               printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
> >                      to, size, ret ? "ERROR" : "OK");
> >
> > @@ -729,6 +721,7 @@ static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> >               if (mtd_block_isbad(mtd, off)) {
> >                       printf("Block %d is bad, skipped\n",
> >                              (int)(i + CONV_TO_BLOCKS(off)));
> > +                     off += mtd->erasesize;
> >                       continue;
> >               }
> >
> > --
> > 2.25.1
> >



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 0/4] MXS nand fixes in SPL
  2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
                   ` (3 preceding siblings ...)
  2022-04-27  5:50 ` [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
@ 2022-05-11 15:16 ` Tim Harvey
  4 siblings, 0 replies; 20+ messages in thread
From: Tim Harvey @ 2022-05-11 15:16 UTC (permalink / raw)
  To: Michael Trimarchi
  Cc: Han Xu, U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal,
	Fabio Estevam, Dario Binacchi, Sean Anderson, linux-kernel,
	Jagan Teki, Ariel D'Alessandro

On Tue, Apr 26, 2022 at 10:50 PM Michael Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Those patches come after some testing of failing in factory on some
> unit. We found out that the bootrom imx loader was not able to handling
> badblock. This can be a limit of the implementation right now in imx8mn.
> Anyway not all the imx platform has the support of this loader. I found
> some problems on the implementation so I have fixed it up according the
> experience of Sitara. I tested only using a Fit Image as a flash
> container. This version add in the series the fix of cmd_nandbcb and
> the fix of spl_nand load. I can imagine that a lot of boards and users
> are affected. I have started to backport this changes in some older
> uboot and adapt it
>
> Michael Trimarchi (4):
>   nand: raw: mxs_nand: Fix specific hook registration
>   mtd: nand: mxs_nand_spl: Fix bad block skipping
>   arm: mach-imx: cmd_nandbcb fix bad block handling
>   spl: spl_nand: Fix bad block handling in fitImage
>
>  arch/arm/mach-imx/cmd_nandbcb.c     | 21 +++----
>  common/spl/spl_nand.c               |  5 +-
>  drivers/mtd/nand/raw/mxs_nand.c     | 32 +++++-----
>  drivers/mtd/nand/raw/mxs_nand_spl.c | 90 ++++++++++++++++-------------
>  4 files changed, 73 insertions(+), 75 deletions(-)
>
> --
> 2.25.1
>

Tested By: Tim Harvey <tharvey@gateworks.com>
#gwventana_nand_defconfig (imx6qdl NAND)

Best Regards,

Tim

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling
  2022-05-11  6:49     ` Michael Nazzareno Trimarchi
@ 2022-05-11 15:17       ` Tim Harvey
  0 siblings, 0 replies; 20+ messages in thread
From: Tim Harvey @ 2022-05-11 15:17 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: Han Xu, U-Boot-Denx, Ye Li, Stefano Babic, Miquel Raynal,
	Fabio Estevam, Dario Binacchi, Sean Anderson, linux-kernel,
	Jagan Teki, Ariel D'Alessandro, Fabio Estevam

On Tue, May 10, 2022 at 11:49 PM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi Tim
>
> Do you have an alternative board to test?
>

Michael,

Yes sorry... I tested the series and had the reply in my draft folder.
I sent it just now in response to the cover letter.

Best regards,

Tim

> Michael
>
> On Fri, May 6, 2022 at 4:41 PM Han Xu <han.xu@nxp.com> wrote:
> >
> > On 22/04/27 07:50AM, Michael Trimarchi wrote:
> > > The badblock should be skipped properly in reading and writing.
> > > Fix the logic. The bcb struct is written, skipping the bad block,
> > > so we need to read using the same logic. This was tested create
> > > bad block in the area and then flash it and read it back.
> > >
> > > Cc: Han Xu <han.xu@nxp.com>
> > > Cc: Fabio Estevam <festevam@gmail.com>
> > > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> >
> > Acked-by: Han Xu <han.xu@nxp.com>
> >
> > > ---
> > > V1->V2:
> > >       - Adjust the commit message
> > >       - Add Cc Han Xu and Fabio
> > >       - move out from RFC
> > > ---
> > >  arch/arm/mach-imx/cmd_nandbcb.c | 21 +++++++--------------
> > >  1 file changed, 7 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> > > index f119e9f88d..c54f52b343 100644
> > > --- a/arch/arm/mach-imx/cmd_nandbcb.c
> > > +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> > > @@ -506,10 +506,6 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
> > >       int ret = 0;
> > >
> > >       mtd = boot_cfg->mtd;
> > > -     if (mtd_block_isbad(mtd, off)) {
> > > -             printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
> > > -             return 1;
> > > -     }
> > >
> > >       fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> > >       if (!fcb_raw_page) {
> > > @@ -530,7 +526,7 @@ static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
> > >               else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
> > >                       mxs_nand_mode_fcb_40bit(mtd);
> > >
> > > -             ret = nand_read(mtd, off, &size, (u_char *)fcb);
> > > +             ret = nand_read_skip_bad(mtd, off, &size, NULL, mtd->size, (u_char *)fcb);
> > >
> > >               /* switch BCH back */
> > >               mxs_nand_mode_normal(mtd);
> > > @@ -617,6 +613,7 @@ static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
> > >       for (i = 0; i < g_boot_search_count; i++) {
> > >               if (mtd_block_isbad(mtd, off)) {
> > >                       printf("Block %d is bad, skipped\n", i);
> > > +                     off += mtd->erasesize;
> > >                       continue;
> > >               }
> > >
> > > @@ -676,20 +673,15 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> > >                     void *dbbt_data_page, loff_t off)
> > >  {
> > >       size_t size;
> > > +     size_t actual_size;
> > >       struct mtd_info *mtd;
> > >       loff_t to;
> > >       int ret;
> > >
> > >       mtd = boot_cfg->mtd;
> > >
> > > -     if (mtd_block_isbad(mtd, off)) {
> > > -             printf("Block %d is bad, skipped\n",
> > > -                    (int)CONV_TO_BLOCKS(off));
> > > -             return 1;
> > > -     }
> > > -
> > >       size = sizeof(struct dbbt_block);
> > > -     ret = nand_read(mtd, off, &size, (u_char *)dbbt);
> > > +     ret = nand_read_skip_bad(mtd, off, &size, &actual_size, mtd->size, (u_char *)dbbt);
> > >       printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
> > >              off, size, ret ? "ERROR" : "OK");
> > >       if (ret)
> > > @@ -697,9 +689,9 @@ static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> > >
> > >       /* dbbtpages == 0 if no bad blocks */
> > >       if (dbbt->dbbtpages > 0) {
> > > -             to = off + 4 * mtd->writesize;
> > > +             to = off + 4 * mtd->writesize + actual_size - size;
> > >               size = mtd->writesize;
> > > -             ret = nand_read(mtd, to, &size, dbbt_data_page);
> > > +             ret = nand_read_skip_bad(mtd, to, &size, NULL, mtd->size, dbbt_data_page);
> > >               printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
> > >                      to, size, ret ? "ERROR" : "OK");
> > >
> > > @@ -729,6 +721,7 @@ static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
> > >               if (mtd_block_isbad(mtd, off)) {
> > >                       printf("Block %d is bad, skipped\n",
> > >                              (int)(i + CONV_TO_BLOCKS(off)));
> > > +                     off += mtd->erasesize;
> > >                       continue;
> > >               }
> > >
> > > --
> > > 2.25.1
> > >
>
>
>
> --
> Michael Nazzareno Trimarchi
> Co-Founder & Chief Executive Officer
> M. +39 347 913 2170
> michael@amarulasolutions.com
> __________________________________
>
> Amarula Solutions BV
> Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
> T. +31 (0)85 111 9172
> info@amarulasolutions.com
> www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-05-11 15:18 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27  5:50 [PATCH V2 0/4] MXS nand fixes in SPL Michael Trimarchi
2022-04-27  5:50 ` [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
2022-05-06 14:40   ` Han Xu
2022-04-27  5:50 ` [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping Michael Trimarchi
2022-04-28  0:27   ` Han Xu
2022-04-28  5:01     ` Michael Nazzareno Trimarchi
2022-05-01  6:36       ` Michael Nazzareno Trimarchi
2022-05-02 21:32         ` Han Xu
2022-05-03  5:14           ` Michael Nazzareno Trimarchi
2022-05-06  8:21             ` Michael Nazzareno Trimarchi
2022-05-06 14:41   ` Han Xu
2022-05-06 14:44     ` Michael Nazzareno Trimarchi
2022-04-27  5:50 ` [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling Michael Trimarchi
2022-05-06 14:41   ` Han Xu
2022-05-11  6:49     ` Michael Nazzareno Trimarchi
2022-05-11 15:17       ` Tim Harvey
2022-04-27  5:50 ` [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
2022-04-28 12:45   ` Tom Rini
2022-05-06 14:42   ` Han Xu
2022-05-11 15:16 ` [PATCH V2 0/4] MXS nand fixes in SPL Tim Harvey

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.