diff options
Diffstat (limited to 'sys/pci/if_dc.c')
-rw-r--r-- | sys/pci/if_dc.c | 65 |
1 files changed, 32 insertions, 33 deletions
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index ca72682..61672ef 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -1905,7 +1905,6 @@ dc_attach(dev) sc = device_get_softc(dev); unit = device_get_unit(dev); - bzero(sc, sizeof(struct dc_softc)); mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); @@ -1950,6 +1949,17 @@ dc_attach(dev) sc->dc_btag = rman_get_bustag(sc->dc_res); sc->dc_bhandle = rman_get_bushandle(sc->dc_res); + /* Allocate interrupt */ + rid = 0; + sc->dc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->dc_irq == NULL) { + printf("dc%d: couldn't map interrupt\n", unit); + error = ENXIO; + goto fail; + } + /* Need this info to decide on a chip type. */ sc->dc_info = dc_devtype(dev); revision = pci_read_config(dev, DC_PCI_CFRV, 4) & 0x000000FF; @@ -2141,7 +2151,6 @@ dc_attach(dev) mac = pci_get_ether(dev); if (!mac) { device_printf(dev, "No station address in CIS!\n"); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); error = ENXIO; goto fail; } @@ -2165,7 +2174,6 @@ dc_attach(dev) if (sc->dc_ldata == NULL) { printf("dc%d: no memory for list buffers!\n", unit); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); error = ENXIO; goto fail; } @@ -2224,8 +2232,6 @@ dc_attach(dev) if (error) { printf("dc%d: MII without any PHY!\n", sc->dc_unit); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - error = ENXIO; goto fail; } @@ -2288,31 +2294,19 @@ dc_attach(dev) */ ether_ifattach(ifp, eaddr); - /* Allocate interrupt */ - rid = 0; - sc->dc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - - if (sc->dc_irq == NULL) { - printf("dc%d: couldn't map interrupt\n", unit); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - error = ENXIO; - goto fail; - } - + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | (IS_MPSAFE ? INTR_MPSAFE : 0), dc_intr, sc, &sc->dc_intrhand); if (error) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); printf("dc%d: couldn't set up irq\n", unit); + goto fail; } fail: - if (error != 0) - mtx_destroy(&sc->dc_mtx); + if (error) + dc_detach(dev); return (error); } @@ -2325,24 +2319,29 @@ dc_detach(dev) struct dc_mediainfo *m; sc = device_get_softc(dev); - + KASSERT(mtx_initialized(&sc->dc_mtx), "dc mutex not initialized"); DC_LOCK(sc); ifp = &sc->arpcom.ac_if; - dc_stop(sc); - ether_ifdetach(ifp); - - bus_generic_detach(dev); - device_delete_child(dev, sc->dc_miibus); + if (device_is_alive(dev)) { + if (bus_child_present(dev)) + dc_stop(sc); + ether_ifdetach(ifp); + device_delete_child(dev, sc->dc_miibus); + bus_generic_detach(dev); + } - bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); + if (sc->dc_intrhand) + bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); + if (sc->dc_irq) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); + if (sc->dc_res) + bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - contigfree(sc->dc_ldata, sizeof(struct dc_list_data), M_DEVBUF); - if (sc->dc_pnic_rx_buf != NULL) - free(sc->dc_pnic_rx_buf, M_DEVBUF); + if (sc->dc_ldata) + contigfree(sc->dc_ldata, sizeof(struct dc_list_data), M_DEVBUF); + free(sc->dc_pnic_rx_buf, M_DEVBUF); while(sc->dc_mi != NULL) { m = sc->dc_mi->dc_next; |