Module Name:    src
Committed By:   jmcneill
Date:           Fri Jul 31 15:00:08 UTC 2015

Modified Files:
        src/sys/arch/arm/broadcom: bcm2835_emmc.c
        src/sys/arch/arm/omap: omap3_sdhc.c
        src/sys/dev/sdmmc: sdhc.c sdhcvar.h

Log Message:
Simplify sdhc(4) locking


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/arm/broadcom/bcm2835_emmc.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/omap/omap3_sdhc.c
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/sdmmc/sdhc.c
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/sdmmc/sdhcvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/broadcom/bcm2835_emmc.c
diff -u src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.23 src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.24
--- src/sys/arch/arm/broadcom/bcm2835_emmc.c:1.23	Wed Jul 29 14:22:49 2015
+++ src/sys/arch/arm/broadcom/bcm2835_emmc.c	Fri Jul 31 15:00:07 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_emmc.c,v 1.23 2015/07/29 14:22:49 skrll Exp $	*/
+/*	$NetBSD: bcm2835_emmc.c,v 1.24 2015/07/31 15:00:07 jmcneill Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.23 2015/07/29 14:22:49 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.24 2015/07/31 15:00:07 jmcneill Exp $");
 
 #include "bcmdmac.h"
 
@@ -64,7 +64,6 @@ struct bcmemmc_softc {
 	struct sdhc_host	*sc_hosts[1];
 	void			*sc_ih;
 
-	kmutex_t		sc_lock;
 	kcondvar_t		sc_cv;
 
 	enum bcmemmc_dma_state	sc_state;
@@ -165,7 +164,6 @@ bcmemmc_attach(device_t parent, device_t
 	sc->sc.sc_vendor_transfer_data_dma = bcmemmc_xfer_data_dma;
 
 	sc->sc_state = EMMC_DMA_STATE_IDLE;
-	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SDMMC);
 	cv_init(&sc->sc_cv, "bcmemmcdma");
 
 	int rseg;
@@ -242,9 +240,12 @@ static int
 bcmemmc_xfer_data_dma(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
 {
 	struct bcmemmc_softc * const sc = device_private(sdhc_sc->sc_dev);
+	kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
 	size_t seg;
 	int error;
 
+	KASSERT(mutex_owned(plock));
+
 	for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
 		sc->sc_cblk[seg].cb_ti =
 		    __SHIFTIN(11, DMAC_TI_PERMAP); /* e.MMC */
@@ -303,14 +304,13 @@ bcmemmc_xfer_data_dma(struct sdhc_softc 
 
 	error = 0;
 
-	mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_state == EMMC_DMA_STATE_IDLE);
 	sc->sc_state = EMMC_DMA_STATE_BUSY;
 	bcm_dmac_set_conblk_addr(sc->sc_dmac,
 	    sc->sc_dmamap->dm_segs[0].ds_addr);
 	bcm_dmac_transfer(sc->sc_dmac);
 	while (sc->sc_state == EMMC_DMA_STATE_BUSY) {
-		error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz * 10);
+		error = cv_timedwait(&sc->sc_cv, plock, hz * 10);
 		if (error == EWOULDBLOCK) {
 			device_printf(sc->sc.sc_dev, "transfer timeout!\n");
 			bcm_dmac_halt(sc->sc_dmac);
@@ -319,7 +319,6 @@ bcmemmc_xfer_data_dma(struct sdhc_softc 
 			break;
 		}
 	}
-	mutex_exit(&sc->sc_lock);
 
 	bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_dmamap, 0,
 	    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
@@ -331,12 +330,12 @@ static void
 bcmemmc_dma_done(void *arg)
 {
 	struct bcmemmc_softc * const sc = arg;
+	kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
 
-	mutex_enter(&sc->sc_lock);
+	mutex_enter(plock);
 	KASSERT(sc->sc_state == EMMC_DMA_STATE_BUSY);
 	sc->sc_state = EMMC_DMA_STATE_IDLE;
 	cv_broadcast(&sc->sc_cv);
-	mutex_exit(&sc->sc_lock);
-
+	mutex_exit(plock);
 }
 #endif

