diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-17 20:48:28 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-17 20:48:28 +0000 |
commit | fb8fa2baab9637eec71161e51d7bf82081e540ce (patch) | |
tree | 45c1a4dda0da1def14d4a5e8e39896080e7689f3 | |
parent | 34afc6ce380fc7428a969ce3c7ddb53409fb122e (diff) |
correct the way hosts are alloc'ed. fixes crashes on controllers with
multiple slots. tested by me and ian@. uwe@ ok.
-rw-r--r-- | sys/dev/pci/sdhc_pci.c | 13 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdhc.c | 26 | ||||
-rw-r--r-- | sys/dev/sdmmc/sdhcvar.h | 4 |
3 files changed, 23 insertions, 20 deletions
diff --git a/sys/dev/pci/sdhc_pci.c b/sys/dev/pci/sdhc_pci.c index d7927da18fc..605b0b436f9 100644 --- a/sys/dev/pci/sdhc_pci.c +++ b/sys/dev/pci/sdhc_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc_pci.c,v 1.2 2006/06/29 01:26:13 uwe Exp $ */ +/* $OpenBSD: sdhc_pci.c,v 1.3 2006/07/17 20:48:26 fgsch Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -19,6 +19,7 @@ #include <sys/param.h> #include <sys/device.h> #include <sys/systm.h> +#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/sdmmc/sdhcreg.h> @@ -94,10 +95,15 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux) */ slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag, SDHC_PCI_CONF_SLOT_INFO); + nslots = SDHC_PCI_NUM_SLOTS(slotinfo); + + /* Allocate an array big enough to hold all the possible hosts */ + MALLOC(sc->sc.sc_host, struct sdhc_host **, + sizeof(struct sdhc_host *) * nslots, M_DEVBUF, M_WAITOK); + /* XXX: handle 64-bit BARs */ for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) * - sizeof(u_int32_t), - nslots = SDHC_PCI_NUM_SLOTS(slotinfo); + sizeof(u_int32_t); reg < SDHC_PCI_BAR_END && nslots > 0; reg += sizeof(u_int32_t), nslots--) { @@ -113,6 +119,7 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux) } if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma) != 0) + /* XXX: sc->sc_host leak */ printf("%s at 0x%x: can't initialize host\n", sc->sc.sc_dev.dv_xname, reg); } diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c index 084dac8b301..4900cc7669e 100644 --- a/sys/dev/sdmmc/sdhc.c +++ b/sys/dev/sdmmc/sdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc.c,v 1.6 2006/07/10 17:58:23 fgsch Exp $ */ +/* $OpenBSD: sdhc.c,v 1.7 2006/07/17 20:48:27 fgsch Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -156,17 +156,11 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot, /* Allocate one more host structure. */ sc->sc_nhosts++; - MALLOC(hp, struct sdhc_host *, sizeof(struct sdhc_host) * - sc->sc_nhosts, M_DEVBUF, M_WAITOK); - if (sc->sc_host != NULL) { - bcopy(sc->sc_host, hp, sizeof(struct sdhc_host) * - (sc->sc_nhosts-1)); - FREE(sc->sc_host, M_DEVBUF); - } - sc->sc_host = hp; + MALLOC(hp, struct sdhc_host *, sizeof(struct sdhc_host), + M_DEVBUF, M_WAITOK); + sc->sc_host[sc->sc_nhosts - 1] = hp; /* Fill in the new host structure. */ - hp = &sc->sc_host[sc->sc_nhosts-1]; bzero(hp, sizeof(struct sdhc_host)); hp->sc = sc; hp->iot = iot; @@ -263,7 +257,9 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot, return 0; err: - /* XXX: Leaking one sdhc_host structure here. */ + timeout_del(&hp->cmd_to); + FREE(hp, M_DEVBUF); + sc->sc_host[sc->sc_nhosts - 1] = NULL; sc->sc_nhosts--; return 1; } @@ -345,7 +341,7 @@ sdhc_power(int why, void *arg) /* Save the host controller state. */ for (n = 0; n < sc->sc_nhosts; n++) { - hp = &sc->sc_host[n]; + hp = sc->sc_host[n]; for (i = 0; i < sizeof hp->regs; i++) hp->regs[i] = HREAD1(hp, i); } @@ -354,7 +350,7 @@ sdhc_power(int why, void *arg) case PWR_RESUME: /* Restore the host controller state. */ for (n = 0; n < sc->sc_nhosts; n++) { - hp = &sc->sc_host[n]; + hp = sc->sc_host[n]; (void)sdhc_host_reset(hp); for (i = 0; i < sizeof hp->regs; i++) HWRITE1(hp, i, hp->regs[i]); @@ -375,7 +371,7 @@ sdhc_shutdown(void *arg) /* XXX chip locks up if we don't disable it before reboot. */ for (i = 0; i < sc->sc_nhosts; i++) { - hp = &sc->sc_host[i]; + hp = sc->sc_host[i]; (void)sdhc_host_reset(hp); } } @@ -964,7 +960,7 @@ sdhc_intr(void *arg) /* We got an interrupt, but we don't know from which slot. */ for (host = 0; host < sc->sc_nhosts; host++) { - struct sdhc_host *hp = &sc->sc_host[host]; + struct sdhc_host *hp = sc->sc_host[host]; u_int16_t status; if (hp == NULL) diff --git a/sys/dev/sdmmc/sdhcvar.h b/sys/dev/sdmmc/sdhcvar.h index c39fb0dd955..f129f2fdb16 100644 --- a/sys/dev/sdmmc/sdhcvar.h +++ b/sys/dev/sdmmc/sdhcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhcvar.h,v 1.1 2006/05/28 17:21:14 uwe Exp $ */ +/* $OpenBSD: sdhcvar.h,v 1.2 2006/07/17 20:48:27 fgsch Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -25,7 +25,7 @@ struct sdhc_host; struct sdhc_softc { struct device sc_dev; - struct sdhc_host *sc_host; + struct sdhc_host **sc_host; int sc_nhosts; }; |