svn commit: r354932 - head/sys/arm/broadcom/bcm2835
Kyle Evans
kevans at FreeBSD.org
Thu Nov 21 02:47:55 UTC 2019
Author: kevans
Date: Thu Nov 21 02:47:55 2019
New Revision: 354932
URL: https://svnweb.freebsd.org/changeset/base/354932
Log:
bcm2835_sdhci: roll back r354823
r354823 kicked DATA_END handling out of the DMA interrupt path "to make
things easy", but this was likely a mistake -- if we know we're done after
we've finished pending DMA operations, we should go ahead and acknowledge
it rather than waiting for the controller to finalize it. If it's not ready,
we'll simply re-enable interrupts and wait for it anyways, to be re-entered
in sdhci_data_intr.
Modified:
head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Thu Nov 21 02:44:05 2019 (r354931)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Thu Nov 21 02:47:55 2019 (r354932)
@@ -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);
}
@@ -625,6 +626,8 @@ 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);
@@ -654,6 +657,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 +741,11 @@ bcm_sdhci_finish_transfer(device_t dev, struct sdhci_s
{
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 +766,6 @@ bcm_sdhci_finish_transfer(device_t dev, struct sdhci_s
sc->dmamap_seg_index = 0;
}
- bcm_sdhci_dma_exit(sc);
sdhci_finish_data(slot);
}
More information about the svn-src-all
mailing list