wlan - Rip out all wlan locks part 2/2
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 7 Sep 2010 17:01:17 +0000 (10:01 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 7 Sep 2010 17:01:17 +0000 (10:01 -0700)
* Add wlan_global_serializer and wlan_*() API calls.

* Use the calls at all border crossings.

* NOTE: callout_stop() may still have deadlock issues if it catches a
  callout in-progress.

18 files changed:
sys/netproto/802_11/README.DRAGONFLY [new file with mode: 0644]
sys/netproto/802_11/ieee80211_dragonfly.h
sys/netproto/802_11/ieee80211_node.h
sys/netproto/802_11/ieee80211_proto.h
sys/netproto/802_11/wlan/ieee80211.c
sys/netproto/802_11/wlan/ieee80211_amrr.c
sys/netproto/802_11/wlan/ieee80211_dfs.c
sys/netproto/802_11/wlan/ieee80211_dragonfly.c
sys/netproto/802_11/wlan/ieee80211_ht.c
sys/netproto/802_11/wlan/ieee80211_hwmp.c
sys/netproto/802_11/wlan/ieee80211_mesh.c
sys/netproto/802_11/wlan/ieee80211_node.c
sys/netproto/802_11/wlan/ieee80211_output.c
sys/netproto/802_11/wlan/ieee80211_proto.c
sys/netproto/802_11/wlan/ieee80211_rssadapt.c
sys/netproto/802_11/wlan/ieee80211_scan.c
sys/netproto/802_11/wlan/ieee80211_sta.c
sys/netproto/802_11/wlan/ieee80211_tdma.c

diff --git a/sys/netproto/802_11/README.DRAGONFLY b/sys/netproto/802_11/README.DRAGONFLY
new file mode 100644 (file)
index 0000000..4cf19ba
--- /dev/null
@@ -0,0 +1,37 @@
+
+                           README.DRAGONFLY
+
+    All ABI entry points into the wlan infrastructure must acquire the
+    wlan_global_serializer.  Normally all wireless base drivers also
+    use this serializer to avoid deadlocks.
+
+modevent       ieee80211_dragonfly.h
+               search for DECLARE_MODULE
+
+sysctl         search for SYSCTL_HANDLER_ARGS
+
+eventhandler   search for EVENTHANDLER_REGISTER
+
+taskq          search for TASK_INIT
+
+callout                search for callout_reset
+
+               search for callout_stop to deal with
+               potential deadlock issues
+
+ifnet          wlan/ieee80211.c
+
+               Set if_serializer to &wlan_global_serializer.  There are
+               a few places where if_ioctl is set to NULL and then later
+               restored.  It is unclear why this is being done.
+
+ifnet, interrupt, devmethod, copyin/copyout
+
+ieee80211_ioctl()
+
+               This is called directly from the wlan's ifp->if_ioctl and
+               also from various wireless drivers.  This function expects
+               the serializer to already be acquired.
+
+               The kernel will acquire if_serializer when making
+               ifp->if_ioctl() calls.
index 35f3dc7..4568d09 100644 (file)
@@ -221,16 +221,22 @@ static int                                                                \
 wlan_##name##_modevent(module_t mod, int type, void *unused)           \
 {                                                                      \
        policy##_setup * const *iter, f;                                \
+       int error;                                                      \
+                                                                       \
+       wlan_serialize_enter();                                         \
+                                                                       \
        switch (type) {                                                 \
        case MOD_LOAD:                                                  \
                SET_FOREACH(iter, policy##_set) {                       \
                        f = (void*) *iter;                              \
                        f(type);                                        \
                }                                                       \
-               return 0;                                               \
+               error = 0;                                              \
+               break;                                                  \
        case MOD_UNLOAD:                                                \
                if (nrefs) {                                            \
-                       kprintf("wlan_##name: still in use (%u dynamic refs)\n",\
+                       kprintf("wlan_##name: still in use (%u "        \
+                               "dynamic refs)\n",                      \
                                nrefs);                                 \
                        return EBUSY;                                   \
                }                                                       \
@@ -240,9 +246,16 @@ wlan_##name##_modevent(module_t mod, int type, void *unused)               \
                                f(type);                                \
                        }                                               \
                }                                                       \
-               return 0;                                               \
+               error = 0;                                              \
+               break;                                                  \
+       default:                                                        \
+               error = EINVAL;                                         \
+               break;                                                  \
        }                                                               \
-       return EINVAL;                                                  \
+                                                                       \
+       wlan_serialize_exit();                                          \
+                                                                       \
+       return error;                                                   \
 }                                                                      \
 static moduledata_t name##_mod = {                                     \
        "wlan_" #name,                                                  \
@@ -261,10 +274,12 @@ _IEEE80211_POLICY_MODULE(crypto, name, version);                  \
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
+       wlan_serialize_enter();                                         \
        if (type == MOD_LOAD)                                           \
                ieee80211_crypto_register(&name);                       \
        else                                                            \
                ieee80211_crypto_unregister(&name);                     \
