diff --git a/sys/arch/arm/broadcom/bcm2835_emmc.c b/sys/arch/arm/broadcom/bcm2835_emmc.c index 9713e746b9f1..ddb29b35e1cb 100644 --- a/sys/arch/arm/broadcom/bcm2835_emmc.c +++ b/sys/arch/arm/broadcom/bcm2835_emmc.c @@ -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 -__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 self, void *aux) 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 *sdhc_sc, struct sdmmc_command *cmd) 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 *sdhc_sc, struct sdmmc_command *cmd) 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 diff --git a/sys/arch/arm/omap/omap3_sdhc.c b/sys/arch/arm/omap/omap3_sdhc.c index 3aef39aca2a4..76690635a200 100644 --- a/sys/arch/arm/omap/omap3_sdhc.c +++ b/sys/arch/arm/omap/omap3_sdhc.c @@ -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 -__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_t self, void *aux) #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_softc *sdhc_sc, struct sdmmc_command *cmd) 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_softc *sdhc_sc, struct sdmmc_command *cmd) #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_softc *sdhc_sc, struct sdmmc_command *cmd) } } 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 diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c index d85d987025c3..7f6e12b841df 100644 --- a/sys/dev/sdmmc/sdhc.c +++ b/sys/dev/sdmmc/sdhc.c @@ -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 -__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, bus_space_tag_t iot, 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, bus_space_tag_t iot, 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 flags) 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 sch) 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 sch) #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 sch) 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 sch) 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 sch) 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_t sch) 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 sch, uint32_t ocr) 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 sch, uint32_t ocr) } out: - mutex_exit(&hp->host_mtx); + mutex_exit(&hp->intr_lock); return error; } @@ -960,12 +947,12 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq) u_int timo; int16_t reg; int error = 0; -#ifdef DIAGNOSTIC - bool present; + bool present __diagused; - mutex_enter(&hp->host_mtx); + mutex_enter(&hp->intr_lock); + +#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 sch, int freq) } #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 sch, int freq) } out: - mutex_exit(&hp->host_mtx); + mutex_exit(&hp->intr_lock); return error; } @@ -1095,7 +1080,8 @@ sdhc_bus_width(sdmmc_chipset_handle_t sch, int width) 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 sch, int width) } } 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_handle_t sch, int enable) 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_handle_t sch, int enable) 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_t sch) 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, uint32_t mask, uint32_t value) 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 sch, struct sdmmc_command *cmd) 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 sch, struct sdmmc_command *cmd) 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 sch, struct sdmmc_command *cmd) * 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 sch, struct sdmmc_command *cmd) } } } - 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 sch, struct sdmmc_command *cmd) 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, struct sdmmc_command *cmd) 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, struct sdmmc_command *cmd) 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, struct sdmmc_command *cmd) HWRITE2(hp, SDHC_COMMAND, command); } - mutex_exit(&hp->host_mtx); - return 0; } @@ -1451,6 +1434,8 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd) 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 *hp, struct sdmmc_command *cmd) 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 *hp, struct sdmmc_command *cmd) 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 *hp, struct sdmmc_command *cmd) } 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 mask, int timo) { 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 mask, int timo) } 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) diff --git a/sys/dev/sdmmc/sdhcvar.h b/sys/dev/sdmmc/sdhcvar.h index ce7e2842882f..45bba931d1b3 100644 --- a/sys/dev/sdmmc/sdhcvar.h +++ b/sys/dev/sdmmc/sdhcvar.h @@ -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_ */