wlan - Rip out all wlan locks part 2/2 - cleanup
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 7 Sep 2010 20:18:31 +0000 (13:18 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 7 Sep 2010 20:25:18 +0000 (13:25 -0700)
* Clean up a few snafus and adjust the names for some procedures.

* Flesh out README.DRAGONFLY

sys/netproto/802_11/README.DRAGONFLY
sys/netproto/802_11/ieee80211_dragonfly.h
sys/netproto/802_11/wlan/ieee80211.c
sys/netproto/802_11/wlan/ieee80211_dragonfly.c
sys/netproto/802_11/wlan/ieee80211_input.c
sys/netproto/802_11/wlan/ieee80211_proto.c
sys/netproto/802_11/wlan/ieee80211_scan.c

index 4cf19ba..28c02c8 100644 (file)
@@ -5,33 +5,75 @@
     wlan_global_serializer.  Normally all wireless base drivers also
     use this serializer to avoid deadlocks.
 
-modevent       ieee80211_dragonfly.h
-               search for DECLARE_MODULE
+STEP 1:
 
-sysctl         search for SYSCTL_HANDLER_ARGS
+    When porting a new wireless low level device be sure to remove all
+    *LOCK* (upper case) macro calls because the whole point of this is
+    to redo the locking with our own.
 
-eventhandler   search for EVENTHANDLER_REGISTER
+STEP 2:
 
-taskq          search for TASK_INIT
+    All border crossings (module loader, sysctl, eventhandlers, tasks,
+    callouts, ifnet, devmethod, and interrupt handlers) must be properly
+    wrapped with wlan_serialize_enter() and wlan_serialize_exit().  Pay
+    careful attention to any early return()s that might break your locks.
 
-callout                search for callout_reset
 
-               search for callout_stop to deal with
-               potential deadlock issues
+modevent       search for DECLARE_MODULE and MOD_LOAD and friends.
+
+sysctl         search for SYSCTL_HANDLER_ARGS.
+
+               Generally speaking sysctls should be rewritten to use
+               a flow-through model (see ath for an example) as most
+               of them currently use a badly designed early-termination
+               model.
+
+eventhandler   search for EVENTHANDLER_REGISTER.
+
+taskq          search for TASK_INIT.
+
+               All taskq callback procedures should be renamed to
+               "<blah>_task".
+
+callout                search for callout_reset.
+
+               search for callout_stop to deal with potential deadlock
+               issues.
+
+               All callout callback procedures should be renamed to
+               "<blah>_callout"
 
 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.
+               This is handled by ieee80211_ifattach() where we set
+               the serializer to &wlan_global_serializer when we
+               call ether_ifattach().  The low level drivers should
+               just be calling ieee80211_ifattach() so no additional
+               work should be needed here.
 
-ifnet, interrupt, devmethod, copyin/copyout
+devmethod      Search for DEVMETHOD (low level drivers).  Typically
+               this is in the *_pci.c file.  The attach function might
+               present an issue where you may wish to release the
+               serializer across the main DMA area allocations.
+               see ath.
 
-ieee80211_ioctl()
+interrupt      Search for bus_setup_intr().
+
+               Typically we pass the &wlan_global_serializer to
+               bus_setup_intr().  The interrupt callback is thus
+               serialized automatically.
 
+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.
+
+Low level device drivers
+               Don't forget that low level device drivers such as ath
+               have callouts, taskq, sysctl, and other elements also!
+
+               Look for old calls to ifnet_serialize*() and remove,
+               in addition to the various LOCK macros.
index 4568d09..0ba82f5 100644 (file)
  */
 extern struct lwkt_serialize wlan_global_serializer;
 
-void wlan_serialize_enter(void);
-void wlan_serialize_exit(void);
+#define wlan_serialize_enter() _wlan_serialize_enter(__FUNCTION__)
+#define wlan_serialize_exit()  _wlan_serialize_exit(__FUNCTION__)
+void _wlan_serialize_enter(const char *funcname);
+void _wlan_serialize_exit(const char *funcname);
 int wlan_serialize_sleep(void *ident, int flags, const char *wmesg, int timo);
 
 static __inline void
@@ -234,19 +236,18 @@ wlan_##name##_modevent(module_t mod, int type, void *unused)              \
                error = 0;                                              \
                break;                                                  \
        case MOD_UNLOAD:                                                \
+               error = 0;                                              \
                if (nrefs) {                                            \
                        kprintf("wlan_##name: still in use (%u "        \
                                "dynamic refs)\n",                      \
                                nrefs);                                 \
-                       return EBUSY;                                   \
-               }                                                       \
-               if (type == MOD_UNLOAD) {                               \
+                       error = EBUSY;                                  \
+               } else if (type == MOD_UNLOAD) {                        \
                        SET_FOREACH(iter, policy##_set) {               \
                                f = (void*) *iter;                      \
                                f(type);                                \
                        }                                               \
                }                                                       \
-               error = 0;                                              \
                break;                                                  \
        default:                                                        \
                error = EINVAL;                                         \
@@ -274,12 +275,11 @@ _IEEE80211_POLICY_MODULE(crypto, name, version);                  \
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
-       wlan_serialize_enter();                                         \
+       /* wlan already serialized! */                                  \
        if (type == MOD_LOAD)                                           \
                ieee80211_crypto_register(&name);                       \
        else                                                            \
                ieee80211_crypto_unregister(&name);                     \
-       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(crypto##_set, name##_modevent)
 
@@ -293,12 +293,11 @@ TEXT_SET(crypto##_set, name##_modevent)
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
-       wlan_serialize_enter();                                         \
+       /* wlan already serialized! */                                  \
        if (type == MOD_LOAD)                                           \
                ieee80211_scanner_register(alg, &v);                    \
        else                                                            \
                ieee80211_scanner_unregister(alg, &v);                  \
-       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(scanner_set, name##_modevent);                                        \
 
@@ -310,12 +309,11 @@ _IEEE80211_POLICY_MODULE(acl, name, version);                             \
 static void                                                            \
 alg##_modevent(int type)                                               \
 {                                                                      \
-       wlan_serialize_enter();                                         \
+       /* wlan already serialized! */                                  \
        if (type == MOD_LOAD)                                           \
                ieee80211_aclator_register(&alg);                       \
        else                                                            \
                ieee80211_aclator_unregister(&alg);                     \
-       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(acl_set, alg##_modevent);                                     \
 
@@ -329,12 +327,11 @@ TEXT_SET(acl_set, alg##_modevent);                                        \
 static void                                                            \
 name##_modevent(int type)                                              \
 {                                                                      \
-       wlan_serialize_enter();                                         \
+       /* wlan already serialized! */                                  \
        if (type == MOD_LOAD)                                           \
                ieee80211_authenticator_register(alg, &v);              \
        else                                                            \
                ieee80211_authenticator_unregister(alg);                \
-       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(auth_set, name##_modevent)
 
@@ -348,12 +345,11 @@ TEXT_SET(auth_set, name##_modevent)
 static void                                                            \
 alg##_modevent(int type)                                               \
 {                                                                      \
-       wlan_serialize_enter();                                         \
+       /* wlan already serialized! */                                  \
        if (type == MOD_LOAD)                                           \
                ieee80211_ratectl_register(alg, &v);                    \
        else                                                            \
                ieee80211_ratectl_unregister(alg);                      \
-       wlan_serialize_exit();                                          \
 }                                                                      \
 TEXT_SET(ratectl##_set, alg##_modevent)
 
index baab813..9bf79a2 100644 (file)
@@ -392,7 +392,6 @@ 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;
@@ -529,7 +528,7 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
        if (maxrate)
                ifp->if_baudrate = IF_Mbps(maxrate);
 
-       ether_ifattach(ifp, vap->iv_myaddr, NULL);
+       ether_ifattach(ifp, vap->iv_myaddr, &wlan_global_serializer);
        if (vap->iv_opmode == IEEE80211_M_MONITOR) {
                /* NB: disallow transmit */
 #ifdef __FreeBSD__
@@ -582,8 +581,11 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
        /*
         * Flush any deferred vap tasks.
         */
+       wlan_assert_serialized();
+       wlan_serialize_exit();  /* exit to block */
        ieee80211_draintask(ic, &vap->iv_nstate_task);
        ieee80211_draintask(ic, &vap->iv_swbmiss_task);
+       wlan_serialize_enter(); /* then reenter */
 
 #ifdef __FreeBSD__
        /* XXX band-aid until ifnet handles this for us */
index a062fe1..3e615eb 100644 (file)
@@ -155,19 +155,23 @@ wlan_clone_destroy(struct ifnet *ifp)
        ic->ic_vap_delete(vap);
 }
 
+const char *wlan_last_enter_func;
+const char *wlan_last_exit_func;
 /*
  * These serializer functions are used by wlan and all drivers.
  */
 void
-wlan_serialize_enter(void)
+_wlan_serialize_enter(const char *funcname)
 {
        lwkt_serialize_enter(&wlan_global_serializer);
+       wlan_last_enter_func = funcname;
 }
 
 void
-wlan_serialize_exit(void)
+_wlan_serialize_exit(const char *funcname)
 {
        lwkt_serialize_exit(&wlan_global_serializer);
+       wlan_last_exit_func = funcname;
 }
 
 int
@@ -907,7 +911,7 @@ static eventhandler_tag wlan_bpfevent;
 static eventhandler_tag wlan_ifllevent;
 
 static void
-bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
+bpf_track_event(void *arg, struct ifnet *ifp, int dlt, int attach)
 {
        /* NB: identify vap's by if_start */
 
@@ -935,7 +939,7 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
 }
 
 static void
-wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
+wlan_iflladdr_event(void *arg __unused, struct ifnet *ifp)
 {
        struct ieee80211com *ic = ifp->if_l2com;
        struct ieee80211vap *vap, *next;
@@ -980,14 +984,14 @@ wlan_modevent(module_t mod, int type, void *unused)
                if (bootverbose)
                        kprintf("wlan: <802.11 Link Layer>\n");
                wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
-                                       bpf_track, 0,
+                                       bpf_track_event, 0,
                                        EVENTHANDLER_PRI_ANY);
                if (wlan_bpfevent == NULL) {
                        error = ENOMEM;
                        break;
                }
                wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
-                                       wlan_iflladdr, NULL,
+                                       wlan_iflladdr_event, NULL,
                                        EVENTHANDLER_PRI_ANY);
                if (wlan_ifllevent == NULL) {
                        EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
index 03b33b2..d1a466d 100644 (file)
@@ -714,7 +714,11 @@ ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m)
        return 0;
 }
 
-#ifdef IEEE80211_DEBUG
+/*
+ * Modules may be compiled with debugging even if wlan isn't
+ */
+/*#ifdef IEEE80211_DEBUG*/
+#if 1
 /*
  * Debugging support.
  */
index ce50c8e..0337c54 100644 (file)
@@ -1131,7 +1131,9 @@ update_channel_task(void *arg, int npending)
 void
 ieee80211_waitfor_parent(struct ieee80211com *ic)
 {
-       wlan_serialize_exit();
+       print_backtrace(-1);
+       wlan_assert_serialized();
+       wlan_serialize_exit();  /* exit to block */
        taskqueue_block(ic->ic_tq);
        ieee80211_draintask(ic, &ic->ic_parent_task);
        ieee80211_draintask(ic, &ic->ic_mcast_task);
@@ -1139,7 +1141,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();
+       wlan_serialize_enter(); /* then re-enter */
 }
 
 /*
index ea5d78c..9ae2308 100644 (file)
@@ -978,7 +978,7 @@ scan_task(void *arg, int pending)
 
                ss->ss_ops->scan_restart(ss, vap);      /* XXX? */
                ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
-               return;
+               goto done2;
        }
 
        /* past here, scandone is ``true'' if not in bg mode */
@@ -1016,6 +1016,7 @@ done:
        }
        SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
        ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
+done2:
        wlan_serialize_exit();
 #undef ISCAN_REP
 }