diff options
Diffstat (limited to 'sys/pci/if_wb.c')
-rw-r--r-- | sys/pci/if_wb.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/sys/pci/if_wb.c b/sys/pci/if_wb.c index b540e00..b0ef638 100644 --- a/sys/pci/if_wb.c +++ b/sys/pci/if_wb.c @@ -941,11 +941,13 @@ wb_attach(dev) */ ether_ifattach(ifp, eaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->wb_irq, INTR_TYPE_NET, wb_intr, sc, &sc->wb_intrhand); if (error) { printf("wb%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -956,6 +958,13 @@ fail: return(error); } +/* + * Shutdown hardware and free up resources. This can be called any + * time after the mutex has been initialized. It is called in both + * the error case in attach and the normal detach case so it needs + * to be careful about only freeing resources that have actually been + * allocated. + */ static int wb_detach(dev) device_t dev; @@ -968,14 +977,17 @@ wb_detach(dev) WB_LOCK(sc); ifp = &sc->arpcom.ac_if; - /* Delete any miibus and phy devices attached to this interface */ + /* + * Delete any miibus and phy devices attached to this interface. + * This should only be done if attach succeeded. + */ if (device_is_alive(dev)) { - if (bus_child_present(dev)) - wb_stop(sc); + wb_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->wb_miibus); - bus_generic_detach(dev); } + if (sc->wb_miibus) + device_delete_child(dev, sc->wb_miibus); + bus_generic_detach(dev); if (sc->wb_intrhand) bus_teardown_intr(dev, sc->wb_irq, sc->wb_intrhand); |