+       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(crypto##_set, name##_modevent)
 
@@ -278,10 +293,12 @@ TEXT_SET(crypto##_set, name##_modevent)
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
+       wlan_serialize_enter();                                         \
        if (type == MOD_LOAD)                                           \
                ieee80211_scanner_register(alg, &v);                    \
        else                                                            \
                ieee80211_scanner_unregister(alg, &v);                  \
+       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(scanner_set, name##_modevent);                                        \
 
@@ -293,10 +310,12 @@ _IEEE80211_POLICY_MODULE(acl, name, version);                             \
 static void                                                            \
 alg##_modevent(int type)                                               \
 {                                                                      \
+       wlan_serialize_enter();                                         \
        if (type == MOD_LOAD)                                           \
                ieee80211_aclator_register(&alg);                       \
        else                                                            \
                ieee80211_aclator_unregister(&alg);                     \
+       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(acl_set, alg##_modevent);                                     \
 
@@ -310,10 +329,12 @@ TEXT_SET(acl_set, alg##_modevent);                                        \
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
+       wlan_serialize_enter();                                         \
        if (type == MOD_LOAD)                                           \
                ieee80211_authenticator_register(alg, &v);              \
        else                                                            \
                ieee80211_authenticator_unregister(alg);                \
+       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(auth_set, name##_modevent)
 
@@ -327,10 +348,12 @@ TEXT_SET(auth_set, name##_modevent)
 static void                                                            \
 alg##_modevent(int type)                                               \
 {                                                                      \
+       wlan_serialize_enter();                                         \
        if (type == MOD_LOAD)                                           \
                ieee80211_ratectl_register(alg, &v);                    \
        else                                                            \
                ieee80211_ratectl_unregister(alg);                      \
+       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(ratectl##_set, alg##_modevent)
 
index d788643..500b160 100644 (file)
@@ -428,7 +428,6 @@ struct ieee80211_node *ieee80211_find_txnode(struct ieee80211vap *,
                const uint8_t macaddr[IEEE80211_ADDR_LEN]);
 #endif
 int    ieee80211_node_delucastkey(struct ieee80211_node *);
-void   ieee80211_node_timeout(void *arg);
 
 typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
 void   ieee80211_iterate_nodes(struct ieee80211_node_table *,
index a969d69..d6ba5ae 100644 (file)
@@ -285,7 +285,7 @@ void        ieee80211_stop_all(struct ieee80211com *);
 void   ieee80211_suspend_all(struct ieee80211com *);
 void   ieee80211_resume_all(struct ieee80211com *);
 void   ieee80211_dturbo_switch(struct ieee80211vap *, int newflags);
-void   ieee80211_swbmiss(void *arg);
+void   ieee80211_swbmiss_callout(void *arg);
 void   ieee80211_beacon_miss(struct ieee80211com *);
 int    ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
 void   ieee80211_print_essid(const uint8_t *, int);
index f41838f..baab813 100644 (file)
@@ -392,6 +392,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
                return ENOMEM;
        }
        if_initname(ifp, name, unit);
+       ifp->if_serializer = &wlan_global_serializer;
        ifp->if_softc = vap;                    /* back pointer */
        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
        ifp->if_start = ieee80211_start;
index 16ec3b4..dc61de3 100644 (file)
@@ -287,10 +287,12 @@ amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
        int error;
 
        error = sysctl_handle_int(oidp, &msecs, 0, req);
-       if (error || !req->newptr)
-               return error;
-       amrr_setinterval(vap, msecs);
-       return 0;
+       wlan_serialize_enter();
+       if (error == 0 && req->newptr)
+               amrr_setinterval(vap, msecs);
+       wlan_serialize_exit();
+
+       return error;
 }
 
 static void
index 00f3663..fab9f29 100644 (file)
@@ -94,15 +94,20 @@ ieee80211_dfs_reset(struct ieee80211com *ic)
 }
 
 static void
-cac_timeout(void *arg)
+cac_timeout_callout(void *arg)
 {
        struct ieee80211vap *vap = arg;
-       struct ieee80211com *ic = vap->iv_ic;
-       struct ieee80211_dfs_state *dfs = &ic->ic_dfs;
+       struct ieee80211com *ic;
+       struct ieee80211_dfs_state *dfs;
        int i;
 
-       if (vap->iv_state != IEEE80211_S_CAC)   /* NB: just in case */
+       wlan_serialize_enter();
+       ic = vap->iv_ic;
+       dfs = &ic->ic_dfs;
+       if (vap->iv_state != IEEE80211_S_CAC) { /* NB: just in case */
+               wlan_serialize_exit();
                return;
+       }
        /*
         * When radar is detected during a CAC we are woken
         * up prematurely to switch to a new channel.
@@ -140,6 +145,7 @@ cac_timeout(void *arg)
                    IEEE80211_NOTIFY_CAC_EXPIRE);
                ieee80211_cac_completeswitch(vap);
        }
+       wlan_serialize_exit();
 }
 
 /*
@@ -153,7 +159,7 @@ ieee80211_dfs_cac_start(struct ieee80211vap *vap)
        struct ieee80211com *ic = vap->iv_ic;
        struct ieee80211_dfs_state *dfs = &ic->ic_dfs;
 
-       callout_reset(&dfs->cac_timer, CAC_TIMEOUT, cac_timeout, vap);
+       callout_reset(&dfs->cac_timer, CAC_TIMEOUT, cac_timeout_callout, vap);
        if_printf(vap->iv_ifp, "start %d second CAC timer on channel %u (%u MHz)\n",
            ticks_to_secs(CAC_TIMEOUT),
            ic->ic_curchan->ic_ieee, ic->ic_curchan->ic_freq);
@@ -193,13 +199,14 @@ ieee80211_dfs_cac_clear(struct ieee80211com *ic,
 }
 
 static void
-dfs_timeout(void *arg)
+dfs_timeout_callout(void *arg)
 {
        struct ieee80211com *ic = arg;
        struct ieee80211_dfs_state *dfs = &ic->ic_dfs;
        struct ieee80211_channel *c;
        int i, oldest, now;
 
+       wlan_serialize_enter();
        now = oldest = ticks;
        for (i = 0; i < ic->ic_nchans; i++) {
                c = &ic->ic_channels[i];
@@ -227,8 +234,9 @@ dfs_timeout(void *arg)
        if (oldest != now) {
                /* arrange to process next channel up for a status change */
                callout_reset(&dfs->nol_timer, oldest + NOL_TIMEOUT - now,
-                   dfs_timeout, ic);
+                   dfs_timeout_callout, ic);
        }
+       wlan_serialize_exit();
 }
 
 static void
@@ -276,8 +284,10 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch
        }
        ieee80211_notify_radar(ic, chan);
        chan->ic_state |= IEEE80211_CHANSTATE_NORADAR;
-       if (!callout_pending(&dfs->nol_timer))
-               callout_reset(&dfs->nol_timer, NOL_TIMEOUT, dfs_timeout, ic);
+       if (!callout_pending(&dfs->nol_timer)) {
+               callout_reset(&dfs->nol_timer, NOL_TIMEOUT,
+                               dfs_timeout_callout, ic);
+       }
 
        /*
         * If radar is detected on the bss channel while
@@ -297,8 +307,10 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch
                announce_radar(ic->ic_ifp, chan, dfs->newchan);
 
 #ifdef notyet
-               if (callout_pending(&dfs->cac_timer))
-                       callout_reset(&dfs->cac_timer, 0, cac_timeout, vap);
+               if (callout_pending(&dfs->cac_timer)) {
+                       callout_reset(&dfs->cac_timer, 0,
+                                       cac_timeout_callout, vap);
+               }
                else if (dfs->newchan != NULL) {
                        /* XXX mode 1, switch count 2 */
                        /* XXX calculate switch count based on max
index e232c51..a062fe1 100644 (file)
@@ -227,6 +227,11 @@ ieee80211_vap_destroy(struct ieee80211vap *vap)
        if_clone_destroy(vap->iv_ifp->if_xname);
 }
 
+/*
+ * NOTE: This handler is used generally to convert milliseconds
+ *      to ticks for various simple sysctl variables and does not
+ *      need to be serialized.
+ */
 int
 ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS)
 {
@@ -234,11 +239,12 @@ ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS)
        int error, t;
 
        error = sysctl_handle_int(oidp, &msecs, 0, req);
-       if (error || !req->newptr)
-               return error;
-       t = msecs_to_ticks(msecs);
-       *(int *)arg1 = (t < 1) ? 1 : t;
-       return 0;
+       if (error == 0 && req->newptr) {
+               t = msecs_to_ticks(msecs);
+               *(int *)arg1 = (t < 1) ? 1 : t;
+       }
+
+       return error;
 }
 
 static int
@@ -248,10 +254,12 @@ ieee80211_sysctl_inact(SYSCTL_HANDLER_ARGS)
        int error;
 
        error = sysctl_handle_int(oidp, &inact, 0, req);
-       if (error || !req->newptr)
-               return error;
-       *(int *)arg1 = inact / IEEE80211_INACT_WAIT;
-       return 0;
+       wlan_serialize_enter();
+       if (error == 0 && req->newptr)
+               *(int *)arg1 = inact / IEEE80211_INACT_WAIT;
+       wlan_serialize_exit();
+
+       return error;
 }
 
 static int
@@ -270,10 +278,12 @@ ieee80211_sysctl_radar(SYSCTL_HANDLER_ARGS)
        int t = 0, error;
 
        error = sysctl_handle_int(oidp, &t, 0, req);
-       if (error || !req->newptr)
-               return error;
-       ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
-       return 0;
+       wlan_serialize_enter();
+       if (error == 0 && req->newptr)
+               ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
+       wlan_serialize_exit();
+
+       return error;
 }
 
 void
@@ -900,6 +910,8 @@ static void
 bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
 {
        /* NB: identify vap's by if_start */
+
+       wlan_serialize_enter();
        if (dlt == DLT_IEEE802_11_RADIO && ifp->if_start == ieee80211_start) {
                struct ieee80211vap *vap = ifp->if_softc;
                /*
@@ -919,6 +931,7 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
                                atomic_subtract_int(&vap->iv_ic->ic_montaps, 1);
                }
        }
+       wlan_serialize_exit();
 }
 
 static void
@@ -927,8 +940,11 @@ wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
        struct ieee80211com *ic = ifp->if_l2com;
        struct ieee80211vap *vap, *next;
 
-       if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
+       wlan_serialize_enter();
+       if (ifp->if_type != IFT_IEEE80211 || ic == NULL) {
+               wlan_serialize_exit();
                return;
+       }
 
        TAILQ_FOREACH_MUTABLE(vap, &ic->ic_vaps, iv_next, next) {
                /*
@@ -944,6 +960,7 @@ wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
                        wlan_serialize_enter();
                }
        }
+       wlan_serialize_exit();
 }
 
 /*
@@ -954,31 +971,47 @@ wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
 static int
 wlan_modevent(module_t mod, int type, void *unused)
 {
+       int error;
+
+       wlan_serialize_enter();
+
        switch (type) {
        case MOD_LOAD:
                if (bootverbose)
                        kprintf("wlan: <802.11 Link Layer>\n");
                wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
-                   bpf_track, 0, EVENTHANDLER_PRI_ANY);
-               if (wlan_bpfevent == NULL)
-                       return ENOMEM;
+                                       bpf_track, 0,
+                                       EVENTHANDLER_PRI_ANY);
+               if (wlan_bpfevent == NULL) {
+                       error = ENOMEM;
+                       break;
+               }
                wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
-                   wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
+                                       wlan_iflladdr, NULL,
+                                       EVENTHANDLER_PRI_ANY);
                if (wlan_ifllevent == NULL) {
                        EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
-                       return ENOMEM;
+                       error = ENOMEM;
+                       break;
                }
                if_clone_attach(&wlan_cloner);
                if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
-               return 0;
+               error = 0;
+               break;
        case MOD_UNLOAD:
                if_deregister_com_alloc(IFT_IEEE80211);
                if_clone_detach(&wlan_cloner);
                EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
                EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
-               return 0;
+               error = 0;
+               break;
+       default:
+               error = EINVAL;
+               break;
        }
-       return EINVAL;
+       wlan_serialize_exit();
+
+       return error;
 }
 
 static moduledata_t wlan_mod = {
index 3b3c7de..6cfed23 100644 (file)
@@ -1496,13 +1496,15 @@ ampdu_tx_stop(struct ieee80211_tx_ampdu *tap)
 }
 
 static void
-addba_timeout(void *arg)
+addba_timeout_callout(void *arg)
 {
        struct ieee80211_tx_ampdu *tap = arg;
 
+       wlan_serialize_enter();
        /* XXX ? */
        tap->txa_flags &= ~IEEE80211_AGGR_XCHGPEND;
        tap->txa_attempts++;
+       wlan_serialize_exit();
 }
 
 static void
@@ -1510,7 +1512,7 @@ addba_start_timeout(struct ieee80211_tx_ampdu *tap)
 {
        /* XXX use CALLOUT_PENDING instead? */
        callout_reset(&tap->txa_timer, ieee80211_addba_timeout,
-           addba_timeout, tap);
+                       addba_timeout_callout, tap);
        tap->txa_flags |= IEEE80211_AGGR_XCHGPEND;
        tap->txa_nextrequest = ticks + ieee80211_addba_timeout;
 }
@@ -1941,11 +1943,13 @@ ieee80211_ampdu_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
 }
 
 static void
