diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2019-11-21 02:49:41 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2019-11-21 02:49:41 +0000 |
commit | a8761a2a55b5ad851e62b12221c1bb9858cd77e6 (patch) | |
tree | dcc09d5ea54a3bf77071107208f8fc85b3294a23 | |
parent | b61ac067064681a906a5dec6ea8d3e81c4efb523 (diff) | |
download | src-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.c | 47 |
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); |