ar71xx/ath79: fix mtd corruption
authorFabio Bettoni <fbettoni@gmail.com>
Wed, 17 Oct 2018 12:21:41 +0000 (14:21 +0200)
committerKoen Vandeputte <koen.vandeputte@ncentric.com>
Wed, 17 Oct 2018 16:55:37 +0000 (18:55 +0200)
In commit fec8fe806963 ("kernel: bump 4.9 to 4.9.116") [1], the following patch for removed:
- 403-mtd_fix_cfi_cmdset_0002_status_check.patch

This patch contained fixes for both write and erase functions.

While the chip-detects for erase got fixed upstream [2],
some modifications are still required, even with the fixes applied.

While at it, also apply the same fix for target ath79,
which suffers the same issue.

Not doing so results in following errors seen:

Collected errors:
 * pkg_write_filelist: Failed to open //usr/lib/opkg/info/luci-lib-ip.list: I/O error.
 * opkg_install_pkg: Failed to extract data files for luci-lib-ip. Package debris may remain!
 * opkg_install_cmd: Cannot install package luci-ssl.
 * opkg_conf_write_status_files: Can't open status file //usr/lib/opkg/status: I/O error.

[    0.780920] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    8.406396] jffs2: notice: (415) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
[    8.423476] mount_root: switching to jffs2 overlay
[  270.902671] jffs2: Write of 1989 bytes at 0x005ce6f8 failed. returned -5, retlen 962
[  270.931965] jffs2: Write of 1989 bytes at 0x005ceec0 failed. returned -5, retlen 0
[  270.939631] jffs2: Not marking the space at 0x005ceec0 as dirty because the flash driver returned retlen zero
[  270.950397] jffs2: Write of 68 bytes at 0x005ceec0 failed. returned -5, retlen 0
[  270.957838] jffs2: Not marking the space at 0x005ceec0 as dirty because the flash driver returned retlen zero
[  270.968584] jffs2: Write of 68 bytes at 0x005ceec0 failed. returned -5, retlen 0
[  270.976027] jffs2: Not marking the space at 0x005ceec0 as dirty because the flash driver returned retlen zero
[  270.986735] jffs2: Write of 68 bytes at 0x005ceec0 failed. returned -5, retlen 0
[  270.994225] jffs2: Not marking the space at 0x005ceec0 as dirty because the flash driver returned retlen zero

[1] https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=fec8fe806963c96a6506c2aebc3572d3a11f285f
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v4.9.133&id=a0239d83e1cb60de5e78452d4708c083b9e3dcbe

Fixes: fec8fe806963 ("kernel: bump 4.9 to 4.9.116")
Signed-off-by: Fabio Bettoni <fbettoni@gmail.com>
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
target/linux/ar71xx/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch [new file with mode: 0644]
target/linux/ar71xx/patches-4.14/411-mtd-cfi_cmdset_0002-force-word-write.patch
target/linux/ath79/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch [new file with mode: 0644]

diff --git a/target/linux/ar71xx/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch b/target/linux/ar71xx/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch
new file mode 100644 (file)
index 0000000..3c1f62f
--- /dev/null
@@ -0,0 +1,64 @@
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -1635,8 +1635,8 @@ static int __xipram do_write_oneword(str
+                       break;
+               }
+-              if (chip_ready(map, adr))
+-                      break;
++              if (chip_good(map, adr, datum))
++                      goto enable_xip;
+               /* Latency issues. Drop the lock, wait a while and retry */
+               UDELAY(map, chip, adr, 1);
+@@ -1652,6 +1652,8 @@ static int __xipram do_write_oneword(str
+               ret = -EIO;
+       }
++
++ enable_xip:
+       xip_enable(map, chip, adr);
+  op_done:
+       if (mode == FL_OTP_WRITE)
+@@ -2230,7 +2232,6 @@ static int cfi_amdstd_panic_write(struct
+       return 0;
+ }
+-
+ /*
+  * Handle devices with one erase region, that only implement
+  * the chip erase command.
+@@ -2298,7 +2299,7 @@ static int __xipram do_erase_chip(struct
+               }
+               if (chip_good(map, adr, map_word_ff(map)))
+-                      break;
++                      goto op_done;
+               if (time_after(jiffies, timeo)) {
+                       printk(KERN_WARNING "MTD %s(): software timeout\n",
+@@ -2322,6 +2323,7 @@ static int __xipram do_erase_chip(struct
+               }
+       }
++ op_done:
+       chip->state = FL_READY;
+       xip_enable(map, chip, adr);
+       DISABLE_VPP(map);
+@@ -2395,7 +2397,7 @@ static int __xipram do_erase_oneblock(st
+               if (chip_good(map, adr, map_word_ff(map))) {
+                       xip_enable(map, chip, adr);
+-                      break;
++                      goto op_done;
+               }
+               if (time_after(jiffies, timeo)) {
+@@ -2421,6 +2423,7 @@ static int __xipram do_erase_oneblock(st
+               }
+       }
++ op_done:
+       chip->state = FL_READY;
+       DISABLE_VPP(map);
+       put_chip(map, chip, adr);
index b28d6c1c2d2475c40f6f3045712e807f835eaee7..3862dfd14b24832b7c7cd234e33ce7be9275f62b 100644 (file)
@@ -35,7 +35,7 @@
  
  /* Atmel chips don't use the same PRI format as AMD chips */
  static void fixup_convert_atmel_pri(struct mtd_info *mtd)
