From owner-p4-projects@FreeBSD.ORG Mon Jun 4 17:33:51 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E63471065689; Mon, 4 Jun 2012 17:33:50 +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 8FA031065680 for ; Mon, 4 Jun 2012 17:33:50 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 713318FC16 for ; Mon, 4 Jun 2012 17:33:50 +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 q54HXo8V012117 for ; Mon, 4 Jun 2012 17:33:50 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q54HXoX6012112 for perforce@freebsd.org; Mon, 4 Jun 2012 17:33:50 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Mon, 4 Jun 2012 17:33:50 GMT Message-Id: <201206041733.q54HXoX6012112@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 212270 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: Mon, 04 Jun 2012 17:33:51 -0000 http://p4web.freebsd.org/@@212270?ac=10 Change 212270 by rwatson@rwatson_svr_ctsrd_mipsbuild on 2012/06/04 17:33:35 Add a work-around for a like Altera SD Card IP core bug in which, mysteriously, the 16-bit word at offset 320 in the memory-mapped 512-byte RXTX buffer is corrupted during 16-bit writes: read back the buffer on every write, and confirm its contents against the bio passed down the storage stack. If it differs, repeat until it doesn't differ any more. This appears to trigger only during two block writes during the early boot, and can require 30-50 attempts to "stick" for one of the blocks -- always /var, where a portion of the directory is otherwise corrupted. This work- around, suggested by Jon Woodruff, doesn't committer corrupted versions to disk, as we detect and recover from corruption before the SD Card write is actually issued. Affected files ... .. //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard_io.c#12 edit Differences ... ==== //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard_io.c#12 (text+ko) ==== @@ -54,6 +54,7 @@ #include int altera_sdcard_ignore_crc_errors = 1; +int altera_sdcard_verify_rxtx_writes = 1; /* * Low-level I/O routines for the Altera SD Card University IP Core driver. @@ -231,14 +232,47 @@ altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data, size_t len) { + u_int differences, i, retry_counter; + uint16_t v; KASSERT((uintptr_t)data % 2 == 0, ("%s: unaligned data %p", __func__, data)); KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0), ("%s: invalid length %ju", __func__, len)); - bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER, - (uint16_t *)data, len / 2); + retry_counter = 0; + do { + bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER, + (uint16_t *)data, len / 2); + + /* + * XXXRW: Due to a possible hardware bug, the above call to + * bus_write_region_2() might not succeed. If the workaround + * is enabled, verify each write and retry until it succeeds. + * + * XXXRW: Do we want a limit counter for retries here? + */ + differences = 0; + if (altera_sdcard_verify_rxtx_writes) { + for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) { + v = bus_read_2(sc->as_res, + ALTERA_SDCARD_OFF_RXTX_BUFFER + i); + if (v != *(uint16_t *)((uint8_t *)data + i)) { + differences++; + device_printf(sc->as_dev, + "%s: retrying write -- difference" + " %u at offset %u, retry %u\n", + __func__, differences, i, + retry_counter); + } + } + if (differences) + retry_counter++; + } + } while (differences != 0); + if (retry_counter) + device_printf(sc->as_dev, "%s: succeeded after %u retries\n", + __func__, retry_counter); } static void