Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 11 Jan 2015 21:25:04 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r277027 - head/sys/dev/sdhci
Message-ID:  <201501112125.t0BLP4mx057006@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Jan 11 21:25:03 2015
New Revision: 277027
URL: https://svnweb.freebsd.org/changeset/base/277027

Log:
  Handle the possibility that SDHCI_PLATFORM_START_TRANSFER() can fail, by
  moving the handling of curcmd->error != 0 to the end of the interrupt
  handler.  Also make sdhci_finish_data() idempotent by moving the setting
  of slot->data_done = 1 down past the point where the busdma buffer is
  unmapped.  This allows for the possibility that the finish routine can
  get called from multiple places when handling errors.

Modified:
  head/sys/dev/sdhci/sdhci.c

Modified: head/sys/dev/sdhci/sdhci.c
==============================================================================
--- head/sys/dev/sdhci/sdhci.c	Sun Jan 11 20:55:16 2015	(r277026)
+++ head/sys/dev/sdhci/sdhci.c	Sun Jan 11 21:25:03 2015	(r277027)
@@ -984,7 +984,6 @@ sdhci_finish_data(struct sdhci_slot *slo
 {
 	struct mmc_data *data = slot->curcmd->data;
 
-	slot->data_done = 1;
 	/* Interrupt aggregation: Restore command interrupt.
 	 * Auxiliary restore point for the case when data interrupt
 	 * happened first. */
@@ -993,7 +992,7 @@ sdhci_finish_data(struct sdhci_slot *slo
 		    slot->intmask |= SDHCI_INT_RESPONSE);
 	}
 	/* Unload rest of data from DMA buffer. */
-	if (slot->flags & SDHCI_USE_DMA) {
+	if (!slot->data_done && (slot->flags & SDHCI_USE_DMA)) {
 		if (data->flags & MMC_DATA_READ) {
 			size_t left = data->len - slot->offset;
 			bus_dmamap_sync(slot->dmatag, slot->dmamap, 
@@ -1004,6 +1003,7 @@ sdhci_finish_data(struct sdhci_slot *slo
 			bus_dmamap_sync(slot->dmatag, slot->dmamap, 
 			    BUS_DMASYNC_POSTWRITE);
 	}
+	slot->data_done = 1;
 	/* If there was error - reset the host. */
 	if (slot->curcmd->error) {
 		sdhci_reset(slot, SDHCI_RESET_CMD);
@@ -1171,12 +1171,7 @@ sdhci_data_irq(struct sdhci_slot *slot, 
 	}
 	if (slot->curcmd->error) {
 		/* No need to continue after any error. */
-		if (slot->flags & PLATFORM_DATA_STARTED) {
-			slot->flags &= ~PLATFORM_DATA_STARTED;
-			SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
-		} else
-			sdhci_finish_data(slot);
-		return;
+		goto done;
 	}
 
 	/* Handle PIO interrupt. */
@@ -1233,6 +1228,15 @@ sdhci_data_irq(struct sdhci_slot *slot, 
 		} else
 			sdhci_finish_data(slot);
 	}
+done:
+	if (slot->curcmd != NULL && slot->curcmd->error != 0) {
+		if (slot->flags & PLATFORM_DATA_STARTED) {
+			slot->flags &= ~PLATFORM_DATA_STARTED;
+			SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
+		} else
+			sdhci_finish_data(slot);
+		return;
+	}
 }
 
 static void



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