em/emx: Fix attach error handling and media leakage in detach
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 23 Sep 2013 01:34:17 +0000 (09:34 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 23 Sep 2013 01:34:17 +0000 (09:34 +0800)
- Add missing ether_ifdetach() if reset fails.
Reported-by: Johannes Hofmann <Johannes.Hofmann@gmx.de>
- Call ifmedia_removeall() on detach path, since these drivers add
  ifmedia themselves; move ifmedia_init() to the beginning of attach
  for this to work.

sys/dev/netif/em/if_em.c
sys/dev/netif/emx/if_emx.c

index ac4ebb2..456fdf1 100644 (file)
@@ -429,6 +429,9 @@ em_attach(device_t dev)
        callout_init_mp(&adapter->timer);
        callout_init_mp(&adapter->tx_fifo_timer);
 
+       ifmedia_init(&adapter->media, IFM_IMASK,
+           em_media_change, em_media_status);
+
        /* Determine hardware and mac info */
        error = em_get_hw_info(adapter);
        if (error) {
@@ -788,6 +791,7 @@ em_attach(device_t dev)
        error = em_reset(adapter);
        if (error) {
                device_printf(dev, "Unable to reset the hardware\n");
+               ether_ifdetach(ifp);
                goto fail;
        }
 
@@ -863,7 +867,7 @@ em_attach(device_t dev)
                               ifp->if_serializer);
        if (error) {
                device_printf(dev, "Failed to register interrupt handler");
-               ether_ifdetach(&adapter->arpcom.ac_if);
+               ether_ifdetach(ifp);
                goto fail;
        }
        return (0);
@@ -904,6 +908,8 @@ em_detach(device_t dev)
        } else if (adapter->memory != NULL) {
                em_rel_hw_control(adapter);
        }
+
+       ifmedia_removeall(&adapter->media);
        bus_generic_detach(dev);
 
        em_free_pci_res(adapter);
@@ -2520,8 +2526,6 @@ em_setup_ifp(struct adapter *adapter)
         * Specify the media types supported by this adapter and register
         * callbacks to update media and link information
         */
-       ifmedia_init(&adapter->media, IFM_IMASK,
-                    em_media_change, em_media_status);
        if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
            adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
                u_char fiber_type = IFM_1000_SX; /* default type */
index d5db862..8ee505b 100644 (file)
@@ -476,6 +476,7 @@ emx_attach(device_t dev)
 
        KKASSERT(i == EMX_NSERIALIZE);
 
+       ifmedia_init(&sc->media, IFM_IMASK, emx_media_change, emx_media_status);
        callout_init_mp(&sc->timer);
 
        sc->dev = sc->osdep.dev = dev;
@@ -825,6 +826,7 @@ emx_attach(device_t dev)
        error = emx_reset(sc);
        if (error) {
                device_printf(dev, "Unable to reset the hardware\n");
+               ether_ifdetach(&sc->arpcom.ac_if);
                goto fail;
        }
 
@@ -898,6 +900,8 @@ emx_detach(device_t dev)
        } else if (sc->memory != NULL) {
                emx_rel_hw_control(sc);
        }
+
+       ifmedia_removeall(&sc->media);
        bus_generic_detach(dev);
 
        if (sc->intr_res != NULL) {
@@ -2044,8 +2048,6 @@ emx_setup_ifp(struct emx_softc *sc)
         * Specify the media types supported by this sc and register
         * callbacks to update media and link information
         */
-       ifmedia_init(&sc->media, IFM_IMASK,
-                    emx_media_change, emx_media_status);
        if (sc->hw.phy.media_type == e1000_media_type_fiber ||
            sc->hw.phy.media_type == e1000_media_type_internal_serdes) {
                ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,