svn commit: r354930 - head/sys/arm/broadcom/bcm2835

Kyle Evans kevans at FreeBSD.org
Thu Nov 21 02:41:23 UTC 2019


Author: kevans
Date: Thu Nov 21 02:41:22 2019
New Revision: 354930
URL: https://svnweb.freebsd.org/changeset/base/354930

Log:
  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.

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 01:24:49 2019	(r354929)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Thu Nov 21 02:41:22 2019	(r354930)
@@ -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_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 +764,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-head mailing list