diff options
Diffstat (limited to 'sys/pci/if_sf.c')
-rw-r--r-- | sys/pci/if_sf.c | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/sys/pci/if_sf.c b/sys/pci/if_sf.c index a148ba575862..288ca7e95c50 100644 --- a/sys/pci/if_sf.c +++ b/sys/pci/if_sf.c @@ -681,11 +681,10 @@ sf_attach(dev) sc = device_get_softc(dev); unit = device_get_unit(dev); - bzero(sc, sizeof(struct sf_softc)); mtx_init(&sc->sf_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); - SF_LOCK(sc); + /* * Handle power management nonsense. */ @@ -751,21 +750,10 @@ sf_attach(dev) if (sc->sf_irq == NULL) { printf("sf%d: couldn't map interrupt\n", unit); - bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); error = ENXIO; goto fail; } - error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET, - sf_intr, sc, &sc->sf_intrhand); - - if (error) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_res); - bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); - printf("sf%d: couldn't set up irq\n", unit); - goto fail; - } - callout_handle_init(&sc->sf_stat_ch); /* Reset the adapter. */ sf_reset(sc); @@ -791,9 +779,6 @@ sf_attach(dev) if (sc->sf_ldata == NULL) { printf("sf%d: no memory for list buffers!\n", unit); - bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq); - bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); error = ENXIO; goto fail; } @@ -804,10 +789,6 @@ sf_attach(dev) if (mii_phy_probe(dev, &sc->sf_miibus, sf_ifmedia_upd, sf_ifmedia_sts)) { printf("sf%d: MII without any phy!\n", sc->sf_unit); - contigfree(sc->sf_ldata,sizeof(struct sf_list_data),M_DEVBUF); - bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq); - bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); error = ENXIO; goto fail; } @@ -830,12 +811,19 @@ sf_attach(dev) * Call MI attach routine. */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); - SF_UNLOCK(sc); - return(0); + + error = bus_setup_intr(dev, sc->sf_irq, INTR_TYPE_NET, + sf_intr, sc, &sc->sf_intrhand); + + if (error) { + printf("sf%d: couldn't set up irq\n", unit); + goto fail; + } fail: - SF_UNLOCK(sc); - mtx_destroy(&sc->sf_mtx); + if (error) + sf_detach(dev); + return(error); } @@ -847,20 +835,27 @@ sf_detach(dev) struct ifnet *ifp; sc = device_get_softc(dev); + KASSERT(mtx_initialized(&sc->sf_mtx), "sf mutex not initialized"); SF_LOCK(sc); ifp = &sc->arpcom.ac_if; - ether_ifdetach(ifp); - sf_stop(sc); - - bus_generic_detach(dev); - device_delete_child(dev, sc->sf_miibus); + if (device_is_alive(dev)) { + if (bus_child_present(dev)) + sf_stop(sc); + ether_ifdetach(ifp); + device_delete_child(dev, sc->sf_miibus); + bus_generic_detach(dev); + } - bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq); - bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); + if (sc->sf_intrhand) + bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); + if (sc->sf_irq) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq); + if (sc->sf_res) + bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); - contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF); + if (sc->sf_ldata) + contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF); SF_UNLOCK(sc); mtx_destroy(&sc->sf_mtx); |