wlan: Make sure that WLAN serializer is not held for if_{detach,attach}()
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 4 Feb 2015 14:01:19 +0000 (22:01 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 5 Feb 2015 02:52:33 +0000 (10:52 +0800)
Tested-by: dillon@
sys/dev/netif/ath/ath/if_ath.c
sys/netproto/802_11/ieee80211_dragonfly.h
sys/netproto/802_11/wlan/ieee80211.c
sys/netproto/802_11/wlan/ieee80211_dragonfly.c

index 2ed6576..a664bf4 100644 (file)
@@ -1180,8 +1180,15 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
 
        /* NB: used to size node table key mapping array */
        ic->ic_max_keyix = sc->sc_keymax;
-       /* call MI attach routine. */
+       /*
+        * Call MI attach routine.
+        *
+        * WLAN serializer must _not_ be held for ieee80211_ifattach(),
+        * since it could dead-lock the domsg to netisrs.
+        */
+       wlan_serialize_exit();
        ieee80211_ifattach(ic, macaddr);
+       wlan_serialize_enter();
        ic->ic_setregdomain = ath_setregdomain;
        ic->ic_getradiocaps = ath_getradiocaps;
        sc->sc_opmode = HAL_M_STA;
index 33099e3..bb7cb10 100644 (file)
@@ -83,6 +83,12 @@ wlan_assert_serialized(void)
        ASSERT_SERIALIZED(&wlan_global_serializer);
 }
 
+static __inline void
+wlan_assert_notserialized(void)
+{
+       ASSERT_NOT_SERIALIZED(&wlan_global_serializer);
+}
+
 /*
  * Node reference counting definitions.
  *
index 784dca0..609f773 100644 (file)
@@ -300,6 +300,12 @@ ieee80211_ifattach(struct ieee80211com *ic,
        struct sockaddr_dl *sdl;
        struct ifaddr *ifa;
 
+       /*
+        * This function must _not_ be serialized by the WLAN serializer,
+        * since it could dead-lock the domsg to netisrs in if_attach().
+        */
+       wlan_assert_notserialized();
+
        KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
 
        IEEE80211_LOCK_INIT(ic, ifp->if_xname);
@@ -384,6 +390,23 @@ ieee80211_ifdetach(struct ieee80211com *ic)
        struct ifnet *ifp = ic->ic_ifp;
        struct ieee80211vap *vap;
 
+       /*
+        * WLAN serializer must _not_ be held for if_detach()
+        * or ieee80211_vap_destroy(), since it could dead-lock
+        * the domsg to netisrs.
+        *
+        * NOTE:
+        * It is safe to release the WLAN serializer for the
+        * ic_vaps, since the physical/parent ifnet is no longer
+        * visible after the if_detach().
+        *
+        * XXX
+        * This function actually should _not_ be serialized
+        * by the WLAN serializer, however, all 802.11 device
+        * drivers serialize it ...
+        */
+       wlan_serialize_exit();
+
        /*
         * This detaches the main interface, but not the vaps.
         * Each VAP may be in a separate VIMAGE.
@@ -398,6 +421,9 @@ ieee80211_ifdetach(struct ieee80211com *ic)
         */
        while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL)
                ieee80211_vap_destroy(vap);
+
+       wlan_serialize_enter();
+
        ieee80211_waitfor_parent(ic);
 
        ieee80211_sysctl_detach(ic);
@@ -582,6 +608,12 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
        struct ifmediareq imr;
        int maxrate;
 
+       /*
+        * This function must _not_ be serialized by the WLAN serializer,
+        * since it could dead-lock the domsg to netisrs in ether_ifattach().
+        */
+       wlan_assert_notserialized();
+
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
            "%s: %s parent %s flags 0x%x flags_ext 0x%x\n",
            __func__, ieee80211_opmode_name[vap->iv_opmode],
@@ -642,6 +674,12 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
        struct ieee80211com *ic = vap->iv_ic;
        struct ifnet *ifp = vap->iv_ifp;
 
+       /*
+        * This function must _not_ be serialized by the WLAN serializer,
+        * since it could dead-lock the domsg to netisrs in ether_ifdettach().
+        */
+       wlan_assert_notserialized();
+
        CURVNET_SET(ifp->if_vnet);
 
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s parent %s\n",
index 1142161..890f197 100644 (file)
@@ -314,6 +314,7 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
 void
 ieee80211_vap_destroy(struct ieee80211vap *vap)
 {
+       wlan_assert_notserialized();
        if_clone_destroy(vap->iv_ifp->if_xname);
 }