| From 37c673ade35c707d50583b5b25091ff8ebdeafd7 Mon Sep 17 00:00:00 2001 |
| From: Tokunori Ikegami <ikegami.t@gmail.com> |
| Date: Tue, 6 Aug 2019 04:03:18 +0900 |
| Subject: mtd: cfi_cmdset_0002: Use chip_good() to retry in do_write_oneword() |
| |
| From: Tokunori Ikegami <ikegami.t@gmail.com> |
| |
| commit 37c673ade35c707d50583b5b25091ff8ebdeafd7 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 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@alliedtelesis.co.nz> |
| Cc: Joakim Tjernlund <Joakim.Tjernlund@infinera.com> |
| Cc: linux-mtd@lists.infradead.org |
| Cc: stable@vger.kernel.org |
| Reported-by: Fabio Bettoni <fbettoni@gmail.com> |
| Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> |
| Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com> |
| [vigneshr@ti.com: Fix a checkpatch warning] |
| Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/mtd/chips/cfi_cmdset_0002.c | 18 ++++++++++++------ |
| 1 file changed, 12 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/mtd/chips/cfi_cmdset_0002.c |
| +++ b/drivers/mtd/chips/cfi_cmdset_0002.c |
| @@ -1717,31 +1717,37 @@ static int __xipram do_write_oneword(str |
| continue; |
| } |
| |
| + /* |
| + * We check "time_after" and "!chip_good" before checking |
| + * "chip_good" to avoid the failure due to scheduling. |
| + */ |
| if (time_after(jiffies, timeo) && |
| - !chip_ready(map, chip, adr)) { |
| + !chip_good(map, chip, 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, chip, adr)) |
| + if (chip_good(map, chip, 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, chip, adr, datum)) { |
| + if (ret) { |
| /* reset on all failures. */ |
| cfi_check_err_status(map, chip, adr); |
| 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: |