Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Nov 2019 02:47:55 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r354932 - head/sys/arm/broadcom/bcm2835
Message-ID:  <201911210247.xAL2ltl8046218@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911210247.xAL2ltl8046218>