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.
This commit is contained in:
Kyle Evans 2019-11-21 02:41:22 +00:00
parent 71f0077631
commit 7af945c666
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354930

View File

@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
rounddown(BCM_SDHCI_SLOT_LEFT(slot), BCM_SDHCI_BUFFER_SIZE))
#define DATA_PENDING_MASK (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)
#define DATA_XFER_MASK (DATA_PENDING_MASK | SDHCI_INT_DATA_END)
#ifdef DEBUG
static int bcm2835_sdhci_debug = 0;
@ -579,7 +580,7 @@ bcm_sdhci_start_dma_seg(struct bcm_sdhci_softc *sc)
if (idx == 0) {
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op);
slot->intmask &= ~DATA_PENDING_MASK;
slot->intmask &= ~DATA_XFER_MASK;
bcm_sdhci_write_4(sc->sc_dev, slot, SDHCI_SIGNAL_ENABLE,
slot->intmask);
}
@ -600,7 +601,7 @@ bcm_sdhci_dma_exit(struct bcm_sdhci_softc *sc)
mtx_assert(&slot->mtx, MA_OWNED);
/* Re-enable interrupts */
slot->intmask |= DATA_PENDING_MASK;
slot->intmask |= DATA_XFER_MASK;
bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
slot->intmask);
}
@ -654,6 +655,12 @@ bcm_sdhci_dma_intr(int ch, void *arg)
sdhci_finish_data(slot);
bcm_sdhci_dma_exit(sc);
}
} else if ((reg & SDHCI_INT_DATA_END) != 0) {
bcm_sdhci_dma_exit(sc);
bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS,
reg);
slot->flags &= ~PLATFORM_DATA_STARTED;
sdhci_finish_data(slot);
} else {
bcm_sdhci_dma_exit(sc);
}
@ -732,7 +739,11 @@ bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
{
struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
/* Clean up */
/*
* Clean up. Interrupts are clearly enabled, because we received an
* SDHCI_INT_DATA_END to get this far -- just make sure we don't leave
* anything laying around.
*/
if (sc->dmamap_seg_count != 0) {
/*
* Our segment math should have worked out such that we would
@ -753,7 +764,6 @@ bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
sc->dmamap_seg_index = 0;
}
bcm_sdhci_dma_exit(sc);
sdhci_finish_data(slot);
}