Index: src/sys/arch/arm/omap/omap3_sdhc.c
diff -u src/sys/arch/arm/omap/omap3_sdhc.c:1.16 src/sys/arch/arm/omap/omap3_sdhc.c:1.17
--- src/sys/arch/arm/omap/omap3_sdhc.c:1.16	Tue Apr 14 18:45:25 2015
+++ src/sys/arch/arm/omap/omap3_sdhc.c	Fri Jul 31 15:00:07 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $	*/
+/*	$NetBSD: omap3_sdhc.c,v 1.17 2015/07/31 15:00:07 jmcneill Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.17 2015/07/31 15:00:07 jmcneill Exp $");
 
 #include "opt_omap.h"
 #include "edma.h"
@@ -102,7 +102,6 @@ struct obiosdhc_softc {
 	struct edma_channel	*sc_edma_rx;
 	uint16_t		sc_edma_param_tx[EDMA_MAX_PARAMS];
 	uint16_t		sc_edma_param_rx[EDMA_MAX_PARAMS];
-	kmutex_t		sc_edma_lock;
 	kcondvar_t		sc_edma_cv;
 	bus_addr_t		sc_edma_fifo;
 	bool			sc_edma_pending;
@@ -230,7 +229,6 @@ obiosdhc_attach(device_t parent, device_
 
 #if NEDMA > 0
 	if (oa->obio_edmabase != -1) {
-		mutex_init(&sc->sc_edma_lock, MUTEX_DEFAULT, IPL_SCHED);
 		cv_init(&sc->sc_edma_cv, "sdhcedma");
 		sc->sc_edma_fifo = oa->obio_addr +
 		    OMAP3_SDMMC_SDHC_OFFSET + SDHC_DATA;
@@ -468,6 +466,7 @@ static int
 obiosdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
 {
 	struct obiosdhc_softc *sc = device_private(sdhc_sc->sc_dev);
+	kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
 	struct edma_channel *edma;
 	uint16_t *edma_param;
 	struct edma_param ep;
@@ -475,6 +474,8 @@ obiosdhc_edma_xfer_data(struct sdhc_soft
 	int error;
 	int blksize = MIN(cmd->c_datalen, cmd->c_blklen);
 
+	KASSERT(mutex_owned(plock));
+
 	edma = ISSET(cmd->c_flags, SCF_CMD_READ) ?
 	    sc->sc_edma_rx : sc->sc_edma_tx;
 	edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ?
@@ -540,12 +541,11 @@ obiosdhc_edma_xfer_data(struct sdhc_soft
 #endif
 	}
 
-	mutex_enter(&sc->sc_edma_lock);
 	error = 0;
 	sc->sc_edma_pending = true;
 	edma_transfer_enable(edma, edma_param[0]);
 	while (sc->sc_edma_pending) {
-		error = cv_timedwait(&sc->sc_edma_cv, &sc->sc_edma_lock, hz*10);
+		error = cv_timedwait(&sc->sc_edma_cv, plock, hz*10);
 		if (error == EWOULDBLOCK) {
 			device_printf(sc->sc.sc_dev, "transfer timeout!\n");
 			edma_dump(edma);
@@ -557,7 +557,6 @@ obiosdhc_edma_xfer_data(struct sdhc_soft
 		}
 	}
 	edma_halt(edma);
-	mutex_exit(&sc->sc_edma_lock);
 
 	return error;
 }
@@ -566,11 +565,12 @@ static void
 obiosdhc_edma_done(void *priv)
 {
 	struct obiosdhc_softc *sc = priv;
+	kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
 
-	mutex_enter(&sc->sc_edma_lock);
+	mutex_enter(plock);
 	KASSERT(sc->sc_edma_pending == true);
 	sc->sc_edma_pending = false;
 	cv_broadcast(&sc->sc_edma_cv);
-	mutex_exit(&sc->sc_edma_lock);
+	mutex_exit(plock);
 }
 #endif

Index: src/sys/dev/sdmmc/sdhc.c
diff -u src/sys/dev/sdmmc/sdhc.c:1.64 src/sys/dev/sdmmc/sdhc.c:1.65
--- src/sys/dev/sdmmc/sdhc.c:1.64	Thu Jul 30 15:03:14 2015
+++ src/sys/dev/sdmmc/sdhc.c	Fri Jul 31 15:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhc.c,v 1.64 2015/07/30 15:03:14 jmcneill Exp $	*/
+/*	$NetBSD: sdhc.c,v 1.65 2015/07/31 15:00:08 jmcneill Exp $	*/
 /*	$OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $	*/
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.64 2015/07/30 15:03:14 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.65 2015/07/31 15:00:08 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -66,8 +66,6 @@ struct sdhc_host {
 
 	device_t sdmmc;			/* generic SD/MMC device */
 
-	struct kmutex host_mtx;
-
 	u_int clkbase;			/* base clock frequency in KHz */
 	int maxblklen;			/* maximum block length */
 	uint32_t ocr;			/* OCR value from capabilities */
@@ -76,8 +74,8 @@ struct sdhc_host {
 
 	uint16_t intr_status;		/* soft interrupt status */
 	uint16_t intr_error_status;	/* soft error status */
-	struct kmutex intr_mtx;
-	struct kcondvar intr_cv;
+	kmutex_t intr_lock;
+	kcondvar_t intr_cv;
 
 	int specver;			/* spec. version */
 
@@ -271,8 +269,7 @@ sdhc_host_found(struct sdhc_softc *sc, b
 	hp->ios = iosize;
 	hp->dmat = sc->sc_dmat;
 
-	mutex_init(&hp->host_mtx, MUTEX_DEFAULT, IPL_SDMMC);
-	mutex_init(&hp->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC);
+	mutex_init(&hp->intr_lock, MUTEX_DEFAULT, IPL_SDMMC);
 	cv_init(&hp->intr_cv, "sdhcintr");
 
 	if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
@@ -315,9 +312,7 @@ sdhc_host_found(struct sdhc_softc *sc, b
 	if (ISSET(sc->sc_flags, SDHC_FLAG_HOSTCAPS)) {
 		caps = sc->sc_caps;
 	} else {
-		mutex_enter(&hp->host_mtx);
 		caps = HREAD4(hp, SDHC_CAPABILITIES);
-		mutex_exit(&hp->host_mtx);
 	}
 
 	/*
@@ -528,8 +523,7 @@ adma_done:
 
 err:
 	cv_destroy(&hp->intr_cv);
-	mutex_destroy(&hp->intr_mtx);
-	mutex_destroy(&hp->host_mtx);
+	mutex_destroy(&hp->intr_lock);
 	free(hp, M_DEVBUF);
 	sc->sc_host[--sc->sc_nhosts] = NULL;
 err1:
@@ -562,8 +556,7 @@ sdhc_detach(struct sdhc_softc *sc, int f
 			sdhc_soft_reset(hp, SDHC_RESET_ALL);
 		}
 		cv_destroy(&hp->intr_cv);
-		mutex_destroy(&hp->intr_mtx);
-		mutex_destroy(&hp->host_mtx);
+		mutex_destroy(&hp->intr_lock);
 		if (hp->ios > 0) {
 			bus_space_unmap(hp->iot, hp->ioh, hp->ios);
 			hp->ios = 0;
@@ -672,7 +665,7 @@ sdhc_host_reset1(sdmmc_chipset_handle_t 
 	uint32_t sdhcimask;
 	int error;
 
-	/* Don't lock. */
+	KASSERT(mutex_owned(&hp->intr_lock));
 
 	/* Disable all interrupts. */
 	if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
@@ -697,7 +690,6 @@ sdhc_host_reset1(sdmmc_chipset_handle_t 
 #endif
 
 	/* Enable interrupts. */
-	mutex_enter(&hp->intr_mtx);
 	sdhcimask = SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION |
 	    SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY |
 	    SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT |
@@ -716,7 +708,6 @@ sdhc_host_reset1(sdmmc_chipset_handle_t 
 		HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, sdhcimask);
 		HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK);
 	}
-	mutex_exit(&hp->intr_mtx);
 
 out:
 	return error;
@@ -728,9 +719,9 @@ sdhc_host_reset(sdmmc_chipset_handle_t s
 	struct sdhc_host *hp = (struct sdhc_host *)sch;
 	int error;
 
-	mutex_enter(&hp->host_mtx);
+	mutex_enter(&hp->intr_lock);
 	error = sdhc_host_reset1(sch);
-	mutex_exit(&hp->host_mtx);
+	mutex_exit(&hp->intr_lock);
 
 	return error;
 }
@@ -763,9 +754,7 @@ sdhc_card_detect(sdmmc_chipset_handle_t 
 	if (hp->sc->sc_vendor_card_detect)
 		return (*hp->sc->sc_vendor_card_detect)(hp->sc);
 
-	mutex_enter(&hp->host_mtx);
 	r = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED);
-	mutex_exit(&hp->host_mtx);
 
 	return r ? 1 : 0;
 }
@@ -782,9 +771,7 @@ sdhc_write_protect(sdmmc_chipset_handle_
 	if (hp->sc->sc_vendor_write_protect)
 		return (*hp->sc->sc_vendor_write_protect)(hp->sc);
 
-	mutex_enter(&hp->host_mtx);
 	r = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_WRITE_PROTECT_SWITCH);
-	mutex_exit(&hp->host_mtx);
 
 	return r ? 0 : 1;
 }
@@ -802,7 +789,7 @@ sdhc_bus_power(sdmmc_chipset_handle_t sc
 	const uint32_t pcmask =
 	    ~(SDHC_BUS_POWER | (SDHC_VOLTAGE_MASK << SDHC_VOLTAGE_SHIFT));
 
-	mutex_enter(&hp->host_mtx);
+	mutex_enter(&hp->intr_lock);
 
 	/*
 	 * Disable bus power before voltage change.
@@ -865,7 +852,7 @@ sdhc_bus_power(sdmmc_chipset_handle_t sc
 	}
 
 out:
-	mutex_exit(&hp->host_mtx);
+	mutex_exit(&hp->intr_lock);
 
 	return error;
 }
@@ -960,12 +947,12 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sc
 	u_int timo;
 	int16_t reg;
 	int error = 0;
-#ifdef DIAGNOSTIC
-	bool present;
+	bool present __diagused;
+
+	mutex_enter(&hp->intr_lock);
 
-	mutex_enter(&hp->host_mtx);
+#ifdef DIAGNOSTIC
 	present = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK);
-	mutex_exit(&hp->host_mtx);
 
 	/* Must not stop the clock if commands are in progress. */
 	if (present && sdhc_card_detect(hp)) {
@@ -974,8 +961,6 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sc
 	}
 #endif
 
-	mutex_enter(&hp->host_mtx);
-
 	if (hp->sc->sc_vendor_bus_clock) {
 		error = (*hp->sc->sc_vendor_bus_clock)(hp->sc, freq);
 		if (error != 0)
@@ -1069,7 +1054,7 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sc
 	}
 
 out:
-	mutex_exit(&hp->host_mtx);
+	mutex_exit(&hp->intr_lock);
 
 	return error;
 }
@@ -1095,7 +1080,8 @@ sdhc_bus_width(sdmmc_chipset_handle_t sc
 		return 1;
 	}
 
-	mutex_enter(&hp->host_mtx);
+	mutex_enter(&hp->intr_lock);
+
 	reg = HREAD1(hp, SDHC_HOST_CTL);
 	if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
 		reg &= ~(SDHC_4BIT_MODE|SDHC_ESDHC_8BIT_MODE);
@@ -1115,7 +1101,8 @@ sdhc_bus_width(sdmmc_chipset_handle_t sc
 		}
 	}
 	HWRITE1(hp, SDHC_HOST_CTL, reg);