-bar_timeout(void *arg)
+bar_timeout_callout(void *arg)
 {
        struct ieee80211_tx_ampdu *tap = arg;
-       struct ieee80211_node *ni = tap->txa_ni;
+       struct ieee80211_node *ni;
 
+       wlan_serialize_enter();
+       ni = tap->txa_ni;
        KASSERT((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0,
            ("bar/addba collision, flags 0x%x", tap->txa_flags));
 
@@ -1954,19 +1958,21 @@ bar_timeout(void *arg)
            tap->txa_ac, tap->txa_flags, tap->txa_attempts);
 
        /* guard against race with bar_tx_complete */
-       if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
-               return;
-       /* XXX ? */
-       if (tap->txa_attempts >= ieee80211_bar_maxtries)
-               ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
-       else
-               ieee80211_send_bar(ni, tap, tap->txa_seqpending);
+       if (tap->txa_flags & IEEE80211_AGGR_BARPEND) {
+               /* XXX ? */
+               if (tap->txa_attempts >= ieee80211_bar_maxtries)
+                       ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
+               else
+                       ieee80211_send_bar(ni, tap, tap->txa_seqpending);
+       }
+       wlan_serialize_exit();
 }
 
 static void
 bar_start_timer(struct ieee80211_tx_ampdu *tap)
 {
-       callout_reset(&tap->txa_timer, ieee80211_bar_timeout, bar_timeout, tap);
+       callout_reset(&tap->txa_timer, ieee80211_bar_timeout,
+                       bar_timeout_callout, tap);
 }
 
 static void
