aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2019-11-21 02:49:41 +0000
committerKyle Evans <kevans@FreeBSD.org>2019-11-21 02:49:41 +0000
commita8761a2a55b5ad851e62b12221c1bb9858cd77e6 (patch)
treedcc09d5ea54a3bf77071107208f8fc85b3294a23
parentb61ac067064681a906a5dec6ea8d3e81c4efb523 (diff)
downloadsrc-a8761a2a55b5ad851e62b12221c1bb9858cd77e6.tar.gz
src-a8761a2a55b5ad851e62b12221c1bb9858cd77e6.zip
bcm2835_sdhci: clean up DMA segments in error handling path
Later parts assume that this would've been done if interrupts are enabled, but this is the only case in which that wouldn't have been true. This commit also reorders operations such that we're done touching slot/slot->intmask before we call back into the SDHCI framework and exit.
Notes
Notes: svn path=/head/; revision=354933
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_sdhci.c47
1 files changed, 24 insertions, 23 deletions
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
index 7f71ab75f398..3181e9dccf08 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
@@ -607,6 +607,25 @@ bcm_sdhci_dma_exit(struct bcm_sdhci_softc *sc)
}
static void
+bcm_sdhci_dma_unload(struct bcm_sdhci_softc *sc)
+{
+ struct sdhci_slot *slot = &sc->sc_slot;
+
+ if (sc->dmamap_seg_count == 0)
+ return;
+ if ((slot->curcmd->data->flags & MMC_DATA_READ) != 0)
+ bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
+ BUS_DMASYNC_POSTREAD);
+ else
+ bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map);
+
+ sc->dmamap_seg_count = 0;
+ sc->dmamap_seg_index = 0;
+}
+
+static void
bcm_sdhci_dma_intr(int ch, void *arg)
{
struct bcm_sdhci_softc *sc = (struct bcm_sdhci_softc *)arg;
@@ -626,18 +645,7 @@ bcm_sdhci_dma_intr(int ch, void *arg)
goto out;
}
- if (sc->dmamap_seg_count == 0)
- return;
- if ((slot->curcmd->data->flags & MMC_DATA_READ) != 0)
- bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
- BUS_DMASYNC_POSTREAD);
- else
- bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map);
-
- sc->dmamap_seg_count = 0;
- sc->dmamap_seg_index = 0;
+ bcm_sdhci_dma_unload(sc);
/*
* If we had no further segments pending, we need to determine how to
@@ -654,8 +662,10 @@ bcm_sdhci_dma_intr(int ch, void *arg)
bcm_sdhci_start_dma(slot);
if (slot->curcmd->error != 0) {
- sdhci_finish_data(slot);
+ /* We won't recover from this error for this command. */
+ bcm_sdhci_dma_unload(sc);
bcm_sdhci_dma_exit(sc);
+ sdhci_finish_data(slot);
}
} else if ((reg & SDHCI_INT_DATA_END) != 0) {
bcm_sdhci_dma_exit(sc);
@@ -754,16 +764,7 @@ bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
* regressed to SDHCI-driven PIO to finish the operation and
* this is certainly caused by developer-error.
*/
- if (slot->curcmd->data->flags & MMC_DATA_READ)
- bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
- BUS_DMASYNC_POSTREAD);
- else
- bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map);
-
- sc->dmamap_seg_count = 0;
- sc->dmamap_seg_index = 0;
+ bcm_sdhci_dma_unload(sc);
}
sdhci_finish_data(slot);