As reported by the OpenWRT team, write requests sometimes fail on some platforms. Currently to check the state chip_ready() is used correctly as described by the flash memory S29GL256P11TFI01 datasheet. Also chip_good() is used to check if the write is succeeded and it was implemented by the commit fb4a90bfcd6d8 ("[MTD] CFI-0002 - Improve error checking"). But actually the write failure is caused on some platforms and also it can be fixed by using chip_good() to check the state and retry instead. Also it seems that it is caused after repeated about 1,000 times to retry the write one word with the reset command. By using chip_good() to check the state to be done it can be reduced the retry with reset. It is depended on the actual flash chip behavior so the root cause is unknown. Cc: Chris Packham <chris.packham@xxxxxxxxxxxxxxxxxxx> Cc: Joakim Tjernlund <Joakim.Tjernlund@xxxxxxxxxxxx> Cc: linux-mtd@xxxxxxxxxxxxxxxxxxx Cc: stable@xxxxxxxxxxxxxxx Reported-by: Fabio Bettoni <fbettoni@xxxxxxxxx> Signed-off-by: Felix Fietkau <nbd@xxxxxxxx> Signed-off-by: Hauke Mehrtens <hauke@xxxxxxxxxx> Signed-off-by: Tokunori Ikegami <ikegami.t@xxxxxxxxx> [vigneshr@xxxxxx: Fix a checkpatch warning] Signed-off-by: Vignesh Raghavendra <vigneshr@xxxxxx> --- drivers/mtd/chips/cfi_cmdset_0002.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) mode change 100644 => 100755 drivers/mtd/chips/cfi_cmdset_0002.c diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c old mode 100644 new mode 100755 index af3d207c9cc4..e773dc6fdd3c --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1628,29 +1628,35 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, continue; } - if (time_after(jiffies, timeo) && !chip_ready(map, adr)){ + /* + * We check "time_after" and "!chip_good" before checking + * "chip_good" to avoid the failure due to scheduling. + */ + if (time_after(jiffies, timeo) && !chip_good(map, adr, datum)) { xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); xip_disable(map, chip, adr); + ret = -EIO; break; } - if (chip_ready(map, adr)) + if (chip_good(map, adr, datum)) break; /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1); } + /* Did we succeed? */ - if (!chip_good(map, adr, datum)) { + if (ret) { /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) + if (++retry_cnt <= MAX_RETRIES) { + ret = 0; goto retry; - - ret = -EIO; + } } xip_enable(map, chip, adr); op_done: -- 2.11.0