index f947fd6..70705c8 100644 (file)
@@ -81,8 +81,8 @@ static uint8_t * hwmp_add_meshperr(uint8_t *,
 static uint8_t * hwmp_add_meshrann(uint8_t *,
                    const struct ieee80211_meshrann_ie *);
 static void    hwmp_rootmode_setup(struct ieee80211vap *);
-static void    hwmp_rootmode_cb(void *);
-static void    hwmp_rootmode_rann_cb(void *);
+static void    hwmp_rootmode_callout(void *);
+static void    hwmp_rootmode_rann_callout(void *);
 static void    hwmp_recv_preq(struct ieee80211vap *, struct ieee80211_node *,
                    const struct ieee80211_frame *,
                    const struct ieee80211_meshpreq_ie *);
@@ -586,11 +586,11 @@ hwmp_rootmode_setup(struct ieee80211vap *vap)
        case IEEE80211_HWMP_ROOTMODE_NORMAL:
        case IEEE80211_HWMP_ROOTMODE_PROACTIVE:
                callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rootint,
-                   hwmp_rootmode_cb, vap);
+                   hwmp_rootmode_callout, vap);
                break;
        case IEEE80211_HWMP_ROOTMODE_RANN:
                callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rannint,
-                   hwmp_rootmode_rann_cb, vap);
+                   hwmp_rootmode_rann_callout, vap);
                break;
        }
 }