-	mutex_exit(&hp->host_mtx);
+
+	mutex_exit(&hp->intr_lock);
 
 	return 0;
 }
@@ -1137,7 +1124,7 @@ sdhc_card_enable_intr(sdmmc_chipset_hand
 	struct sdhc_host *hp = (struct sdhc_host *)sch;
 
 	if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
-		mutex_enter(&hp->intr_mtx);
+		mutex_enter(&hp->intr_lock);
 		if (enable) {
 			HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
 			HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
@@ -1145,7 +1132,7 @@ sdhc_card_enable_intr(sdmmc_chipset_hand
 			HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
 			HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
 		}
-		mutex_exit(&hp->intr_mtx);
+		mutex_exit(&hp->intr_lock);
 	}
 }
 
@@ -1155,9 +1142,9 @@ sdhc_card_intr_ack(sdmmc_chipset_handle_
 	struct sdhc_host *hp = (struct sdhc_host *)sch;
 
 	if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
-		mutex_enter(&hp->intr_mtx);
+		mutex_enter(&hp->intr_lock);
 		HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
-		mutex_exit(&hp->intr_mtx);
+		mutex_exit(&hp->intr_lock);
 	}
 }
 
@@ -1167,10 +1154,10 @@ sdhc_wait_state(struct sdhc_host *hp, ui
 	uint32_t state;
 	int timeout;
 
-	for (timeout = 10; timeout > 0; timeout--) {
+	for (timeout = 10000; timeout > 0; timeout--) {
 		if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask) == value)
 			return 0;
-		sdmmc_delay(10000);
+		sdmmc_delay(10);
 	}
 	DPRINTF(0,("%s: timeout waiting for %x (state=%x)\n", HDEVNAME(hp),
 	    value, state));
