diff options
author | Jasper Lievisse Adriaanse <jasper@cvs.openbsd.org> | 2009-11-11 21:59:17 +0000 |
---|---|---|
committer | Jasper Lievisse Adriaanse <jasper@cvs.openbsd.org> | 2009-11-11 21:59:17 +0000 |
commit | 4619c02898d091e55da2103807f0e9263ea54271 (patch) | |
tree | 79815a68b71ef5ba4332961e4ac08883d21db9cb | |
parent | 6b584759798e88e98b87ef87ba4fc1f7740695d8 (diff) |
fixup of locking issues with sdmmc, which were causing
"locking against myself" panics as found the hard way by
several. diff by blamert@ with input from oga@,
committing bret's behalf.
ok todd@
-rw-r--r-- | sys/dev/sdmmc/sbt.c | 10 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdmmc_cis.c | 8 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdmmc_io.c | 33 |
3 files changed, 43 insertions, 8 deletions
diff --git a/sys/dev/sdmmc/sbt.c b/sys/dev/sdmmc/sbt.c index 0acd4b716cc..4c40f70b68c 100644 --- a/sys/dev/sdmmc/sbt.c +++ b/sys/dev/sdmmc/sbt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sbt.c,v 1.12 2008/11/01 09:24:35 tedu Exp $ */ +/* $OpenBSD: sbt.c,v 1.13 2009/11/11 21:59:16 jasper Exp $ */ /* * Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org> @@ -162,6 +162,8 @@ sbt_attach(struct device *parent, struct device *self, void *aux) struct sbt_softc *sc = (struct sbt_softc *)self; struct sdmmc_attach_args *sa = aux; + SDMMC_ASSERT_LOCKED(sc->sc_sf->sc); + printf("\n"); sc->sc_sf = sa->sf; @@ -308,6 +310,7 @@ sbt_read_packet(struct sbt_softc *sc, u_char *buf, size_t *lenp) } out: + SDMMC_LOCK(sc->sc_sf->sc); if (error) { if (sc->sc_rxtry >= SBT_RXTRY_MAX) { /* Drop and request the next packet. */ @@ -318,12 +321,15 @@ out: sc->sc_rxtry++; CSR_WRITE_1(sc, SBT_REG_RPC, RPC_PCRRT); } + SDMMC_UNLOCK(sc->sc_sf->sc); return error; } /* acknowledge read packet */ CSR_WRITE_1(sc, SBT_REG_RPC, 0); + SDMMC_UNLOCK(sc->sc_sf->sc); + *lenp = len; return 0; } @@ -345,8 +351,10 @@ sbt_intr(void *arg) /* Block further SDIO interrupts; XXX not really needed? */ s = splsdmmc(); + SDMMC_LOCK(sc->sc_sf->sc); status = CSR_READ_1(sc, SBT_REG_ISTAT); CSR_WRITE_1(sc, SBT_REG_ICLR, status); + SDMMC_UNLOCK(sc->sc_sf->sc); if ((status & ISTAT_INTRD) == 0) return 0; /* shared SDIO card interrupt? */ diff --git a/sys/dev/sdmmc/sdmmc_cis.c b/sys/dev/sdmmc/sdmmc_cis.c index 16a6890a8c7..1b4f5584ce4 100644 --- a/sys/dev/sdmmc/sdmmc_cis.c +++ b/sys/dev/sdmmc/sdmmc_cis.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdmmc_cis.c,v 1.2 2009/10/03 18:42:36 kettenis Exp $ */ +/* $OpenBSD: sdmmc_cis.c,v 1.3 2009/11/11 21:59:16 jasper Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -39,6 +39,8 @@ sdmmc_cisptr(struct sdmmc_function *sf) { u_int32_t cisptr = 0; + SDMMC_ASSERT_LOCKED(sf->sc); + /* XXX where is the per-function CIS pointer register? */ if (sf->number != 0) return SD_IO_CIS_START; @@ -47,6 +49,7 @@ sdmmc_cisptr(struct sdmmc_function *sf) cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+0) << 0; cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+1) << 8; cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+2) << 16; + return cisptr; } @@ -57,6 +60,8 @@ sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis *cis) u_int8_t tplcode; u_int8_t tpllen; + SDMMC_ASSERT_LOCKED(sf->sc); + bzero(cis, sizeof *cis); /* XXX read per-function CIS */ @@ -142,6 +147,7 @@ sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis *cis) break; } } + return 0; } diff --git a/sys/dev/sdmmc/sdmmc_io.c b/sys/dev/sdmmc/sdmmc_io.c index 33ff18a1983..069dc23d24a 100644 --- a/sys/dev/sdmmc/sdmmc_io.c +++ b/sys/dev/sdmmc/sdmmc_io.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdmmc_io.c,v 1.16 2009/10/03 18:42:36 kettenis Exp $ */ +/* $OpenBSD: sdmmc_io.c,v 1.17 2009/11/11 21:59:16 jasper Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -201,10 +201,13 @@ sdmmc_io_function_ready(struct sdmmc_function *sf) struct sdmmc_function *sf0 = sc->sc_fn0; u_int8_t rv; + SDMMC_ASSERT_LOCKED(sc); + if (sf->number == 0) return 1; /* FN0 is always ready */ rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_READY); + return (rv & (1 << sf->number)) != 0; } @@ -245,14 +248,14 @@ sdmmc_io_function_disable(struct sdmmc_function *sf) struct sdmmc_function *sf0 = sc->sc_fn0; u_int8_t rv; + SDMMC_ASSERT_LOCKED(sc); + if (sf->number == 0) return; /* FN0 is always enabled */ - SDMMC_LOCK(sc); rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE); rv &= ~(1<<sf->number); sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv); - SDMMC_UNLOCK(sc); } void @@ -353,7 +356,7 @@ sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf, struct sdmmc_command cmd; int error; - SDMMC_LOCK(sc); + SDMMC_ASSERT_LOCKED(sc); /* Make sure the card is selected. */ if ((error = sdmmc_select_card(sc, sf)) != 0) { @@ -376,7 +379,6 @@ sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf, error = sdmmc_mmc_command(sc, &cmd); *datap = SD_R5_DATA(cmd.c_resp); - SDMMC_UNLOCK(sc); return error; } @@ -393,7 +395,7 @@ sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf, struct sdmmc_command cmd; int error; - SDMMC_LOCK(sc); + SDMMC_ASSERT_LOCKED(sc); #if 0 /* Make sure the card is selected. */ @@ -430,6 +432,8 @@ u_int8_t sdmmc_io_read_1(struct sdmmc_function *sf, int reg) { u_int8_t data = 0; + + SDMMC_ASSERT_LOCKED(sf->sc); (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data, SD_ARG_CMD52_READ); @@ -439,6 +443,8 @@ sdmmc_io_read_1(struct sdmmc_function *sf, int reg) void sdmmc_io_write_1(struct sdmmc_function *sf, int reg, u_int8_t data) { + SDMMC_ASSERT_LOCKED(sf->sc); + (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data, SD_ARG_CMD52_WRITE); } @@ -448,6 +454,8 @@ sdmmc_io_read_2(struct sdmmc_function *sf, int reg) { u_int16_t data = 0; + SDMMC_ASSERT_LOCKED(sf->sc); + (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT); return data; @@ -456,6 +464,8 @@ sdmmc_io_read_2(struct sdmmc_function *sf, int reg) void sdmmc_io_write_2(struct sdmmc_function *sf, int reg, u_int16_t data) { + SDMMC_ASSERT_LOCKED(sf->sc); + (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT); } @@ -465,6 +475,8 @@ sdmmc_io_read_4(struct sdmmc_function *sf, int reg) { u_int32_t data = 0; + SDMMC_ASSERT_LOCKED(sf->sc); + (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT); return data; @@ -473,6 +485,8 @@ sdmmc_io_read_4(struct sdmmc_function *sf, int reg) void sdmmc_io_write_4(struct sdmmc_function *sf, int reg, u_int32_t data) { + SDMMC_ASSERT_LOCKED(sf->sc); + (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT); } @@ -483,6 +497,8 @@ sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data, { int error; + SDMMC_ASSERT_LOCKED(sf->sc); + while (datalen > SD_ARG_CMD53_LENGTH_MAX) { error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ); @@ -502,6 +518,8 @@ sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data, { int error; + SDMMC_ASSERT_LOCKED(sf->sc); + while (datalen > SD_ARG_CMD53_LENGTH_MAX) { error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE); @@ -519,6 +537,9 @@ int sdmmc_io_xchg(struct sdmmc_softc *sc, struct sdmmc_function *sf, int reg, u_char *datap) { + + SDMMC_ASSERT_LOCKED(sc); + return sdmmc_io_rw_direct(sc, sf, reg, datap, SD_ARG_CMD52_WRITE|SD_ARG_CMD52_EXCHANGE); } |