diff options
author | njl <njl@FreeBSD.org> | 2003-04-17 20:32:06 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2003-04-17 20:32:06 +0000 |
commit | fe07eb9dfb67dec3b9867ee376a889a70b355179 (patch) | |
tree | 3cf87a7e7fce73f14cb753a6554ec38575d14502 /sys/pci | |
parent | 9aba79052e570949849c1985ff95ff264ff272ec (diff) | |
download | FreeBSD-src-fe07eb9dfb67dec3b9867ee376a889a70b355179.zip FreeBSD-src-fe07eb9dfb67dec3b9867ee376a889a70b355179.tar.gz |
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
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_dc.c | 14 | ||||
-rw-r--r-- | sys/pci/if_pcn.c | 21 | ||||
-rw-r--r-- | sys/pci/if_rl.c | 18 | ||||
-rw-r--r-- | sys/pci/if_sf.c | 18 | ||||
-rw-r--r-- | sys/pci/if_sis.c | 21 | ||||
-rw-r--r-- | sys/pci/if_sk.c | 18 | ||||
-rw-r--r-- | sys/pci/if_ste.c | 18 | ||||
-rw-r--r-- | sys/pci/if_ti.c | 18 | ||||
-rw-r--r-- | sys/pci/if_tl.c | 18 | ||||
-rw-r--r-- | sys/pci/if_vr.c | 18 | ||||
-rw-r--r-- | sys/pci/if_wb.c | 22 | ||||
-rw-r--r-- | sys/pci/if_xl.c | 27 |
12 files changed, 173 insertions, 58 deletions
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index 15acd86..5979bd3 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -2282,6 +2282,7 @@ dc_attach(dev) if (error) { printf("dc%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -2291,6 +2292,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 dc_detach(dev) device_t dev; @@ -2305,12 +2313,14 @@ dc_detach(dev) ifp = &sc->arpcom.ac_if; + /* These should only be active if attach succeeded */ if (device_is_alive(dev)) { dc_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->dc_miibus); - bus_generic_detach(dev); } + if (sc->dc_miibus) + device_delete_child(dev, sc->dc_miibus); + bus_generic_detach(dev); if (sc->dc_intrhand) bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); diff --git a/sys/pci/if_pcn.c b/sys/pci/if_pcn.c index 4462160..7fbd351 100644 --- a/sys/pci/if_pcn.c +++ b/sys/pci/if_pcn.c @@ -625,11 +625,13 @@ pcn_attach(dev) */ ether_ifattach(ifp, (u_int8_t *) eaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->pcn_irq, INTR_TYPE_NET, pcn_intr, sc, &sc->pcn_intrhand); if (error) { printf("pcn%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -640,6 +642,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 pcn_detach(dev) device_t dev; @@ -653,15 +662,15 @@ pcn_detach(dev) KASSERT(mtx_initialized(&sc->pcn_mtx), ("pcn mutex not initialized")); PCN_LOCK(sc); + /* These should only be active if attach succeeded */ if (device_is_alive(dev)) { - if (bus_child_present(dev)) { - pcn_reset(sc); - pcn_stop(sc); - } + pcn_reset(sc); + pcn_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->pcn_miibus); - bus_generic_detach(dev); } + if (sc->pcn_miibus) + device_delete_child(dev, sc->pcn_miibus); + bus_generic_detach(dev); if (sc->pcn_intrhand) bus_teardown_intr(dev, sc->pcn_irq, sc->pcn_intrhand); diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 7664dd59..5ddff77 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -1064,11 +1064,13 @@ rl_attach(dev) */ ether_ifattach(ifp, eaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->rl_irq, INTR_TYPE_NET, rl_intr, sc, &sc->rl_intrhand); if (error) { printf("rl%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -1079,6 +1081,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 rl_detach(dev) device_t dev; @@ -1091,13 +1100,14 @@ rl_detach(dev) RL_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)) - rl_stop(sc); + rl_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->rl_miibus); - bus_generic_detach(dev); } + if (sc->rl_miibus) + device_delete_child(dev, sc->rl_miibus); + bus_generic_detach(dev); if (sc->rl_intrhand) bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand); diff --git a/sys/pci/if_sf.c b/sys/pci/if_sf.c index a7ebb01..511e450 100644 --- a/sys/pci/if_sf.c +++ b/sys/pci/if_sf.c @@ -792,11 +792,13 @@ sf_attach(dev) */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); + /* Hook interrupt last to avoid having to lock softc */ 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); + ether_ifdetach(ifp); goto fail; } @@ -807,6 +809,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 sf_detach(dev) device_t dev; @@ -819,13 +828,14 @@ sf_detach(dev) SF_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)) - sf_stop(sc); + sf_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->sf_miibus); - bus_generic_detach(dev); } + if (sc->sf_miibus) + device_delete_child(dev, sc->sf_miibus); + bus_generic_detach(dev); if (sc->sf_intrhand) bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c index 1934827..e8bf48f 100644 --- a/sys/pci/if_sis.c +++ b/sys/pci/if_sis.c @@ -1387,11 +1387,13 @@ sis_attach(dev) ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->sis_irq, INTR_TYPE_NET, sis_intr, sc, &sc->sis_intrhand); if (error) { printf("sis%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -1402,6 +1404,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 sis_detach(dev) device_t dev; @@ -1414,15 +1423,15 @@ sis_detach(dev) SIS_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)) { - sis_reset(sc); - sis_stop(sc); - } + sis_reset(sc); + sis_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->sis_miibus); - bus_generic_detach(dev); } + if (sc->sis_miibus) + device_delete_child(dev, sc->sis_miibus); + bus_generic_detach(dev); if (sc->sis_intrhand) bus_teardown_intr(dev, sc->sis_irq, sc->sis_intrhand); diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c index 1093f34..49424bb 100644 --- a/sys/pci/if_sk.c +++ b/sys/pci/if_sk.c @@ -1178,6 +1178,7 @@ sk_attach_xmac(dev) if (mii_phy_probe(dev, &sc_if->sk_miibus, sk_ifmedia_upd, sk_ifmedia_sts)) { printf("skc%d: no PHY found!\n", sc_if->sk_unit); + ether_ifdetach(ifp); error = ENXIO; goto fail_xmac; } @@ -1335,6 +1336,7 @@ sk_attach(dev) bus_generic_attach(dev); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->sk_irq, INTR_TYPE_NET, sk_intr, sc, &sc->sk_intrhand); @@ -1350,6 +1352,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 sk_detach_xmac(dev) device_t dev; @@ -1365,13 +1374,14 @@ sk_detach_xmac(dev) SK_IF_LOCK(sc_if); ifp = &sc_if->arpcom.ac_if; + /* These should only be active if attach_xmac succeeded */ if (device_is_alive(dev)) { - if (bus_child_present(dev)) - sk_stop(sc_if); + sk_stop(sc_if); ether_ifdetach(ifp); - device_delete_child(dev, sc_if->sk_miibus); - bus_generic_detach(dev); } + if (sc_if->sk_miibus) + device_delete_child(dev, sc_if->sk_miibus); + bus_generic_detach(dev); if (sc_if->sk_cdata.sk_jumbo_buf) contigfree(sc_if->sk_cdata.sk_jumbo_buf, SK_JMEM, M_DEVBUF); if (sc_if->sk_rdata) { diff --git a/sys/pci/if_ste.c b/sys/pci/if_ste.c index 67f16f4..3c913a0 100644 --- a/sys/pci/if_ste.c +++ b/sys/pci/if_ste.c @@ -1052,11 +1052,13 @@ ste_attach(dev) ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET, ste_intr, sc, &sc->ste_intrhand); if (error) { printf("ste%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -1067,6 +1069,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 ste_detach(dev) device_t dev; @@ -1079,13 +1088,14 @@ ste_detach(dev) STE_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)) - ste_stop(sc); + ste_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->ste_miibus); - bus_generic_detach(dev); } + if (sc->ste_miibus) + device_delete_child(dev, sc->ste_miibus); + bus_generic_detach(dev); if (sc->ste_intrhand) bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand); diff --git a/sys/pci/if_ti.c b/sys/pci/if_ti.c index c1b5796..5046685 100644 --- a/sys/pci/if_ti.c +++ b/sys/pci/if_ti.c @@ -2115,6 +2115,7 @@ ti_attach(dev) mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); + ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts); sc->arpcom.ac_if.if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING; sc->arpcom.ac_if.if_capenable = sc->arpcom.ac_if.if_capabilities; @@ -2259,7 +2260,6 @@ ti_attach(dev) ifp->if_snd.ifq_maxlen = TI_TX_RING_CNT - 1; /* Set up ifmedia support. */ - ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts); if (sc->ti_copper) { /* * Copper cards allow manual 10/100 mode selection, @@ -2310,11 +2310,13 @@ ti_attach(dev) */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->ti_irq, INTR_TYPE_NET, ti_intr, sc, &sc->ti_intrhand); if (error) { printf("ti%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -2352,7 +2354,13 @@ ti_unref_special(device_t dev) return(0); } - +/* + * 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 ti_detach(dev) device_t dev; @@ -2368,13 +2376,13 @@ ti_detach(dev) TI_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)) - ti_stop(sc); + ti_stop(sc); ether_ifdetach(ifp); bus_generic_detach(dev); - ifmedia_removeall(&sc->ifmedia); } + ifmedia_removeall(&sc->ifmedia); if (sc->ti_intrhand) bus_teardown_intr(dev, sc->ti_irq, sc->ti_intrhand); diff --git a/sys/pci/if_tl.c b/sys/pci/if_tl.c index 755d4af..ebe64cc 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); diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c index 793ae64..84bd474 100644 --- a/sys/pci/if_vr.c +++ b/sys/pci/if_vr.c @@ -878,11 +878,13 @@ vr_attach(dev) */ ether_ifattach(ifp, eaddr); + /* Hook interrupt last to avoid having to lock softc */ 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); + ether_ifdetach(ifp); goto fail; } @@ -893,6 +895,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 vr_detach(dev) device_t dev; @@ -905,13 +914,14 @@ vr_detach(dev) VR_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)) - vr_stop(sc); + vr_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->vr_miibus); - bus_generic_detach(dev); } + if (sc->vr_miibus) + device_delete_child(dev, sc->vr_miibus); + bus_generic_detach(dev); if (sc->vr_intrhand) bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand); 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); diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index eeb635d..8e6756f 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -1308,6 +1308,7 @@ xl_attach(dev) mtx_init(&sc->xl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); + ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts); sc->xl_flags = 0; if (pci_get_device(dev) == TC_DEVICEID_HURRICANE_555) @@ -1625,9 +1626,6 @@ xl_attach(dev) /* * Do ifmedia setup. */ - - ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts); - if (sc->xl_media & XL_MEDIAOPT_BT) { if (bootverbose) printf("xl%d: found 10baseT\n", sc->xl_unit); @@ -1726,10 +1724,12 @@ done: */ ether_ifattach(ifp, eaddr); + /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->xl_irq, INTR_TYPE_NET, xl_intr, sc, &sc->xl_intrhand); if (error) { printf("xl%d: couldn't set up irq\n", unit); + ether_ifdetach(ifp); goto fail; } @@ -1740,6 +1740,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 xl_detach(dev) device_t dev; @@ -1761,16 +1768,16 @@ xl_detach(dev) res = SYS_RES_IOPORT; } + /* These should only be active if attach succeeded */ if (device_is_alive(dev)) { - if (bus_child_present(dev)) { - xl_reset(sc); - xl_stop(sc); - } + xl_reset(sc); + xl_stop(sc); ether_ifdetach(ifp); - device_delete_child(dev, sc->xl_miibus); - bus_generic_detach(dev); - ifmedia_removeall(&sc->ifmedia); } + if (sc->xl_miibus) + device_delete_child(dev, sc->xl_miibus); + bus_generic_detach(dev); + ifmedia_removeall(&sc->ifmedia); if (sc->xl_intrhand) bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand); |