@@ -1183,9 +1170,10 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 	struct sdhc_host *hp = (struct sdhc_host *)sch;
 	int error;
 
+	mutex_enter(&hp->intr_lock);
+
 	if (cmd->c_data && ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
 		const uint16_t ready = SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY;
-		mutex_enter(&hp->intr_mtx);
 		if (ISSET(hp->flags, SHF_USE_DMA)) {
 			HCLR2(hp, SDHC_NINTR_SIGNAL_EN, ready);
 			HCLR2(hp, SDHC_NINTR_STATUS_EN, ready);
@@ -1193,7 +1181,6 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 			HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready);
 			HSET2(hp, SDHC_NINTR_STATUS_EN, ready);
 		}
-		mutex_exit(&hp->intr_mtx);
 	}
 
 	if (ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_TIMEOUT)) {
@@ -1230,7 +1217,6 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 	 * data (CRC) and we pass the data up unchanged to the bus
 	 * driver (without padding).
 	 */
-	mutex_enter(&hp->host_mtx);
 	if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
 		cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE + 0);
 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
@@ -1248,7 +1234,6 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 			}
 		}
 	}
-	mutex_exit(&hp->host_mtx);
 	DPRINTF(1,("%s: resp = %08x\n", HDEVNAME(hp), cmd->c_resp[0]));
 
 	/*
@@ -1267,13 +1252,13 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 out:
 	if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)
 	    && !ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_LED_ON)) {
-		mutex_enter(&hp->host_mtx);
 		/* Turn off the LED. */
 		HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