@@ -603,13 +603,17 @@ hwmp_rootmode_setup(struct ieee80211vap *vap)
 #define        PREQ_TADDR(n)   preq.preq_targets[n].target_addr
 #define        PREQ_TSEQ(n)    preq.preq_targets[n].target_seq
 static void
-hwmp_rootmode_cb(void *arg)
+hwmp_rootmode_callout(void *arg)
 {
        struct ieee80211vap *vap = (struct ieee80211vap *)arg;
-       struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
-       struct ieee80211_mesh_state *ms = vap->iv_mesh;
+       struct ieee80211_hwmp_state *hs;
+       struct ieee80211_mesh_state *ms;
        struct ieee80211_meshpreq_ie preq;
 
+       wlan_serialize_enter();
+       hs = vap->iv_hwmp;
+       ms = vap->iv_mesh;
+
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
            "%s", "send broadcast PREQ");
 
@@ -633,6 +637,7 @@ hwmp_rootmode_cb(void *arg)
        vap->iv_stats.is_hwmp_rootreqs++;
        hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq);
        hwmp_rootmode_setup(vap);
+       wlan_serialize_exit();
 }
 #undef PREQ_TFLAGS
 #undef PREQ_TADDR
@@ -643,13 +648,16 @@ hwmp_rootmode_cb(void *arg)
  * called when the vap is configured as a HWMP RANN root node.
  */
 static void
-hwmp_rootmode_rann_cb(void *arg)
+hwmp_rootmode_rann_callout(void *arg)
 {
        struct ieee80211vap *vap = (struct ieee80211vap *)arg;
-       struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
-       struct ieee80211_mesh_state *ms = vap->iv_mesh;
+       struct ieee80211_hwmp_state *hs;
+       struct ieee80211_mesh_state *ms;
        struct ieee80211_meshrann_ie rann;
 
+       wlan_serialize_enter();
+       hs = vap->iv_hwmp;
+       ms = vap->iv_mesh;
        IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
            "%s", "send broadcast RANN");
 
@@ -665,6 +673,7 @@ hwmp_rootmode_rann_cb(void *arg)
        vap->iv_stats.is_hwmp_rootrann++;
        hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &rann);
        hwmp_rootmode_setup(vap);
+       wlan_serialize_exit();
 }
 
 #define        PREQ_TFLAGS(n)  preq->preq_targets[n].target_flags
index b967c8a..1cf94a6 100644 (file)
@@ -67,7 +67,7 @@ static int    mesh_select_proto_path(struct ieee80211vap *, const char *);
 static int     mesh_select_proto_metric(struct ieee80211vap *, const char *);
 static void    mesh_vattach(struct ieee80211vap *);
 static int     mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-static void    mesh_rt_cleanup_cb(void *);
+static void    mesh_rt_cleanup_callout(void *);
 static void    mesh_linkchange(struct ieee80211_node *,
                    enum ieee80211_mesh_mlstate);
 static void    mesh_checkid(void *, struct ieee80211_node *);
@@ -84,7 +84,7 @@ static void   mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
                    int, int);
 static void    mesh_peer_timeout_setup(struct ieee80211_node *);
 static void    mesh_peer_timeout_backoff(struct ieee80211_node *);
-static void    mesh_peer_timeout_cb(void *);
+static void    mesh_peer_timeout_callout(void *);
 static __inline void
                mesh_peer_timeout_stop(struct ieee80211_node *);
 static int     mesh_verify_meshid(struct ieee80211vap *, const uint8_t *);
@@ -659,7 +659,7 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                }
                ieee80211_node_authorize(vap->iv_bss);
                callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
-                    mesh_rt_cleanup_cb, vap);
+                    mesh_rt_cleanup_callout, vap);
                break;
        default:
                break;
@@ -670,14 +670,16 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 }
 
 static void
-mesh_rt_cleanup_cb(void *arg)
+mesh_rt_cleanup_callout(void *arg)
 {
        struct ieee80211vap *vap = arg;
        struct ieee80211_mesh_state *ms = vap->iv_mesh;
 
+       wlan_serialize_enter();
        mesh_rt_flush_invalid(vap);
        callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
-           mesh_rt_cleanup_cb, vap);
+                     mesh_rt_cleanup_callout, vap);
+       wlan_serialize_exit();
 }
 
 
@@ -2155,9 +2157,10 @@ mesh_peer_timeout_setup(struct ieee80211_node *ni)
                ni->ni_mltval = ieee80211_mesh_retrytimeout;
                break;
        }
