Patchwork Faster flash_eraseall for NOR flash

login
register
mail settings
Submitter Øyvind Harboe
Date Dec. 14, 2010, 7:27 p.m.
Message ID <AANLkTim7-ZpO5nQ1Up=rxLJVbCLNJqfbiUGvSnsrONay@mail.gmail.com>
Download mbox | patch
Permalink /patch/75526/
State New
Headers show

Comments

Øyvind Harboe - Dec. 14, 2010, 7:27 p.m.
On Tue, Dec 14, 2010 at 4:47 PM, Mike Frysinger <vapier.adi@gmail.com> wrote:
> On Tue, Dec 14, 2010 at 10:46, Øyvind Harboe wrote:
>> I'll see about getting this done. Don't know when though, if
>> someone beats me to the punch here, no loss :-)
>
> np; take your time.  thanks for the improvements!

This is the server, right?

http://git.infradead.org/mtd-utils.git

I made a stab at trying to get something to build at least.
Mike Frysinger - Dec. 14, 2010, 8:18 p.m.
On Tue, Dec 14, 2010 at 14:27, Øyvind Harboe wrote:
> This is the server, right?
>
> http://git.infradead.org/mtd-utils.git

yes
-mike

Patch

From 89aaa5dc801c05e1d11141fa7d0789b072bde655 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=98yvind=20Harboe?= <oyvind.harboe@zylin.com>
Date: Tue, 14 Dec 2010 20:24:10 +0100
Subject: [PATCH] flash_erase: wip to add NOR skip erased block option

---
 flash_erase.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 52 insertions(+), 1 deletions(-)

diff --git a/flash_erase.c b/flash_erase.c
index 1a7b52e..1000397 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -46,6 +46,7 @@  static int quiet;		/* true -- don't output progress */
 static int jffs2;		/* format for jffs2 usage */
 static int noskipbad;		/* do not skip bad blocks */
 static int unlock;		/* unlock sectors before erasing */
+static int skip_erased;		/* Skip erased NOR flash blocks, including cleanmarker check */
 
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
@@ -68,6 +69,7 @@  static void display_help (void)
 			"  -N, --noskipbad   don't skip bad blocks\n"
 			"  -u, --unlock      unlock sectors before erasing\n"
 			"  -q, --quiet       display progress messages\n"
+			"  -s, --skip-erased skip erased NOR sectors\n"
 			"      --silent      same as --quiet\n"
 			"      --help        display this help and exit\n"
 			"      --version     output version information and exit\n",
@@ -104,7 +106,7 @@  int main(int argc, char *argv[])
 	 */
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "jNqu";
+		static const char *short_options = "sjNqu";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -113,6 +115,7 @@  int main(int argc, char *argv[])
 			{"quiet", no_argument, 0, 'q'},
 			{"silent", no_argument, 0, 'q'},
 			{"unlock", no_argument, 0, 'u'},
+			{"skip-erased", no_argument, 0, 's'},
 
 			{0, 0, 0, 0},
 		};
@@ -145,6 +148,9 @@  int main(int argc, char *argv[])
 		case 'u':
 			unlock = 1;
 			break;
+		case 's':
+			skip_erased = 1;
+			break;
 		case '?':
 			error = 1;
 			break;
@@ -250,8 +256,53 @@  int main(int argc, char *argv[])
 			}
 		}
 
+		/* Can we skip this one if it is already erased?
+		 * Perhaps NAND performance could be improved by adding support for
+		 * those cleanmarkers as well?
+		 *
+		 * Currently this only works with JFFS2 NOR clean markers
+		 */
+		int skip = 0;
+		if (skip_erased && !isNAND) {
+			uint8_t *tmp = malloc(mtd.eb_size);
+			if (tmp == NULL) {
+			  return errmsg("Out of memory");
+			}
+			ssize_t actual = pread(fd, tmp, mtd.eb_size, offset);
+			if (actual != mtd.eb_size) {
+			  return errmsg("%s: MTD read failure: %s", mtd_device, strerror(errno));
+			}
+			ssize_t i = 0;
+			int ok = 1;
+
+			if (jffs2) {
+				ok = memcmp(tmp, &cleanmarker, sizeof (cleanmarker)) == 0;
+				i = sizeof (cleanmarker);
+			}
+
+			if (ok)
+			{
+				for (; i < mtd.eb_size; i++)
+				{
+					if (tmp[i] != 0xff)
+						break;
+				}
+				if (i == mtd.eb_size)
+				{
+					/* Yup! we can skip! Here we could improve things by
+					 * adding support for NAND cleanmarkers
+					 */
+					skip = 1;
+				}
+			}
+			free(tmp);
+		}
+
 		show_progress(&mtd, offset, eb, eb_start, eb_cnt);
 
+		if (skip)
+			continue;
+
 		if (unlock) {
 			if (mtd_unlock(&mtd, fd, eb) != 0) {
 				sys_errmsg("%s: MTD unlock failure", mtd_device);
-- 
1.7.0.4