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