-       if (ni->ni_mltval)
+       if (ni->ni_mltval) {
                callout_reset(&ni->ni_mltimer, ni->ni_mltval,
-                   mesh_peer_timeout_cb, ni);
+                             mesh_peer_timeout_callout, ni);
+       }
 }
 
 /*
@@ -2170,8 +2173,8 @@ mesh_peer_timeout_backoff(struct ieee80211_node *ni)
        
        r = karc4random();
        ni->ni_mltval += r % ni->ni_mltval;
-       callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
-           ni);
+       callout_reset(&ni->ni_mltimer, ni->ni_mltval,
+                     mesh_peer_timeout_callout, ni);
 }
 
 static __inline void
@@ -2184,11 +2187,12 @@ mesh_peer_timeout_stop(struct ieee80211_node *ni)
  * Mesh Peer Link Management FSM timeout handling.
  */
 static void
-mesh_peer_timeout_cb(void *arg)
+mesh_peer_timeout_callout(void *arg)
 {
        struct ieee80211_node *ni = (struct ieee80211_node *)arg;
        uint16_t args[3];
 
+       wlan_serialize_enter();
        IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_MESH,
            ni, "mesh link timeout, state %d, retry counter %d",
            ni->ni_mlstate, ni->ni_mlrcnt);
@@ -2236,6 +2240,7 @@ mesh_peer_timeout_cb(void *arg)
                mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
                break;
        }
+       wlan_serialize_exit();
 }
 
 static int
index f342c68..62357b4 100644 (file)
@@ -90,6 +90,7 @@ static int8_t node_getrssi(const struct ieee80211_node *);
 static void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
 static void node_getmimoinfo(const struct ieee80211_node *,
        struct ieee80211_mimo_info *);
+static void ieee80211_node_timeout_callout(void *arg);
 
 static void _ieee80211_free_node(struct ieee80211_node *);
 
@@ -114,7 +115,7 @@ ieee80211_node_attach(struct ieee80211com *ic)
                IEEE80211_INACT_INIT, ic->ic_max_keyix);
        callout_init_mp(&ic->ic_inact);
        callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
-               ieee80211_node_timeout, ic);
+                     ieee80211_node_timeout_callout, ic);
 
        ic->ic_node_alloc = node_alloc;
        ic->ic_node_free = node_free;
@@ -2051,8 +2052,8 @@ ieee80211_drain(struct ieee80211com *ic)
 /*
  * Per-ieee80211com inactivity timer callback.
  */
-void
-ieee80211_node_timeout(void *arg)
+static void
+ieee80211_node_timeout_callout(void *arg)
 {
        struct ieee80211com *ic = arg;
 
@@ -2065,6 +2066,7 @@ ieee80211_node_timeout(void *arg)
         * idle counters) but this should be ok unless the CSA is
         * active for an unusually long time.
         */
+       wlan_serialize_enter();
        if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) {
                ieee80211_scan_timeout(ic);
                ieee80211_timeout_stations(ic);
@@ -2074,7 +2076,8 @@ ieee80211_node_timeout(void *arg)
                ieee80211_ht_timeout(ic);
        }
        callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
-               ieee80211_node_timeout, ic);
+                     ieee80211_node_timeout_callout, ic);
+       wlan_serialize_exit();
 }
 
 void
index c17c5e6..83f1df0 100644 (file)
@@ -2476,11 +2476,13 @@ ieee80211_alloc_cts(struct ieee80211com *ic,
 }
 
 static void
