diff options
author | Nate Lawson <njl@FreeBSD.org> | 2003-04-17 20:32:06 +0000 |
---|---|---|
committer | Nate Lawson <njl@FreeBSD.org> | 2003-04-17 20:32:06 +0000 |
commit | 693f4477b1c27a97e476b242b6db05a08a763925 (patch) | |
tree | 3cf87a7e7fce73f14cb753a6554ec38575d14502 /sys/pci/if_tl.c | |
parent | 59ac15c152afdc761859822ac62f827948ab90a4 (diff) | |
download | src-693f4477b1c27a97e476b242b6db05a08a763925.tar.gz src-693f4477b1c27a97e476b242b6db05a08a763925.zip |
Revise attach/detach resource cleanup
- Unconditionally call *_stop() if device is in the tree. This is to
prevent callouts from happening after the device is gone. Checks for
bus_child_present() should be added in the future to keep from touching
potentially non-existent hardware in *_detach(). Found by iedowse@.
- Always check for and free miibus children, even if the device is not in
the tree since some failure cases could have gotten here.
- Call ether_ifdetach() in the irq setup failure case
- ti(4), xl(4): move ifmedia_init() calls to the beginning of attach so
that ifmedia_removeall() can be unconditionally called on detach. There
is no way to detect whether ifmedia has been initialized without using
a separate variable (as tl(4) does).
- Add comments to indicate assumptions of code path
Notes
Notes:
svn path=/head/; revision=113609
Diffstat (limited to 'sys/pci/if_tl.c')
-rw-r--r-- | sys/pci/if_tl.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/pci/if_tl.c b/sys/pci/if_tl.c index 755d4afe6e6f..ebe64ccf64ea 100644 --- a/sys/pci/if_tl.c +++ b/sys/pci/if_tl.c @@ -1312,11 +1312,13 @@ tl_attach(dev) */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->tl_irq, INTR_TYPE_NET, tl_intr, sc, &sc->tl_intrhand); if (error) { device_printf(dev, "couldn't set up irq\n"); + ether_ifdetach(ifp); goto fail; } @@ -1327,6 +1329,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 tl_detach(dev) device_t dev; @@ -1339,13 +1348,14 @@ tl_detach(dev) TL_LOCK(sc); ifp = &sc->arpcom.ac_if; + /* These should only be active if attach succeeded */ if (device_is_alive(dev)) { - if (bus_child_present(dev)) - tl_stop(sc); + tl_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->tl_miibus); - bus_generic_detach(dev); } + if (sc->tl_miibus) + device_delete_child(dev, sc->tl_miibus); + bus_generic_detach(dev); if (sc->tl_ldata) contigfree(sc->tl_ldata, sizeof(struct tl_list_data), M_DEVBUF); |