svn commit: r277027 - head/sys/dev/sdhci
Ian Lepore
ian at FreeBSD.org
Sun Jan 11 21:25:05 UTC 2015
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
More information about the svn-src-head
mailing list