Patchwork mtd-utils: "flash_erase -j" failes with "unable to get NAND oobinfo" on large flash chips.

login
register
mail settings
Submitter Daid
Date April 12, 2011, 9:58 a.m.
Message ID <BANLkTinozqCrqaDGsAX-gWWUg2G3bvg_Rg@mail.gmail.com>
Download mbox | patch
Permalink /patch/90763/
State New
Headers show

Comments

Daid - April 12, 2011, 9:58 a.m.
I've made a patch to fix flash_erase with large flash chips.
flash_erase uses MEMGETOOBSEL which no longer works if the ECC area is
larger then 32 bytes. ECCGETLAYOUT is the replacement ioctl.

This patch is based on the work of Stanley Miao, he made a patch in
June 2010 for flash_eraseall.
http://lists.infradead.org/pipermail/linux-mtd/2010-June/031981.html
I've implemented the backwards compatibility differently, checking
kernel versions doesn't feel correct.


 		}
 		cleanmarker.hdr_crc = cpu_to_je32(mtd_crc32(0, &cleanmarker,
sizeof(cleanmarker) - 4));
Artem Bityutskiy - April 14, 2011, 6:09 a.m.
On Tue, 2011-04-12 at 11:58 +0200, Daid wrote:
> I've made a patch to fix flash_erase with large flash chips.
> flash_erase uses MEMGETOOBSEL which no longer works if the ECC area is
> larger then 32 bytes. ECCGETLAYOUT is the replacement ioctl.
> 
> This patch is based on the work of Stanley Miao, he made a patch in
> June 2010 for flash_eraseall.
> http://lists.infradead.org/pipermail/linux-mtd/2010-June/031981.html
> I've implemented the backwards compatibility differently, checking
> kernel versions doesn't feel correct.

Hi Daid, would you please use libmtd instead? If libmtd does not have
some functionality you need - just add it there.

The thing is that we are trying to unify this stuff a little.

Patch

diff -ur mtd-utils-v1.4.4/flash_erase.c mtd-utils-patch/flash_erase.c
--- mtd-utils-v1.4.4/flash_erase.c	2011-04-01 18:31:43.000000000 +0200
+++ mtd-utils-patch/flash_erase.c	2011-04-12 11:41:43.000000000 +0200
@@ -193,37 +193,57 @@ 
 		if (!isNAND)
 			cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
 		else {
-			struct nand_oobinfo oobinfo;
+#if defined(ECCGETLAYOUT)
+			struct nand_ecclayout ecclayout;

-			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0)
-				return sys_errmsg("%s: unable to get NAND oobinfo", mtd_device);
-
-			/* Check for autoplacement */
-			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
+			memset(&ecclayout, 0, sizeof(ecclayout));
+			if (ioctl(fd, ECCGETLAYOUT, &ecclayout) == 0) {
 				/* Get the position of the free bytes */
-				if (!oobinfo.oobfree[0][1])
-					return errmsg(" Eeep. Autoplacement selected and no empty space in oob");
-				clmpos = oobinfo.oobfree[0][0];
-				clmlen = oobinfo.oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
+				if (!ecclayout.oobfree[0].length) {
+					fprintf(stderr, " Eeep. Autoplacement selected and no empty
space in oob\n");
+					return 1;
+	 			}
+				clmpos = ecclayout.oobfree[0].offset;
+				clmlen = ecclayout.oobfree[0].length;
 			} else {
-				/* Legacy mode */
-				switch (mtd.oob_size) {
-					case 8:
-						clmpos = 6;
-						clmlen = 2;
-						break;
-					case 16:
-						clmpos = 8;
-						clmlen = 8;
-						break;
-					case 64:
-						clmpos = 16;
+#endif/*defined(ECCGETLAYOUT)*/
+				/* new ECC interface failed or not available, fall back to old
OOB interface, which does not support large flash */
+				struct nand_oobinfo oobinfo;
+				if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0)
+					return sys_errmsg("%s: unable to get NAND oobinfo", mtd_device);
+
+				/* Check for autoplacement */
+				if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
+					/* Get the position of the free bytes */
+					if (!oobinfo.oobfree[0][1])
+						return errmsg(" Eeep. Autoplacement selected and no empty space in oob");
+					clmpos = oobinfo.oobfree[0][0];
+					clmlen = oobinfo.oobfree[0][1];
+					if (clmlen > 8)
 						clmlen = 8;
-						break;
+				} else {
+					/* Legacy mode */
+					switch (mtd.oob_size) {
+						case 8:
+							clmpos = 6;
+							clmlen = 2;
+							break;
+						case 16:
+							clmpos = 8;
+							clmlen = 8;
+							break;
+						case 64:
+							clmpos = 16;
+							clmlen = 8;
+							break;
+					}
 				}
+#if defined(ECCGETLAYOUT)
 			}
+#endif/*defined(ECCGETLAYOUT)*/
+
+			if (clmlen > 8)
+				clmlen = 8;
 			cleanmarker.totlen = cpu_to_je32(8);