Commit 97bb79dc authored by Tokunori Ikegami's avatar Tokunori Ikegami Committed by Khalid Elmously

mtd: cfi_cmdset_0002: Use chip_good() to retry in do_write_oneword()

BugLink: https://bugs.launchpad.net/bugs/1848589

commit 37c673ad upstream.

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 fb4a90bf ("[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@alliedtelesis.co.nz>
Cc: Joakim Tjernlund <Joakim.Tjernlund@infinera.com>
Cc: linux-mtd@lists.infradead.org
Cc: stable@vger.kernel.org
Reported-by: default avatarFabio Bettoni <fbettoni@gmail.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarHauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: default avatarTokunori Ikegami <ikegami.t@gmail.com>
[vigneshr@ti.com: Fix a checkpatch warning]
Signed-off-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarConnor Kuehl <connor.kuehl@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 2fed92c4
...@@ -1626,29 +1626,35 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, ...@@ -1626,29 +1626,35 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
continue; 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); xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
xip_disable(map, chip, adr); xip_disable(map, chip, adr);
ret = -EIO;
break; break;
} }
if (chip_ready(map, adr)) if (chip_good(map, adr, datum))
break; break;
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
UDELAY(map, chip, adr, 1); UDELAY(map, chip, adr, 1);
} }
/* Did we succeed? */ /* Did we succeed? */
if (!chip_good(map, adr, datum)) { if (ret) {
/* reset on all failures. */ /* reset on all failures. */
map_write( map, CMD(0xF0), chip->start ); map_write( map, CMD(0xF0), chip->start );
/* FIXME - should have reset delay before continuing */ /* FIXME - should have reset delay before continuing */
if (++retry_cnt <= MAX_RETRIES) if (++retry_cnt <= MAX_RETRIES) {
ret = 0;
goto retry; goto retry;
}
ret = -EIO;
} }
xip_enable(map, chip, adr); xip_enable(map, chip, adr);
op_done: op_done:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment