[flashrom] [PATCH] Reorder block_erasers to favor large block erasers over small block erasers

Pablo Cases pablo.cases at flatfrog.com
Thu Jul 31 14:08:11 CEST 2014


This patch reorders the block_erasers by increasing block count with the assumption that the fewer block erase commands that have to be issued the lower the erase times. E.g. this will favor chip erase instructions (as their block count is 1) even though they are generally listed last in the block_erasers list for each chip in flashchips.c

As an example this reduces the erase time for a W25Q64.V chip from 14 minutes to 8 seconds as a single Chip Erase (60h) instruction will be used instead of issuing a sequence of 2048 Sector Erase (20h) commands.

Signed-off-by: Pablo Cases <pablo.cases at flatfrog.com>

Index: flashrom.c
===================================================================
--- flashrom.c	(revision 1832)
+++ flashrom.c	(working copy)
@@ -1432,22 +1432,20 @@
 	return 0;
 }
 
-static int check_block_eraser(const struct flashctx *flash, int k, int log)
+static int check_block_eraser2(struct block_eraser* eraser, int log)
 {
-	struct block_eraser eraser = flash->chip->block_erasers[k];
-
-	if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
+	if (!eraser->block_erase && !eraser->eraseblocks[0].count) {
 		if (log)
 			msg_cdbg("not defined. ");
 		return 1;
 	}
-	if (!eraser.block_erase && eraser.eraseblocks[0].count) {
+	if (!eraser->block_erase && eraser->eraseblocks[0].count) {
 		if (log)
 			msg_cdbg("eraseblock layout is known, but matching "
 				 "block erase function is not implemented. ");
 		return 1;
 	}
-	if (eraser.block_erase && !eraser.eraseblocks[0].count) {
+	if (eraser->block_erase && !eraser->eraseblocks[0].count) {
 		if (log)
 			msg_cdbg("block erase function found, but "
 				 "eraseblock layout is not defined. ");
@@ -1457,6 +1455,38 @@
 	return 0;
 }
 
+static int check_block_eraser(const struct flashctx *flash, int k, int log)
+{
+	struct block_eraser eraser = flash->chip->block_erasers[k];
+	return check_block_eraser2(&eraser, log);	
+}
+
+static struct block_eraser* get_block_erasers(struct flashctx* flash)
+{
+	return flash->chip->block_erasers;
+}
+
+static int compare_by_block_count(const void *a, const void *b)
+{
+	struct block_eraser* bea = (struct block_eraser*)a;
+	struct block_eraser* beb = (struct block_eraser*)b;
+
+	if (check_block_eraser2(bea, 0) && check_block_eraser2(beb, 0))
+		// both erasers are invalid
+		return 0;
+	else if (!check_block_eraser2(bea, 0) && check_block_eraser2(beb, 0))
+		// first eraser valid, second eraser invalid
+		return -1;
+	else if (check_block_eraser2(bea, 0) && !check_block_eraser2(beb, 0))
+		// second eraser valid, first eraser invalid
+		return 1;
+	else {
+		// both erasers are valid, ignore that some chips have 
+		// differently sized erase regions
+		return bea->eraseblocks[0].count - beb->eraseblocks[0].count;
+	}
+}
+
 int erase_and_write_flash(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents)
 {
 	int k, ret = 1;
@@ -1463,6 +1493,7 @@
 	uint8_t *curcontents;
 	unsigned long size = flash->chip->total_size * 1024;
 	unsigned int usable_erasefunctions = count_usable_erasers(flash);
+        struct block_eraser* sorted_erasers;
 
 	msg_cinfo("Erasing and writing flash chip... ");
 	curcontents = malloc(size);
@@ -1473,6 +1504,22 @@
 	/* Copy oldcontents to curcontents to avoid clobbering oldcontents. */
 	memcpy(curcontents, oldcontents, size);
 
+	/* only get the pointer to the block_erasers, 
+	   i.e. block_erasers are sorted in place at their original location,
+	   hence the order might no longer match the order defined in 
+	   flashchips.c */
+	sorted_erasers = get_block_erasers(flash);
+	qsort(sorted_erasers, NUM_ERASEFUNCTIONS, sizeof(struct block_eraser),
+		compare_by_block_count);
+	
+	/* block_erasers are now sorted by ascending block count 
+	   with the assumption on that a low block count results in lower 
+	   erase times than a high block counts */
+	msg_gspew("\nSorted erase functions listed by ascending block count:\n");
+	msg_gspew("Block Size\tBlock Count\n");	
+	for (k = 0; k < NUM_ERASEFUNCTIONS; k++)
+		msg_gspew("%d\t\t%d\n", sorted_erasers[k].eraseblocks[0].size, sorted_erasers[k].eraseblocks[0].count);
+
 	for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
 		if (k != 0)
 			msg_cinfo("Looking for another erase function.\n");

----------------------------------------------------------------------

Pablo Cases, M.Sc.
Senior Software Engineer
FlatFrog Laboratories AB





More information about the flashrom mailing list