summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_vr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_vr.c')
-rw-r--r--sys/pci/if_vr.c63
1 files changed, 28 insertions, 35 deletions
diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c
index 6611da4..b6c1b28 100644
--- a/sys/pci/if_vr.c
+++ b/sys/pci/if_vr.c
@@ -744,11 +744,9 @@ vr_attach(dev)
sc = device_get_softc(dev);
unit = device_get_unit(dev);
- bzero(sc, sizeof(struct vr_softc *));
mtx_init(&sc->vr_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
- VR_LOCK(sc);
/*
* Handle power management nonsense.
@@ -785,12 +783,13 @@ vr_attach(dev)
#ifdef VR_USEIOSPACE
if (!(command & PCIM_CMD_PORTEN)) {
printf("vr%d: failed to enable I/O ports!\n", unit);
- free(sc, M_DEVBUF);
+ error = ENXIO;
goto fail;
}
#else
if (!(command & PCIM_CMD_MEMEN)) {
printf("vr%d: failed to enable memory mapping!\n", unit);
+ error = ENXIO;
goto fail;
}
#endif
@@ -815,21 +814,10 @@ vr_attach(dev)
if (sc->vr_irq == NULL) {
printf("vr%d: couldn't map interrupt\n", unit);
- bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
error = ENXIO;
goto fail;
}
- error = bus_setup_intr(dev, sc->vr_irq, INTR_TYPE_NET,
- vr_intr, sc, &sc->vr_intrhand);
-
- if (error) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq);
- bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
- printf("vr%d: couldn't set up irq\n", unit);
- goto fail;
- }
-
/*
* Windows may put the chip in suspend mode when it
* shuts down. Be sure to kick it in the head to wake it
@@ -873,9 +861,6 @@ vr_attach(dev)
if (sc->vr_ldata == NULL) {
printf("vr%d: no memory for list buffers!\n", unit);
- bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq);
- bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
error = ENXIO;
goto fail;
}
@@ -902,11 +887,6 @@ vr_attach(dev)
if (mii_phy_probe(dev, &sc->vr_miibus,
vr_ifmedia_upd, vr_ifmedia_sts)) {
printf("vr%d: MII without any phy!\n", sc->vr_unit);
- bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq);
- bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
- contigfree(sc->vr_ldata,
- sizeof(struct vr_list_data), M_DEVBUF);
error = ENXIO;
goto fail;
}
@@ -917,12 +897,18 @@ vr_attach(dev)
* Call MI attach routine.
*/
ether_ifattach(ifp, eaddr);
- VR_UNLOCK(sc);
- return(0);
+
+ error = bus_setup_intr(dev, sc->vr_irq, INTR_TYPE_NET,
+ vr_intr, sc, &sc->vr_intrhand);
+
+ if (error) {
+ printf("vr%d: couldn't set up irq\n", unit);
+ goto fail;
+ }
fail:
- VR_UNLOCK(sc);
- mtx_destroy(&sc->vr_mtx);
+ if (error)
+ vr_detach(dev);
return(error);
}
@@ -935,20 +921,27 @@ vr_detach(dev)
struct ifnet *ifp;
sc = device_get_softc(dev);
+ KASSERT(mtx_initialized(&sc->vr_mtx), "vr mutex not initialized");
VR_LOCK(sc);
ifp = &sc->arpcom.ac_if;
- vr_stop(sc);
- ether_ifdetach(ifp);
-
- bus_generic_detach(dev);
- device_delete_child(dev, sc->vr_miibus);
+ if (device_is_alive(dev)) {
+ if (bus_child_present(dev))
+ vr_stop(sc);
+ ether_ifdetach(ifp);
+ device_delete_child(dev, sc->vr_miibus);
+ bus_generic_detach(dev);
+ }
- bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq);
- bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
+ if (sc->vr_intrhand)
+ bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand);
+ if (sc->vr_irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq);
+ if (sc->vr_res)
+ bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res);
- contigfree(sc->vr_ldata, sizeof(struct vr_list_data), M_DEVBUF);
+ if (sc->vr_ldata)
+ contigfree(sc->vr_ldata, sizeof(struct vr_list_data), M_DEVBUF);
VR_UNLOCK(sc);
mtx_destroy(&sc->vr_mtx);
OpenPOWER on IntegriCloud