From owner-p4-projects@FreeBSD.ORG Fri Sep 14 20:36:53 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3F4C21065672; Fri, 14 Sep 2012 20:36:52 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E93DB106566B for ; Fri, 14 Sep 2012 20:36:51 +0000 (UTC) (envelope-from brooks@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id D24448FC0A for ; Fri, 14 Sep 2012 20:36:51 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id q8EKapiq052749 for ; Fri, 14 Sep 2012 20:36:51 GMT (envelope-from brooks@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q8EKapUM052746 for perforce@freebsd.org; Fri, 14 Sep 2012 20:36:51 GMT (envelope-from brooks@freebsd.org) Date: Fri, 14 Sep 2012 20:36:51 GMT Message-Id: <201209142036.q8EKapUM052746@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to brooks@freebsd.org using -f From: Brooks Davis To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 217312 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Sep 2012 20:36:53 -0000 http://p4web.freebsd.org/@@217312?ac=10 Change 217312 by brooks@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;