-ieee80211_tx_mgt_timeout(void *arg)
+ieee80211_tx_mgt_timeout_callout(void *arg)
 {
        struct ieee80211_node *ni = arg;
-       struct ieee80211vap *vap = ni->ni_vap;
+       struct ieee80211vap *vap;
 
+       wlan_serialize_enter();
+       vap = ni->ni_vap;
        if (vap->iv_state != IEEE80211_S_INIT &&
            (vap->iv_ic->ic_flags & IEEE80211_F_SCAN) == 0) {
                /*
@@ -2490,6 +2492,7 @@ ieee80211_tx_mgt_timeout(void *arg)
                ieee80211_new_state(vap, IEEE80211_S_SCAN,
                        IEEE80211_SCAN_FAIL_TIMEOUT);
        }
+       wlan_serialize_exit();
 }
 
 static void
@@ -2512,7 +2515,7 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
        if (vap->iv_state == ostate)
                callout_reset(&vap->iv_mgtsend,
                        status == 0 ? IEEE80211_TRANS_WAIT*hz : 0,
-                       ieee80211_tx_mgt_timeout, ni);
+                       ieee80211_tx_mgt_timeout_callout, ni);
 }
 
 static void
index b5f8398..ce50c8e 100644 (file)
@@ -99,13 +99,13 @@ const char *ieee80211_wme_acnames[] = {
        "WME_UPSD",
 };
 
-static void beacon_miss(void *, int);
-static void beacon_swmiss(void *, int);
-static void parent_updown(void *, int);
-static void update_mcast(void *, int);
-static void update_promisc(void *, int);
-static void update_channel(void *, int);
-static void ieee80211_newstate_cb(void *, int);
+static void beacon_miss_task(void *, int);
+static void beacon_swmiss_task(void *, int);
+static void parent_updown_task(void *, int);
+static void update_mcast_task(void *, int);
+static void update_promisc_task(void *, int);
+static void update_channel_task(void *, int);
+static void ieee80211_newstate_task(void *, int);
 static int ieee80211_new_state_locked(struct ieee80211vap *,
        enum ieee80211_state, int);
 
@@ -139,11 +139,11 @@ ieee80211_proto_attach(struct ieee80211com *ic)
        }
        ic->ic_protmode = IEEE80211_PROT_CTSONLY;
 
-       TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
-       TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
-       TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
-       TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
-       TASK_INIT(&ic->ic_bmiss_task, 0, beacon_miss, ic);
+       TASK_INIT(&ic->ic_parent_task, 0, parent_updown_task, ifp);
+       TASK_INIT(&ic->ic_mcast_task, 0, update_mcast_task, ic);
+       TASK_INIT(&ic->ic_promisc_task, 0, update_promisc_task, ic);
+       TASK_INIT(&ic->ic_chan_task, 0, update_channel_task, ic);
+       TASK_INIT(&ic->ic_bmiss_task, 0, beacon_miss_task, ic);
 
        ic->ic_wme.wme_hipri_switch_hysteresis =
                AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
@@ -195,8 +195,8 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
        vap->iv_bmiss_max = IEEE80211_BMISS_MAX;
        callout_init_mp(&vap->iv_swbmiss);
        callout_init_mp(&vap->iv_mgtsend);
-       TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_cb, vap);
-       TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap);
+       TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_task, vap);
+       TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss_task, vap);
        /*
         * Install default tx rate handling: no fixed rate, lowest
         * supported rate for mgmt and multicast frames.  Default
@@ -1081,38 +1081,46 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap)
 }
 
 static void
-parent_updown(void *arg, int npending)
+parent_updown_task(void *arg, int npending)
 {
        struct ifnet *parent = arg;
 
+       wlan_serialize_enter();
        parent->if_ioctl(parent, SIOCSIFFLAGS, NULL, curthread->td_ucred);
+       wlan_serialize_exit();
 }
 
 static void
-update_mcast(void *arg, int npending)
+update_mcast_task(void *arg, int npending)
 {
        struct ieee80211com *ic = arg;
        struct ifnet *parent = ic->ic_ifp;
 
+       wlan_serialize_enter();
        ic->ic_update_mcast(parent);
+       wlan_serialize_exit();
 }
 
 static void
-update_promisc(void *arg, int npending)
+update_promisc_task(void *arg, int npending)
 {
        struct ieee80211com *ic = arg;
        struct ifnet *parent = ic->ic_ifp;
 
+       wlan_serialize_enter();
        ic->ic_update_promisc(parent);
+       wlan_serialize_exit();
 }
 
 static void
-update_channel(void *arg, int npending)
+update_channel_task(void *arg, int npending)
 {
        struct ieee80211com *ic = arg;
 
+       wlan_serialize_enter();
        ic->ic_set_channel(ic);
        ieee80211_radiotap_chan_change(ic);
+       wlan_serialize_exit();
 }
 
 /*
@@ -1123,6 +1131,7 @@ update_channel(void *arg, int npending)
 void
 ieee80211_waitfor_parent(struct ieee80211com *ic)
 {
+       wlan_serialize_exit();
        taskqueue_block(ic->ic_tq);
        ieee80211_draintask(ic, &ic->ic_parent_task);
        ieee80211_draintask(ic, &ic->ic_mcast_task);
@@ -1130,6 +1139,7 @@ ieee80211_waitfor_parent(struct ieee80211com *ic)
        ieee80211_draintask(ic, &ic->ic_chan_task);
        ieee80211_draintask(ic, &ic->ic_bmiss_task);
        taskqueue_unblock(ic->ic_tq);
+       wlan_serialize_enter();
 }
 
 /*
@@ -1349,12 +1359,12 @@ ieee80211_beacon_miss(struct ieee80211com *ic)
 }
 
 static void
-beacon_miss(void *arg, int npending)
+beacon_miss_task(void *arg, int npending)
 {
        struct ieee80211com *ic = arg;
        struct ieee80211vap *vap;
 
-       /* XXX locking */
+       wlan_serialize_enter();
        TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
                /*
                 * We only pass events through for sta vap's in RUN state;
@@ -1366,18 +1376,20 @@ beacon_miss(void *arg, int npending)
                    vap->iv_bmiss != NULL)
                        vap->iv_bmiss(vap);
        }
+       wlan_serialize_exit();
 }
 
 static void
-beacon_swmiss(void *arg, int npending)
+beacon_swmiss_task(void *arg, int npending)
 {
        struct ieee80211vap *vap = arg;
 
-       if (vap->iv_state != IEEE80211_S_RUN)
-               return;
-
-       /* XXX Call multiple times if npending > zero? */
-       vap->iv_bmiss(vap);
+       wlan_serialize_enter();
+       if (vap->iv_state == IEEE80211_S_RUN) {
+               /* XXX Call multiple times if npending > zero? */
+               vap->iv_bmiss(vap);
+       }
+       wlan_serialize_exit();
 }
 
 /*
@@ -1386,12 +1398,12 @@ beacon_swmiss(void *arg, int npending)
  * beacon miss; otherwise reset the counter.
  */
 void
-ieee80211_swbmiss(void *arg)
+ieee80211_swbmiss_callout(void *arg)
 {
        struct ieee80211vap *vap = arg;
        struct ieee80211com *ic = vap->iv_ic;
 
-       /* XXX sleep state? */
+       wlan_serialize_enter();
        KASSERT(vap->iv_state == IEEE80211_S_RUN,
            ("wrong state %d", vap->iv_state));
 
@@ -1411,11 +1423,14 @@ ieee80211_swbmiss(void *arg)
                if (vap->iv_bmiss != NULL)
                        ieee80211_runtask(ic, &vap->iv_swbmiss_task);
                if (vap->iv_bmiss_count == 0)   /* don't re-arm timer */
-                       return;
-       } else
+                       goto done;
+       } else {
                vap->iv_swbmiss_count = 0;
+       }
        callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
