PERFORCE change 112701 for review

Warner Losh imp at FreeBSD.org
Tue Jan 9 23:03:05 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=112701

Change 112701 by imp at imp_lighthouse on 2007/01/10 07:02:04

	Add a comment about why we need to do the dance we do with enabling
	the PDC, along with a simplified version of the code.

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91_mci.c#30 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91_mci.c#30 (text+ko) ====

@@ -402,16 +402,27 @@
 		}
 	}
 //	printf("CMDR %x ARGR %x with data\n", cmdr, cmd->arg);
+	/*
+	 * For Reads, we need to enable the DMA buffer before we send
+	 * the command.  For writes, alas, it has to be enabled after
+	 * we send the command.  If enabled after the CMDR write for
+	 * reads, fast SD parts could win the race that's present and
+	 * the result would be corrupted data because the ENDRX bit
+	 * would be set, but the dma wouldn't have started yet.  When
+	 * that interrupt returned, we'd enable DMA.  We'd then get a
+	 * RXBUFF interrupt and then a CMDRDY interrupt.  We'd process
+	 * things int he ISR.  But since the DMA started after we got
+	 * the ENDRX and RXBUFF interrupts, when we got the CMDRDY
+	 * interrupt the data would still be in flight, leading to
+	 * corruption.  This race was 'hard' to trigger for slow parts,
+	 * but easy to trigger for faster ones.
+	 */
 	WR4(sc, MCI_ARGR, cmd->arg);
-	if (cmdr & MCI_CMDR_TRCMD_START) {
-		if (cmdr & MCI_CMDR_TRDIR) {
-			WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
-			WR4(sc, MCI_CMDR, cmdr);
-		} else {
-			WR4(sc, MCI_CMDR, cmdr);
-			WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN);
-		}
-	}
+	if ((cmdr & MCI_CMDR_TRCMD_START) && (cmdr & MCI_CMDR_TRDIR))
+		WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
+	WR4(sc, MCI_CMDR, cmdr);
+	if ((cmdr & MCI_CMDR_TRCMD_START) && !(cmdr & MCI_CMDR_TRDIR))
+		WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN);
 	WR4(sc, MCI_IER, MCI_SR_ERROR | ier);
 }
 


More information about the p4-projects mailing list