From mboxrd@z Thu Jan 1 00:00:00 1970 From: Miquel Raynal Date: Fri, 20 Sep 2019 11:55:58 +0200 Subject: [U-Boot] [PATCH] cmd: mtd: solve bad block support in erase command In-Reply-To: <20190920072012.17841-1-patrick.delaunay@st.com> References: <20190920072012.17841-1-patrick.delaunay@st.com> Message-ID: <20190920094154.7742d4ac@xps13> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: u-boot@lists.denx.de Hi Patrick, Patrick Delaunay wrote on Fri, 20 Sep 2019 09:20:12 +0200: > This patch modify the loop in mtd erase command to erase one by one > the blocks in the requested area. >=20 > It solves issue on "mtd erase" command on nand with existing bad block, > the command is interrupted on the first bad block with the trace: > "Skipping bad block at 0xffffffffffffffff" >=20 > In MTD driver (nand/raw), when a bad block is present on the MTD > device, the erase_op.fail_addr is not updated and we have the initial > value MTD_FAIL_ADDR_UNKNOWN =3D (ULL)-1. >=20 > This case seems normal in nand_base.c:nand_erase_nand(), > we have the 2 exit cases during the loop: >=20 > 1/ we have a bad block (nand_block_checkbad) > instr->state =3D MTD_ERASE_FAILED > loop interrupted (goto erase_exit) >=20 > 2/ if block erase failed (status & NAND_STATUS_FAIL) > instr->state =3D MTD_ERASE_FAILED; > instr->fail_addr =3D > ((loff_t)page << chip->page_shift); > loop interrupted (goto erase_exit) >=20 > So erase_op.fail_addr can't be used if bad blocks were present > in the erased area; we need to use mtd_erase only one block to detect > and skip these existing bad blocks (as it is done in nand_util.c). >=20 > Signed-off-by: Patrick Delaunay > --- >=20 > Hi, >=20 > Found a correct in the mtd erase command. >=20 > I detect the issue and test the patch on STM32MP157C-EV1 board, > with nor and nand. We have the block table at the end of the nand > so the 4 last blocks are marked bad. >=20 > And I try to erase all the nand with the command "mtd erase". >=20 > Before the patch: >=20 > The "nand erase" command behavior is OK: >=20 > STM32MP> nand erase 0x0 0x000040000000 =20 >=20 > NAND erase: device 0 whole chip > Skipping bad block at 0x3ff00000 > Skipping bad block at 0x3ff40000 > Skipping bad block at 0x3ff80000 > Skipping bad block at 0x3ffc0000 >=20 > But the "mtd erase" command is not correct: >=20 > STM32MP> mtd list =20 > SF: Detected mx66l51235l with page size 256 Bytes, erase size 64 KiB, tot= al 64 MiB > List of MTD devices: > * nand0 > - type: NAND flash > - block size: 0x40000 bytes > - min I/O: 0x1000 bytes > - OOB size: 224 bytes > - OOB available: 118 bytes > - ECC strength: 8 bits > - ECC step size: 512 bytes > - bitflip threshold: 6 bits > - 0x000000000000-0x000040000000 : "nand0" > - 0x000000000000-0x000000200000 : "fsbl" > - 0x000000200000-0x000000400000 : "ssbl1" > - 0x000000400000-0x000000600000 : "ssbl2" > - 0x000000600000-0x000040000000 : "UBI" > * nor0 > - type: NOR flash > - block size: 0x10000 bytes > - min I/O: 0x1 bytes > - 0x000000000000-0x000004000000 : "nor0" > - 0x000000000000-0x000000040000 : "fsbl1" > - 0x000000040000-0x000000080000 : "fsbl2" > - 0x000000080000-0x000000280000 : "ssbl" > - 0x000000280000-0x000000300000 : "u-boot-env" > - 0x000000300000-0x000004000000 : "nor_user" >=20 > STM32MP> mtd erase nand0 0x0 0x000040000000 =20 > Erasing 0x00000000 ... 0x3fffffff (4096 eraseblock(s)) > Skipping bad block at 0xffffffffffffffff >=20 > OK >=20 > The 4 bad blocks are not correctly skipped, > the command is stopped on the first error. >=20 > After the patch, the "mtd erase" command skips the 4 bad block > exactly as the "nand erase" command: >=20 > STM32MP> mtd erase nand0 0x000000000000 0x000040000000 =20 > SF: Detected mx66l51235l with page size 256 Bytes, erase size 64 KiB, tot= al 64 MiB > Erasing 0x00000000 ... 0x3fffffff (4096 eraseblock(s)) > Skipping bad block at 0x3ff00000 > Skipping bad block at 0x3ff40000 > Skipping bad block at 0x3ff80000 > Skipping bad block at 0x3ffc0000 >=20 > Regards >=20 > Patrick >=20 >=20 > cmd/mtd.c | 24 ++++++++++++------------ > 1 file changed, 12 insertions(+), 12 deletions(-) >=20 > diff --git a/cmd/mtd.c b/cmd/mtd.c > index 1b6b8dda2b..a559b5a4a3 100644 > --- a/cmd/mtd.c > +++ b/cmd/mtd.c > @@ -387,7 +387,7 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, i= nt argc, > struct mtd_info *mtd; > u64 off, len; > bool scrub; > - int ret; > + int ret =3D 0; > =20 > if (argc < 2) > return CMD_RET_USAGE; > @@ -423,22 +423,22 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag,= int argc, > =20 > erase_op.mtd =3D mtd; > erase_op.addr =3D off; > - erase_op.len =3D len; > + erase_op.len =3D mtd->erasesize; > erase_op.scrub =3D scrub; > =20 > - while (erase_op.len) { > + while (len) { > ret =3D mtd_erase(mtd, &erase_op); > =20 > - /* Abort if its not a bad block error */ > - if (ret !=3D -EIO) > - break; > - > - printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr); > + if (ret) { > + /* Abort if its not a bad block error */ > + if (ret !=3D -EIO) > + break; > + printf("Skipping bad block at 0x%08llx\n", > + erase_op.addr); > + } > =20 > - /* Skip bad block and continue behind it */ > - erase_op.len -=3D erase_op.fail_addr - erase_op.addr; > - erase_op.len -=3D mtd->erasesize; > - erase_op.addr =3D erase_op.fail_addr + mtd->erasesize; > + len -=3D mtd->erasesize; > + erase_op.addr +=3D mtd->erasesize; > } > =20 > if (ret && ret !=3D -EIO) Nice catch! Reviewed-by: Miquel Raynal Thanks, Miqu=C3=A8l