-		mutex_exit(&hp->host_mtx);
 	}
 	SET(cmd->c_flags, SCF_ITSDONE);
 
+	mutex_exit(&hp->intr_lock);
+
 	DPRINTF(1,("%s: cmd %d %s (flags=%08x error=%d)\n", HDEVNAME(hp),
 	    cmd->c_opcode, (cmd->c_error == 0) ? "done" : "abort",
 	    cmd->c_flags, cmd->c_error));
@@ -1289,6 +1274,8 @@ sdhc_start_command(struct sdhc_host *hp,
 	uint16_t command;
 	int error;
 
+	KASSERT(mutex_owned(&hp->intr_lock));
+
 	DPRINTF(1,("%s: start cmd %d arg=%08x data=%p dlen=%d flags=%08x, status=%#x\n",
 	    HDEVNAME(hp), cmd->c_opcode, cmd->c_arg, cmd->c_data,
 	    cmd->c_datalen, cmd->c_flags, HREAD4(hp, SDHC_NINTR_STATUS)));
@@ -1364,8 +1351,6 @@ sdhc_start_command(struct sdhc_host *hp,
 		    SDHC_DMA_BOUNDARY_SHIFT;	/* PAGE_SIZE DMA boundary */
 	}
 
-	mutex_enter(&hp->host_mtx);
-
 	if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
 		/* Alert the user not to remove the card. */
 		HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
@@ -1440,8 +1425,6 @@ sdhc_start_command(struct sdhc_host *hp,
 		HWRITE2(hp, SDHC_COMMAND, command);
 	}
 
-	mutex_exit(&hp->host_mtx);
-
 	return 0;
 }
 