-@@ -1792,6 +1796,7 @@ static int cfi_amdstd_write_words(struct
+@@ -1794,6 +1798,7 @@ static int cfi_amdstd_write_words(struct
  /*
   * FIXME: interleaved mode not tested, and probably not supported!
   */
@@ -43,7 +43,7 @@
  static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                    unsigned long adr, const u_char *buf,
                                    int len)
-@@ -1920,7 +1925,6 @@ static int __xipram do_write_buffer(stru
+@@ -1922,7 +1927,6 @@ static int __xipram do_write_buffer(stru
        return ret;
  }
  
@@ -51,7 +51,7 @@
  static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
                                    size_t *retlen, const u_char *buf)
  {
-@@ -1995,6 +1999,7 @@ static int cfi_amdstd_write_buffers(stru
+@@ -1997,6 +2001,7 @@ static int cfi_amdstd_write_buffers(stru
  
        return 0;
  }
diff --git a/target/linux/ath79/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch b/target/linux/ath79/patches-4.14/403-mtd_fix_cfi_cmdset_0002_status_check.patch
new file mode 100644 (file)
index 0000000..3c1f62f
--- /dev/null
@@ -0,0 +1,64 @@
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -1635,8 +1635,8 @@ static int __xipram do_write_oneword(str
+                       break;
+               }
+-              if (chip_ready(map, adr))
+-                      break;
++              if (chip_good(map, adr, datum))
++                      goto enable_xip;
+               /* Latency issues. Drop the lock, wait a while and retry */
+               UDELAY(map, chip, adr, 1);
+@@ -1652,6 +1652,8 @@ static int __xipram do_write_oneword(str
+               ret = -EIO;
+       }
++
++ enable_xip:
+       xip_enable(map, chip, adr);
+  op_done:
+       if (mode == FL_OTP_WRITE)
+@@ -2230,7 +2232,6 @@ static int cfi_amdstd_panic_write(struct
+       return 0;
+ }
+-
+ /*
+  * Handle devices with one erase region, that only implement
+  * the chip erase command.
+@@ -2298,7 +2299,7 @@ static int __xipram do_erase_chip(struct
+               }
+               if (chip_good(map, adr, map_word_ff(map)))
+-                      break;
++                      goto op_done;
+               if (time_after(jiffies, timeo)) {
+                       printk(KERN_WARNING "MTD %s(): software timeout\n",
+@@ -2322,6 +2323,7 @@ static int __xipram do_erase_chip(struct
+               }
+       }
++ op_done:
+       chip->state = FL_READY;
+       xip_enable(map, chip, adr);
+       DISABLE_VPP(map);
+@@ -2395,7 +2397,7 @@ static int __xipram do_erase_oneblock(st
+               if (chip_good(map, adr, map_word_ff(map))) {
+                       xip_enable(map, chip, adr);
+-                      break;
++                      goto op_done;
+               }
+               if (time_after(jiffies, timeo)) {
+@@ -2421,6 +2423,7 @@ static int __xipram do_erase_oneblock(st
+               }
+       }
++ op_done:
+       chip->state = FL_READY;
+       DISABLE_VPP(map);
+       put_chip(map, chip, adr);