Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jun 2012 17:33:50 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 212270 for review
Message-ID:  <201206041733.q54HXoX6012112@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dev/altera/sdcard/altera_sdcard.h>
 
 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206041733.q54HXoX6012112>