@@ -1451,6 +1434,8 @@ sdhc_transfer_data(struct sdhc_host *hp,
 	struct sdhc_softc *sc = hp->sc;
 	int error;
 
+	KASSERT(mutex_owned(&hp->intr_lock));
+
 	DPRINTF(1,("%s: data transfer: resp=%08x datalen=%u\n", HDEVNAME(hp),
 	    MMC_R1(cmd->c_resp), cmd->c_datalen));
 
@@ -1495,6 +1480,7 @@ sdhc_transfer_data_dma(struct sdhc_host 
 	int error = 0;
 	int status;
 
+	KASSERT(mutex_owned(&hp->intr_lock));
 	KASSERT(HREAD2(hp, SDHC_NINTR_STATUS_EN) & SDHC_DMA_INTERRUPT);
 	KASSERT(HREAD2(hp, SDHC_NINTR_SIGNAL_EN) & SDHC_DMA_INTERRUPT);
 	KASSERT(HREAD2(hp, SDHC_NINTR_STATUS_EN) & SDHC_TRANSFER_COMPLETE);
@@ -1525,19 +1511,15 @@ sdhc_transfer_data_dma(struct sdhc_host 
 
 		segaddr = dm_segs[seg].ds_addr;
 		seglen = dm_segs[seg].ds_len;
-		mutex_enter(&hp->host_mtx);
 		posaddr = HREAD4(hp, SDHC_DMA_ADDR);
-		mutex_exit(&hp->host_mtx);
 
 		if ((seg == (cmd->c_dmamap->dm_nsegs-1)) && (posaddr == (segaddr + seglen))) {
 			continue;
 		}
-		mutex_enter(&hp->host_mtx);
 		if ((posaddr >= segaddr) && (posaddr < (segaddr + seglen)))
 			HWRITE4(hp, SDHC_DMA_ADDR, posaddr);
 		else if ((posaddr >= segaddr) && (posaddr == (segaddr + seglen)) && (seg + 1) < cmd->c_dmamap->dm_nsegs)
 			HWRITE4(hp, SDHC_DMA_ADDR, dm_segs[++seg].ds_addr);
-		mutex_exit(&hp->host_mtx);
 		KASSERT(seg < cmd->c_dmamap->dm_nsegs);
 	}
 
@@ -1578,19 +1560,18 @@ sdhc_transfer_data_pio(struct sdhc_host 
 	}
 	datalen = cmd->c_datalen;
 
+	KASSERT(mutex_owned(&hp->intr_lock));
 	KASSERT(HREAD2(hp, SDHC_NINTR_STATUS_EN) & imask);
 	KASSERT(HREAD2(hp, SDHC_NINTR_STATUS_EN) & SDHC_TRANSFER_COMPLETE);
 	KASSERT(HREAD2(hp, SDHC_NINTR_SIGNAL_EN) & SDHC_TRANSFER_COMPLETE);
 
 	while (datalen > 0) {
 		if (!ISSET(HREAD4(hp, SDHC_PRESENT_STATE), imask)) {
-			mutex_enter(&hp->intr_mtx);
 			if (ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
 				HSET4(hp, SDHC_NINTR_SIGNAL_EN, imask);
 			} else {
 				HSET2(hp, SDHC_NINTR_SIGNAL_EN, imask);
 			}
-			mutex_exit(&hp->intr_mtx);
 			if (!sdhc_wait_intr(hp, imask, SDHC_BUFFER_TIMEOUT)) {
 				error = ETIMEDOUT;
 				break;
@@ -1822,12 +1803,13 @@ sdhc_wait_intr(struct sdhc_host *hp, int
 {
 	int status;
 
+	KASSERT(mutex_owned(&hp->intr_lock));
+
 	mask |= SDHC_ERROR_INTERRUPT;
 
-	mutex_enter(&hp->intr_mtx);
 	status = hp->intr_status & mask;
 	while (status == 0) {
-		if (cv_timedwait(&hp->intr_cv, &hp->intr_mtx, timo)
+		if (cv_timedwait(&hp->intr_cv, &hp->intr_lock, timo)
 		    == EWOULDBLOCK) {
 			status |= SDHC_ERROR_INTERRUPT;
 			break;
@@ -1848,7 +1830,6 @@ sdhc_wait_intr(struct sdhc_host *hp, int
 		}
 		status = 0;
 	}
-	mutex_exit(&hp->intr_mtx);
 
 	return status;
 }
@@ -1871,6 +1852,8 @@ sdhc_intr(void *arg)
 		if (hp == NULL)
 			continue;
 
+		mutex_enter(&hp->intr_lock);
+
 		if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
 			/* Find out which interrupts are pending. */
 			uint32_t xstatus = HREAD4(hp, SDHC_NINTR_STATUS);
@@ -1879,7 +1862,7 @@ sdhc_intr(void *arg)
 			if (error)
 				xstatus |= SDHC_ERROR_INTERRUPT;
 			else if (!ISSET(status, SDHC_NINTR_STATUS_MASK))
-				continue; /* no interrupt for us */
+				goto next_port; /* no interrupt for us */
 			/* Acknowledge the interrupts we are about to handle. */
 			HWRITE4(hp, SDHC_NINTR_STATUS, xstatus);
 		} else {
@@ -1887,7 +1870,7 @@ sdhc_intr(void *arg)
 			error = 0;
 			status = HREAD2(hp, SDHC_NINTR_STATUS);
 			if (!ISSET(status, SDHC_NINTR_STATUS_MASK))
-				continue; /* no interrupt for us */
+				goto next_port; /* no interrupt for us */
 			/* Acknowledge the interrupts we are about to handle. */
 			HWRITE2(hp, SDHC_NINTR_STATUS, status);
 			if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
@@ -1900,8 +1883,6 @@ sdhc_intr(void *arg)
 		DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp),
 		    status, error));
 
-		mutex_enter(&hp->intr_mtx);
-
 		/* Claim this interrupt. */
 		done = 1;
 
@@ -1960,12 +1941,19 @@ sdhc_intr(void *arg)
 			HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
 			sdmmc_card_intr(hp->sdmmc);
 		}
-		mutex_exit(&hp->intr_mtx);
+next_port:
+		mutex_exit(&hp->intr_lock);
 	}
 
 	return done;
 }
 
+kmutex_t *
+sdhc_host_lock(struct sdhc_host *hp)
+{
+	return &hp->intr_lock;
+}
+
 #ifdef SDHC_DEBUG
 void
 sdhc_dump_regs(struct sdhc_host *hp)

Index: src/sys/dev/sdmmc/sdhcvar.h
diff -u src/sys/dev/sdmmc/sdhcvar.h:1.20 src/sys/dev/sdmmc/sdhcvar.h:1.21
--- src/sys/dev/sdmmc/sdhcvar.h:1.20	Wed Jul 29 12:11:14 2015
+++ src/sys/dev/sdmmc/sdhcvar.h	Fri Jul 31 15:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdhcvar.h,v 1.20 2015/07/29 12:11:14 jmcneill Exp $	*/
+/*	$NetBSD: sdhcvar.h,v 1.21 2015/07/31 15:00:08 jmcneill Exp $	*/
 /*	$OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $	*/
 
 /*
@@ -76,5 +76,6 @@ int	sdhc_detach(struct sdhc_softc *, int
 bool	sdhc_suspend(device_t, const pmf_qual_t *);
 bool	sdhc_resume(device_t, const pmf_qual_t *);
 bool	sdhc_shutdown(device_t, int);
+kmutex_t *sdhc_host_lock(struct sdhc_host *);
 
 #endif	/* _SDHCVAR_H_ */

Reply via email to