Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Nov 2019 02:41:22 +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: r354930 - head/sys/arm/broadcom/bcm2835
Message-ID:  <201911210241.xAL2fMCZ042942@repo.freebsd.org>

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



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