summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2006-07-17 20:48:28 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2006-07-17 20:48:28 +0000
commitfb8fa2baab9637eec71161e51d7bf82081e540ce (patch)
tree45c1a4dda0da1def14d4a5e8e39896080e7689f3
parent34afc6ce380fc7428a969ce3c7ddb53409fb122e (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.c13
-rw-r--r--sys/dev/sdmmc/sdhc.c26
-rw-r--r--sys/dev/sdmmc/sdhcvar.h4
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;
};