mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-27 22:56:49 +08:00
cmd: mtd: solve bad block support in erase command
This patch modify the loop in mtd erase command to erase one by one the blocks in the requested area. 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" 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 = (ULL)-1. This case seems normal in nand_base.c:nand_erase_nand(), we have the 2 exit cases during the loop: 1/ we have a bad block (nand_block_checkbad) instr->state = MTD_ERASE_FAILED loop interrupted (goto erase_exit) 2/ if block erase failed (status & NAND_STATUS_FAIL) instr->state = MTD_ERASE_FAILED; instr->fail_addr = ((loff_t)page << chip->page_shift); loop interrupted (goto erase_exit) 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). Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
parent
83b539cfd4
commit
b1b147f2b8
24
cmd/mtd.c
24
cmd/mtd.c
@ -387,7 +387,7 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
|
|||||||
struct mtd_info *mtd;
|
struct mtd_info *mtd;
|
||||||
u64 off, len;
|
u64 off, len;
|
||||||
bool scrub;
|
bool scrub;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return CMD_RET_USAGE;
|
return CMD_RET_USAGE;
|
||||||
@ -423,22 +423,22 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
|
|||||||
|
|
||||||
erase_op.mtd = mtd;
|
erase_op.mtd = mtd;
|
||||||
erase_op.addr = off;
|
erase_op.addr = off;
|
||||||
erase_op.len = len;
|
erase_op.len = mtd->erasesize;
|
||||||
erase_op.scrub = scrub;
|
erase_op.scrub = scrub;
|
||||||
|
|
||||||
while (erase_op.len) {
|
while (len) {
|
||||||
ret = mtd_erase(mtd, &erase_op);
|
ret = mtd_erase(mtd, &erase_op);
|
||||||
|
|
||||||
/* Abort if its not a bad block error */
|
if (ret) {
|
||||||
if (ret != -EIO)
|
/* Abort if its not a bad block error */
|
||||||
break;
|
if (ret != -EIO)
|
||||||
|
break;
|
||||||
|
printf("Skipping bad block at 0x%08llx\n",
|
||||||
|
erase_op.addr);
|
||||||
|
}
|
||||||
|
|
||||||
printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
|
len -= mtd->erasesize;
|
||||||
|
erase_op.addr += mtd->erasesize;
|
||||||
/* Skip bad block and continue behind it */
|
|
||||||
erase_op.len -= erase_op.fail_addr - erase_op.addr;
|
|
||||||
erase_op.len -= mtd->erasesize;
|
|
||||||
erase_op.addr = erase_op.fail_addr + mtd->erasesize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret && ret != -EIO)
|
if (ret && ret != -EIO)
|
||||||
|
Loading…
Reference in New Issue
Block a user