summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJasper Lievisse Adriaanse <jasper@cvs.openbsd.org>2009-11-11 21:59:17 +0000
committerJasper Lievisse Adriaanse <jasper@cvs.openbsd.org>2009-11-11 21:59:17 +0000
commit4619c02898d091e55da2103807f0e9263ea54271 (patch)
tree79815a68b71ef5ba4332961e4ac08883d21db9cb /sys/dev
parent6b584759798e88e98b87ef87ba4fc1f7740695d8 (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@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sdmmc/sbt.c10
-rw-r--r--sys/dev/sdmmc/sdmmc_cis.c8
-rw-r--r--sys/dev/sdmmc/sdmmc_io.c33
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);
}