summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2006-08-25 04:17:01 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2006-08-25 04:17:01 +0000
commitdc690fffa8e3b038b2f31332c707a52b4a6c0ff2 (patch)
treef7dafffd86bca894ee87a0a474d331736c6a9c71
parent7015f1479013359c596499dc2e4849f959c94597 (diff)
Disable interrupts during the attach of UHCI and EHCI controllers. If
we do not, a shared interrupt which arrives while we are initialising the host controller may cause a NULL pointer dereference. tested joris, ok! dlg
-rw-r--r--sys/dev/pci/ehci_pci.c23
-rw-r--r--sys/dev/pci/uhci_pci.c21
2 files changed, 28 insertions, 16 deletions
diff --git a/sys/dev/pci/ehci_pci.c b/sys/dev/pci/ehci_pci.c
index 0a79fabe46a..59665d44113 100644
--- a/sys/dev/pci/ehci_pci.c
+++ b/sys/dev/pci/ehci_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci_pci.c,v 1.9 2006/07/10 07:54:43 dlg Exp $ */
+/* $OpenBSD: ehci_pci.c,v 1.10 2006/08/25 04:17:00 pascoe Exp $ */
/* $NetBSD: ehci_pci.c,v 1.15 2004/04/23 21:13:06 itojun Exp $ */
/*
@@ -109,6 +109,7 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
const char *vendor;
char *devname = sc->sc.sc_bus.bdev.dv_xname;
usbd_status r;
+ int s;
/* Map I/O registers */
if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
@@ -122,6 +123,7 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
sc->sc.sc_bus.dmatag = pa->pa_dmat;
/* Disable interrupts, so we don't get any spurious ones. */
+ s = splhardusb();
sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
DPRINTF(("%s: offs=%d\n", devname, sc->sc.sc_offs));
EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
@@ -129,8 +131,7 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
/* Map and establish the interrupt. */
if (pci_intr_map(pa, &ih)) {
printf(": couldn't map interrupt\n");
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
intrstr = pci_intr_string(pc, ih);
sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ehci_intr, sc, devname);
@@ -139,8 +140,7 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
if (intrstr != NULL)
printf(" at %s", intrstr);
printf("\n");
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
printf(": %s\n", intrstr);
@@ -150,8 +150,7 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
case PCI_USBREV_1_1:
sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
printf("%s: pre-2.0 USB rev\n", devname);
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
case PCI_USBREV_2_0:
sc->sc.sc_bus.usbrev = USBREV_2_0;
break;
@@ -177,15 +176,21 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux)
r = ehci_init(&sc->sc);
if (r != USBD_NORMAL_COMPLETION) {
printf("%s: init failed, error=%d\n", devname, r);
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
sc->sc.sc_shutdownhook = shutdownhook_establish(ehci_pci_shutdown, sc);
+ splx(s);
/* Attach usb device. */
sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
usbctlprint);
+
+ return;
+
+unmap_ret:
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ splx(s);
}
int
diff --git a/sys/dev/pci/uhci_pci.c b/sys/dev/pci/uhci_pci.c
index fb7f706cda8..2d03e1ab30a 100644
--- a/sys/dev/pci/uhci_pci.c
+++ b/sys/dev/pci/uhci_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci_pci.c,v 1.21 2005/12/30 03:43:04 dlg Exp $ */
+/* $OpenBSD: uhci_pci.c,v 1.22 2006/08/25 04:17:00 pascoe Exp $ */
/* $NetBSD: uhci_pci.c,v 1.24 2002/10/02 16:51:58 thorpej Exp $ */
/*
@@ -98,6 +98,7 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
const char *vendor;
char *devname = sc->sc.sc_bus.bdev.dv_xname;
usbd_status r;
+ int s;
#if defined(__NetBSD__)
char devinfo[256];
@@ -113,7 +114,9 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
return;
}
+
/* Disable interrupts, so we don't get any spurious ones. */
+ s = splhardusb();
bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);
sc->sc_pc = pc;
@@ -123,8 +126,7 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
/* Map and establish the interrupt. */
if (pci_intr_map(pa, &ih)) {
printf(": couldn't map interrupt\n");
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
intrstr = pci_intr_string(pc, ih);
sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, uhci_intr, sc,
@@ -134,8 +136,7 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
if (intrstr != NULL)
printf(" at %s", intrstr);
printf("\n");
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
printf(": %s\n", intrstr);
@@ -175,13 +176,19 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
r = uhci_init(&sc->sc);
if (r != USBD_NORMAL_COMPLETION) {
printf("%s: init failed, error=%d\n", devname, r);
- bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
- return;
+ goto unmap_ret;
}
+ splx(s);
/* Attach usb device. */
sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
usbctlprint);
+
+ return;
+
+unmap_ret:
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ splx(s);
}
int