summaryrefslogtreecommitdiffstats
path: root/sys/pci/uhci_pci.c
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2000-01-20 21:36:07 +0000
committern_hibma <n_hibma@FreeBSD.org>2000-01-20 21:36:07 +0000
commit1b6a1333f623c984732a9786060d08f5d3119555 (patch)
treed9c21883c899afdcec941d447bc1be76249c9d41 /sys/pci/uhci_pci.c
parent7bb98afc93dc9e188e57008966c7ff4419972d02 (diff)
downloadFreeBSD-src-1b6a1333f623c984732a9786060d08f5d3119555.zip
FreeBSD-src-1b6a1333f623c984732a9786060d08f5d3119555.tar.gz
Properly remove interrupts if initialisation fails.
Diffstat (limited to 'sys/pci/uhci_pci.c')
-rw-r--r--sys/pci/uhci_pci.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/sys/pci/uhci_pci.c b/sys/pci/uhci_pci.c
index 0857f16..c05d48b 100644
--- a/sys/pci/uhci_pci.c
+++ b/sys/pci/uhci_pci.c
@@ -154,7 +154,6 @@ uhci_pci_attach(device_t self)
int rid;
void *ih;
struct resource *res;
- device_t usbus;
int intr;
int legsup;
int err;
@@ -178,33 +177,35 @@ uhci_pci_attach(device_t self)
RF_SHAREABLE | RF_ACTIVE);
if (res == NULL) {
device_printf(self, "could not allocate irq\n");
- return ENOMEM;
+ err = ENOMEM;
+ goto bad1;
}
- usbus = device_add_child(self, "usb", -1);
- device_set_ivars(usbus, sc);
- if (!usbus) {
+ sc->sc_bus.bdev = device_add_child(self, "usb", -1);
+ device_set_ivars(sc->sc_bus.bdev, sc);
+ if (!sc->sc_bus.bdev) {
device_printf(self, "could not add USB device\n");
- return ENOMEM;
+ err = ENOMEM;
+ goto bad2;
}
switch (pci_get_devid(self)) {
case PCI_UHCI_DEVICEID_PIIX3:
- device_set_desc(usbus, uhci_device_piix3);
+ device_set_desc(sc->sc_bus.bdev, uhci_device_piix3);
sprintf(sc->sc_vendor, "Intel");
break;
case PCI_UHCI_DEVICEID_PIIX4:
- device_set_desc(usbus, uhci_device_piix4);
+ device_set_desc(sc->sc_bus.bdev, uhci_device_piix4);
sprintf(sc->sc_vendor, "Intel");
break;
case PCI_UHCI_DEVICEID_VT83C572:
- device_set_desc(usbus, uhci_device_vt83c572);
+ device_set_desc(sc->sc_bus.bdev, uhci_device_vt83c572);
sprintf(sc->sc_vendor, "VIA");
break;
default:
device_printf(self, "(New UHCI DeviceId=0x%08x)\n",
pci_get_devid(self));
- device_set_desc(usbus, uhci_device_generic);
+ device_set_desc(sc->sc_bus.bdev, uhci_device_generic);
sprintf(sc->sc_vendor, "(0x%08x)", pci_get_devid(self));
}
@@ -224,16 +225,15 @@ uhci_pci_attach(device_t self)
if (intr == 0 || intr == 255) {
device_printf(self, "Invalid irq %d\n", intr);
device_printf(self, "Please switch on USB support and switch PNP-OS to 'No' in BIOS\n");
- device_delete_child(self, usbus);
- return ENXIO;
+ err = ENXIO;
+ goto bad3;
}
err = BUS_SETUP_INTR(parent, self, res, INTR_TYPE_BIO,
(driver_intr_t *) uhci_intr, sc, &ih);
if (err) {
device_printf(self, "could not setup irq, %d\n", err);
- device_delete_child(self, usbus);
- return err;
+ goto bad3;
}
/* Verify that the PIRQD enable bit is set, some BIOS's don't do that */
@@ -247,31 +247,39 @@ uhci_pci_attach(device_t self)
pci_write_config(self, PCI_LEGSUP, legsup, 4);
}
- sc->sc_bus.bdev = usbus;
err = uhci_init(sc);
-
if (!err)
err = device_probe_and_attach(sc->sc_bus.bdev);
if (err) {
device_printf(self, "init failed\n");
+ err = EIO; /* XXX arbitrary value */
+ goto bad4;
+ }
- /* disable interrupts that might have been switched on
- * in uhci_init
- */
- bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
+ return 0;
- err = BUS_TEARDOWN_INTR(parent, self, res, ih);
- if (err)
- /* XXX or should we panic? */
- device_printf(self, "could not tear down irq, %d\n",
- err);
+bad4:
+ /* disable interrupts that might have been switched on
+ * in uhci_init
+ */
+ bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
- device_delete_child(self, usbus);
- return EIO; /* XXX arbitrary value */
- }
+ err = BUS_TEARDOWN_INTR(parent, self, res, ih);
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "could not tear down irq, %d\n",
+ err);
- return 0;
+bad3:
+ device_delete_child(self, sc->sc_bus.bdev);
+bad2:
+ rid = 0;
+ bus_delete_resource(self, SYS_RES_IRQ, rid);
+bad1:
+ rid = PCI_UHCI_BASE_REG;
+ bus_delete_resource(self, SYS_RES_IOPORT, rid);
+ return err;
}
static device_method_t uhci_methods[] = {
OpenPOWER on IntegriCloud