PERFORCE change 217312 for review

Brooks Davis brooks at FreeBSD.org
Fri Sep 14 20:36:53 UTC 2012


http://p4web.freebsd.org/@@217312?ac=10

Change 217312 by brooks at brooks_zenith on 2012/09/14 20:35:52

	As an optimization, keep an unaltered copy of the block being
	altered and use this to avoid erase cycles when they are unneeded
	as well as avoiding writing unchanged words.

Affected files ...

.. //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_core.c#4 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_dev.c#3 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_var.h#3 edit

Differences ...

==== //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_core.c#4 (text+ko) ====

@@ -386,9 +386,9 @@
 		uint8_t		*x8;
 		uint16_t	*x16;
 		uint32_t	*x32;
-	} ptr;
+	} ptr, cpyprt;
 	register_t intr;
-	int error, i;
+	int error, i, neederase = 0;
 
 	switch (sc->sc_cmdset) {
 	case CFI_VEND_INTEL_ECS:
@@ -399,31 +399,60 @@
 		break;
 	}
 
-	/* Erase the block. */
-	switch (sc->sc_cmdset) {
-	case CFI_VEND_INTEL_ECS:
-	case CFI_VEND_INTEL_SCS:
-		cfi_write(sc, sc->sc_wrofs, CFI_BCS_BLOCK_ERASE);
-		cfi_write(sc, sc->sc_wrofs, CFI_BCS_CONFIRM);
-		break;
-	case CFI_VEND_AMD_SCS:
-	case CFI_VEND_AMD_ECS:
-		cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START,
-		    CFI_AMD_ERASE_SECTOR);
-		cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE);
-		break;
-	default:
-		/* Better safe than sorry... */
-		return (ENODEV);
-	}
-	error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_erase_timeout);
-	if (error)
-		goto out;
+	/* Check if an erase is required. */
+	for (i = 0; i < sc->sc_wrbufsz; i++)
+		if ((sc->sc_wrbuf[i] & sc->sc_wrbufcpy[i]) != sc->sc_wrbuf[i]) {
+			neederase = 1;
+			break;
+		}
+
+	if (neederase) {
+		/* Erase the block. */
+		switch (sc->sc_cmdset) {
+		case CFI_VEND_INTEL_ECS:
+		case CFI_VEND_INTEL_SCS:
+			cfi_write(sc, sc->sc_wrofs, CFI_BCS_BLOCK_ERASE);
+			cfi_write(sc, sc->sc_wrofs, CFI_BCS_CONFIRM);
+			break;
+		case CFI_VEND_AMD_SCS:
+		case CFI_VEND_AMD_ECS:
+			cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START,
+			    CFI_AMD_ERASE_SECTOR);
+			cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE);
+			break;
+		default:
+			/* Better safe than sorry... */
+			return (ENODEV);
+		}
+		error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_erase_timeout);
+		if (error)
+			goto out;
+	} else
+		error = 0;
 
 	/* Write the block. */
 	ptr.x8 = sc->sc_wrbuf;
+	cpyprt.x8 = sc->sc_wrbufcpy;
 	for (i = 0; i < sc->sc_wrbufsz; i += sc->sc_width) {
 
+		/* Avoid writing unless we are actually changing bits */
+		if (!neederase) {
+			switch (sc->sc_width) {
+			case 1:
+				if(*(ptr.x8 + i) == *(cpyprt.x8 + i))
+					continue;
+				break;
+			case 2:
+				if(*(ptr.x16 + i / 2) == *(cpyprt.x16 + i / 2))
+					continue;
+				break;
+			case 4:
+				if(*(ptr.x32 + i / 4) == *(cpyprt.x32 + i / 4))
+					continue;
+				break;
+			}
+		}
+
 		/*
 		 * Make sure the command to start a write and the
 		 * actual write happens back-to-back without any
@@ -444,15 +473,15 @@
 		switch (sc->sc_width) {
 		case 1:
 			bus_space_write_1(sc->sc_tag, sc->sc_handle,
-			    sc->sc_wrofs + i, *(ptr.x8)++);
+			    sc->sc_wrofs + i, *(ptr.x8 + i));
 			break;
 		case 2:
 			bus_space_write_2(sc->sc_tag, sc->sc_handle,
-			    sc->sc_wrofs + i, *(ptr.x16)++);
+			    sc->sc_wrofs + i, *(ptr.x16 + i / 2));
 			break;
 		case 4:
 			bus_space_write_4(sc->sc_tag, sc->sc_handle,
-			    sc->sc_wrofs + i, *(ptr.x32)++);
+			    sc->sc_wrofs + i, *(ptr.x32 + i / 4));
 			break;
 		}
 

==== //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_dev.c#3 (text+ko) ====

@@ -72,7 +72,8 @@
  * Begin writing into a new block/sector.  We read the sector into
  * memory and keep updating that, until we move into another sector
  * or the process stops writing. At that time we write the whole
- * sector to flash (see cfi_block_finish).
+ * sector to flash (see cfi_block_finish).  To avoid unneeded erase
+ * cycles, keep a pristine copy of the sector on hand.
  */
 int
 cfi_block_start(struct cfi_softc *sc, u_int ofs)
@@ -116,6 +117,8 @@
 			break;
 		}
 	}
+	sc->sc_wrbufcpy = malloc(sc->sc_wrbufsz, M_TEMP, M_WAITOK);
+	memcpy(sc->sc_wrbufcpy, sc->sc_wrbuf, sc->sc_wrbufsz);
 	sc->sc_writing = 1;
 	return (0);
 }
@@ -131,6 +134,7 @@
 
 	error = cfi_write_block(sc);
 	free(sc->sc_wrbuf, M_TEMP);
+	free(sc->sc_wrbufcpy, M_TEMP);
 	sc->sc_wrbuf = NULL;
 	sc->sc_wrbufsz = 0;
 	sc->sc_wrofs = 0;

==== //depot/projects/ctsrd/beribsd/src/sys/dev/cfi/cfi_var.h#3 (text+ko) ====

@@ -58,6 +58,7 @@
 	struct proc	*sc_opened;	/* Process that has us opened. */
 
 	u_char		*sc_wrbuf;
+	u_char		*sc_wrbufcpy;
 	u_int		sc_wrbufsz;
 	u_int		sc_wrofs;
 	u_int		sc_writing;


More information about the p4-projects mailing list