summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-02-13 18:13:42 +0000
committerian <ian@FreeBSD.org>2015-02-13 18:13:42 +0000
commit3e6b663e1fe25ee947a722b1c0555e6d97a1a9ab (patch)
tree96e4dfa4c8a2b7cb023afd659dc27f7c2f8acfcb
parent432a94e7fe2210a25e852f288f8dfd3c9bcb26b4 (diff)
downloadFreeBSD-src-3e6b663e1fe25ee947a722b1c0555e6d97a1a9ab.zip
FreeBSD-src-3e6b663e1fe25ee947a722b1c0555e6d97a1a9ab.tar.gz
MFC r277027:
Handle the possibility that SDHCI_PLATFORM_START_TRANSFER() can fail.
-rw-r--r--sys/dev/sdhci/sdhci.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
index 503cbf3..bb99937 100644
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -985,7 +985,6 @@ sdhci_finish_data(struct sdhci_slot *slot)
{
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. */
@@ -994,7 +993,7 @@ sdhci_finish_data(struct sdhci_slot *slot)
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,
@@ -1005,6 +1004,7 @@ sdhci_finish_data(struct sdhci_slot *slot)
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);
@@ -1172,12 +1172,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
}
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. */
@@ -1234,6 +1229,15 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
} 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
OpenPOWER on IntegriCloud