Simplify sdhc(4) locking
This commit is contained in:
parent
0c4bdb7434
commit
cd42d5bc1f
|
@ -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 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
|
||||
|
|
|
@ -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_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
|
||||
|
|
|
@ -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, 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)
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue