From patchwork Thu Apr 14 11:43:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daid X-Patchwork-Id: 91222 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8EB0DB710E for ; Thu, 14 Apr 2011 21:44:55 +1000 (EST) Received: from canuck.infradead.org ([2001:4978:20e::1]) by bombadil.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1QAKxd-0006u1-9o; Thu, 14 Apr 2011 11:43:45 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1QAKxb-0004Bm-Fg; Thu, 14 Apr 2011 11:43:43 +0000 Received: from mail-vx0-f177.google.com ([209.85.220.177]) by canuck.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1QAKxX-0004BU-5S for linux-mtd@lists.infradead.org; Thu, 14 Apr 2011 11:43:40 +0000 Received: by vxd2 with SMTP id 2so1532166vxd.36 for ; Thu, 14 Apr 2011 04:43:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=p1DjAmjeD+2E8celk7IpaI/lKuRMBttBeHaH8Cql0r8=; b=gA4aKRONJzT6f/jcIgMsIhofrKu5BArOFIhzZWb3YihiDXWFz0pKl4mr0qGvN68Glk 3ZcKOOEEehgkz2HSUGZOPpUFNZB4g+c7K0UBkCVvgajqMfiNBmtZjaDvCZajaWWZRKtP cJhVtc+JgKjNAUvemHYqVlKoIgOYc0LcUiE8o= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=Y6RaPbH3jOHLm2sA96/HfH79WSTrUO24gxfbdgm5t7RNaJDynND2cqND2yNZC/kH3R MbYutrKK+2KtWTdA/lhLlHmbXuOqGgfhasvnijK9str/I/EkRM573DmNc+lgxMM4P4wX ANHIKPXzGq48szUyALkKoJ0q5gjha+GBtOVBw= MIME-Version: 1.0 Received: by 10.52.75.165 with SMTP id d5mr873135vdw.300.1302781415722; Thu, 14 Apr 2011 04:43:35 -0700 (PDT) Received: by 10.220.63.79 with HTTP; Thu, 14 Apr 2011 04:43:35 -0700 (PDT) In-Reply-To: <1302761383.2796.4.camel@localhost> References: <1302761383.2796.4.camel@localhost> Date: Thu, 14 Apr 2011 13:43:35 +0200 Message-ID: Subject: Re: mtd-utils: "flash_erase -j" failes with "unable to get NAND oobinfo" on large flash chips. From: Daid To: dedekind1@gmail.com X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110414_074339_396890_C780ECDC X-CRM114-Status: GOOD ( 30.56 ) X-Spam-Score: 2.1 (++) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (2.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is freemail (daid303[at]gmail.com) 2.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (daid303[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.220.177 listed in list.dnswl.org] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 T_TO_NO_BRKTS_FREEMAIL T_TO_NO_BRKTS_FREEMAIL Cc: linux-mtd@lists.infradead.org X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org On Thu, Apr 14, 2011 at 8:09 AM, Artem Bityutskiy wrote: > 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. > > -- > Best Regards, > Artem Bityutskiy (Артём Битюцкий) > > Hi Artem, libmtd didn't have the functionality I needed. I've made a new patch with the functionality build into libmtd. I've added the extra information to struct mtd_dev_info, however, the info needed is only available with ioctls, so even with the sysfs interface it needs to open /dev/mtdXX. When you use mtd_get_dev_info, it reads all the information, which simple for the user of libmtd, but sort of mixes legacy and the sysfs interface. Note that I can only verify if it works with the legacy interface, because we are still a few kernel versions behind on the hardware I run on. (2.6.27) Best Regards, David Braam struct libmtd *lib; @@ -720,9 +796,12 @@ memset(mtd, 0, sizeof(struct mtd_dev_info)); mtd->mtd_num = mtd_num; - if (!lib->sysfs_supported) - return legacy_get_dev_info1(mtd_num, mtd); - else { + if (!lib->sysfs_supported) { + ret = legacy_get_dev_info1(mtd_num, mtd); + if (ret < 0) + return ret; + return mtd_get_oob_info(mtd); + } else { char file[strlen(lib->mtd) + 10]; sprintf(file, lib->mtd, mtd_num); @@ -767,6 +846,9 @@ mtd->eb_cnt = mtd->size / mtd->eb_size; mtd->type = type_str2int(mtd->type_str); mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH); + + if (mtd_get_oob_info(mtd)) + return -1; return 0; } @@ -777,7 +859,12 @@ struct libmtd *lib = (struct libmtd *)desc; if (!lib->sysfs_supported) - return legacy_get_dev_info(node, mtd); + { + int ret = legacy_get_dev_info(node, mtd); + if (ret < 0) + return ret; + return mtd_get_oob_info(mtd); + } if (dev_node2num(lib, node, &mtd_num)) return -1; diff -ur mtd-utils-ori/flash_erase.c mtd-utils-v1.4.4/flash_erase.c --- mtd-utils-ori/flash_erase.c 2011-04-01 18:31:43.000000000 +0200 +++ mtd-utils-v1.4.4/flash_erase.c 2011-04-14 13:06:16.000000000 +0200 @@ -190,40 +190,18 @@ if (jffs2) { cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); - if (!isNAND) + if (!isNAND) { cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker)); - else { - 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; - } 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; - } - } + } else { + if (!mtd.oob_free[0].length) { + fprintf(stderr, " Eeep. No empty space in oob for JFFS2 cleanmarkers\n"); + return 1; + } + clmpos = mtd.oob_free[0].offset; + clmlen = mtd.oob_free[0].length; + if (clmlen > 8) + clmlen = 8; + cleanmarker.totlen = cpu_to_je32(8); } cleanmarker.hdr_crc = cpu_to_je32(mtd_crc32(0, &cleanmarker, sizeof(cleanmarker) - 4)); diff -ur mtd-utils-ori/include/libmtd.h mtd-utils-v1.4.4/include/libmtd.h --- mtd-utils-ori/include/libmtd.h 2011-04-01 18:31:43.000000000 +0200 +++ mtd-utils-v1.4.4/include/libmtd.h 2011-04-14 11:40:48.000000000 +0200 @@ -31,6 +31,8 @@ #define MTD_NAME_MAX 127 /* Maximum MTD device type string length */ #define MTD_TYPE_MAX 64 +/* Maximum MTD nand OOB free entries */ +#define MTD_NAND_MAX_OOBFREE_ENTRIES 8 /* MTD library descriptor */ typedef void * libmtd_t; @@ -50,6 +52,17 @@ }; /** + * struct mtd_nand_oobfree - information about free OOB areas + * @offset: offset of free OOB area from start of OOB area + * @length: length of free OOB area + */ +struct mtd_nand_oobfree +{ + int offset; + int length; +}; + +/** * struct mtd_dev_info - information about an MTD device. * @mtd_num: MTD device number * @major: major number of corresponding character device @@ -66,6 +79,10 @@ * @region_cnt: count of additional erase regions * @writable: zero if the device is read-only * @bb_allowed: non-zero if the MTD device may have bad eraseblocks + * @eccbytes: number of ecc bytes in OOB area + * @eccpos: position of ecc bytes in OOB area + * @oob_available: number of bytes available in OOB area free other use then ECC + * @oob_free: location and sizes of free OOB areas */ struct mtd_dev_info { @@ -84,6 +101,10 @@ int region_cnt; unsigned int writable:1; unsigned int bb_allowed:1; + int eccbytes; + int eccpos[64]; + int oob_available; + struct mtd_nand_oobfree oob_free[MTD_NAND_MAX_OOBFREE_ENTRIES]; }; /** diff -ur mtd-utils-ori/lib/libmtd.c mtd-utils-v1.4.4/lib/libmtd.c --- mtd-utils-ori/lib/libmtd.c 2011-04-01 18:31:43.000000000 +0200 +++ mtd-utils-v1.4.4/lib/libmtd.c 2011-04-14 13:30:20.000000000 +0200 @@ -37,6 +37,8 @@ #include "libmtd_int.h" #include "common.h" +#define MTD_DEV_PATT "/dev/mtd%d" + /** * mkpath - compose full path from 2 given components. * @path: the first component @@ -548,6 +550,80 @@ return 1; } +/** + * mtd_get_oob_info - fill the mtd_dev_info structure with information + * about the OOB data. + */ +static int mtd_get_oob_info(struct mtd_dev_info *mtd) +{ + int i, fd; + char node[sizeof(MTD_DEV_PATT) + 20]; + + sprintf(node, MTD_DEV_PATT, mtd->mtd_num); + fd = open(node, O_RDWR); + if (fd == -1) + return sys_errmsg("cannot open \"%s\"", node); + + if (mtd->type == MTD_NANDFLASH) { + /* get ECC/OOB information for NAND flash */ +#if defined(ECCGETLAYOUT) + struct nand_ecclayout ecclayout; + memset(&ecclayout, 0, sizeof(ecclayout)); + if (ioctl(fd, ECCGETLAYOUT, &ecclayout) == 0) { + mtd->eccbytes = ecclayout.eccbytes; + for(i=0; i<64; i++) { + mtd->eccpos[i] = ecclayout.eccpos[i]; + } + mtd->oob_available = ecclayout.oobavail; + for (i=0; ioob_free[i].offset = ecclayout.oobfree[i].offset; + mtd->oob_free[i].length = ecclayout.oobfree[i].length; + } + } else { +#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) + { + /* Check for autoplacement */ + mtd->eccbytes = oobinfo.eccbytes; + for(i=0;i<32;i++) { + mtd->eccpos[i] = oobinfo.eccpos[i]; + } + if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) { + for(i=0;i<8;i++) { + mtd->oob_free[i].offset = oobinfo.oobfree[i][0]; + mtd->oob_free[i].length = oobinfo.oobfree[i][1]; + mtd->oob_available += mtd->oob_free[i].length; + } + } else{ + /* Legacy mode */ + switch (mtd->oob_size) { + case 8: + mtd->oob_free[0].offset = 6; + mtd->oob_free[0].length = 2; + break; + case 16: + mtd->oob_free[0].offset = 8; + mtd->oob_free[0].length = 8; + break; + case 64: + mtd->oob_free[0].offset = 16; + mtd->oob_free[0].length = 8; + break; + } + mtd->oob_available = mtd->oob_free[0].length; + } + } +#if defined(ECCGETLAYOUT) + } +#endif/*defined(ECCGETLAYOUT)*/ + } + close(fd); + + return 0; +} + libmtd_t libmtd_open(void) {