-               ieee80211_swbmiss, vap);
+                     ieee80211_swbmiss_callout, vap);
+done:
+       wlan_serialize_exit();
 }
 
 /*
@@ -1576,13 +1591,16 @@ wakeupwaiting(struct ieee80211vap *vap0)
  * Handle post state change work common to all operating modes.
  */
 static void
-ieee80211_newstate_cb(void *xvap, int npending)
+ieee80211_newstate_task(void *xvap, int npending)
 {
        struct ieee80211vap *vap = xvap;
-       struct ieee80211com *ic = vap->iv_ic;
+       struct ieee80211com *ic;
        enum ieee80211_state nstate, ostate;
        int arg, rc;
 
+       wlan_serialize_enter();
+
+       ic = vap->iv_ic;
        nstate = vap->iv_nstate;
        arg = vap->iv_nstate_arg;
 
@@ -1660,7 +1678,7 @@ ieee80211_newstate_cb(void *xvap, int npending)
                ieee80211_flush_ifq((struct ifqueue *)&ic->ic_ifp->if_snd, vap);
        }
 done:
-       ;
+       wlan_serialize_exit();
 }
 
 /*
index 46da93e..29438bb 100644 (file)
@@ -320,10 +320,12 @@ rssadapt_sysctl_interval(SYSCTL_HANDLER_ARGS)
        int error;
 
        error = sysctl_handle_int(oidp, &msecs, 0, req);
-       if (error || !req->newptr)
-               return error;
-       rssadapt_setinterval(vap, msecs);
-       return 0;
+       wlan_serialize_enter();
+       if (error == 0 && req->newptr)
+               rssadapt_setinterval(vap, msecs);
+       wlan_serialize_exit();
+
+       return error;
 }
 
 static void
index 1b5f8c4..ea5d78c 100644 (file)
@@ -95,7 +95,8 @@ struct scan_state {
 
 static void scan_curchan(struct ieee80211_scan_state *, unsigned long);
 static void scan_mindwell(struct ieee80211_scan_state *);
-static void scan_signal(void *);
+static void scan_signal_callout(void *);
+static void scan_signal(struct ieee80211_scan_state *ss);
 static void scan_task(void *, int);
 
 MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
@@ -785,14 +786,22 @@ scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
        if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
                ieee80211_probe_curchan(vap, 0);
        callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
-           maxdwell, scan_signal, ss);
+                     maxdwell, scan_signal_callout, ss);
 }
 
 static void
-scan_signal(void *arg)
+scan_signal_callout(void *arg)
 {
        struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
 
+       wlan_serialize_enter();
+       scan_signal(ss);
+       wlan_serialize_exit();
+}
+
+static void
+scan_signal(struct ieee80211_scan_state *ss)
+{
        wlan_cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv, 0);
 }
 
@@ -814,12 +823,16 @@ scan_task(void *arg, int pending)
 {
 #define        ISCAN_REP       (ISCAN_MINDWELL | ISCAN_DISCARD)
        struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
-       struct ieee80211vap *vap = ss->ss_vap;
-       struct ieee80211com *ic = ss->ss_ic;
+       struct ieee80211vap *vap;
+       struct ieee80211com *ic;
        struct ieee80211_channel *chan;
        unsigned long maxdwell, scanend;
        int scandone = 0;
 
+       wlan_serialize_enter();
+       vap = ss->ss_vap;
+       ic = ss->ss_ic;
+
        if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
            (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) {
                /* Cancelled before we started */
@@ -1003,6 +1016,7 @@ done:
        }
        SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
        ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
+       wlan_serialize_exit();
 #undef ISCAN_REP
 }
 
index 61a5ec9..cfee127 100644 (file)
@@ -409,7 +409,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                                2 * vap->iv_bmissthreshold * ni->ni_intval);
                        vap->iv_swbmiss_count = 0;
                        callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
-                               ieee80211_swbmiss, vap);
+                                     ieee80211_swbmiss_callout, vap);
                }
                /*
                 * When 802.1x is not in use mark the port authorized
index d3b5b12..4e9b0c0 100644 (file)
@@ -274,7 +274,7 @@ tdma_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                    ((ts->tdma_slotcnt * ts->tdma_slotlen) / 1024));
                vap->iv_swbmiss_count = 0;
                callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
-                       ieee80211_swbmiss, vap);
+                             ieee80211_swbmiss_callout, vap);
        }
        return status;
 }