PERFORCE change 140218 for review

Sam Leffler sam at FreeBSD.org
Fri Apr 18 18:22:41 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=140218

Change 140218 by sam at sam_ebb on 2008/04/18 18:21:48

	Eliminate holding the com lock over the ioctl callback to
	auto-up the parent device by deferring to a task.  We mark
	the vap running so when the driver calls back to us through
	ieee80211_start_all we don't double count them in ic_nrunning.
	This eliminates the lock being held over the driver's init
	method which was problematic for drivers that must defer work
	(e.g. usb)

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_proto.c#28 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#39 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_proto.c#28 (text+ko) ====

@@ -37,6 +37,7 @@
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
+#include <sys/taskqueue.h>
 
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -95,6 +96,7 @@
 	"WME_UPSD",
 };
 
+static void parent_up(void *, int);
 static int ieee80211_new_state_locked(struct ieee80211vap *,
 	enum ieee80211_state, int);
 
@@ -128,6 +130,8 @@
 	}
 	ic->ic_protmode = IEEE80211_PROT_CTSONLY;
 
+	TASK_INIT(&ic->ic_parent_task, 0, parent_up, ifp);
+
 	ic->ic_wme.wme_hipri_switch_hysteresis =
 		AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
 
@@ -1059,6 +1063,14 @@
 	}
 }
 
+static void
+parent_up(void *arg, int npending)
+{
+	struct ifnet *parent = arg;
+
+	parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
+}
+
 /*
  * Start a vap running.  If this is the first vap to be
  * set running on the underlying device then we
@@ -1079,6 +1091,15 @@
 
 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
 		/*
+		 * Mark us running.  Note that it's ok to do this first;
+		 * if we need to bring the parent device up we defer that
+		 * to avoid dropping the com lock.  We expect the device
+		 * to respond to being marked up by calling back into us
+		 * through ieee80211_start_all at which point we'll come
+		 * back in here and complete the work.
+		 */
+		ifp->if_drv_flags |= IFF_DRV_RUNNING;
+		/*
 		 * We are not running; if this we are the first vap
 		 * to be brought up auto-up the parent if necessary.
 		 */
@@ -1088,13 +1109,9 @@
 			    IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
 			    "%s: up parent %s\n", __func__, parent->if_xname);
 			parent->if_flags |= IFF_UP;
-			parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
+			taskqueue_enqueue(taskqueue_swi, &ic->ic_parent_task);
+			return;
 		}
-		/*
-		 * Mark us running.  Note that we do this after
-		 * bringing up the parent device to avoid recursion.
-		 */
-		ifp->if_drv_flags |= IFF_DRV_RUNNING;	/* mark us running */
 	}
 	/*
 	 * If the parent is up and running, then kick the
@@ -1231,7 +1248,6 @@
 
 /*
  * Stop all vap's running on a device.
- * XXX not currently used
  */
 void
 ieee80211_stop_all(struct ieee80211com *ic)
@@ -1240,12 +1256,18 @@
 	struct ieee80211vap *vap;
 
 	IEEE80211_LOCK(ic);
+	/* XXX why do we do this? */
 	/* XXX shouldn't touch driver state */
 	parent->if_drv_flags &= ~IFF_DRV_RUNNING;
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
 		struct ifnet *ifp = vap->iv_ifp;
-		if (IFNET_IS_UP_RUNNING(ifp))	/* NB: avoid recursion */
+		if (IFNET_IS_UP_RUNNING(ifp)) {	/* NB: avoid recursion */
+			/*
+			 * NB: since parent is marked !RUNNING
+			 * this won't drop com lock
+			 */
 			ieee80211_stop_locked(vap);
+		}
 	}
 	IEEE80211_UNLOCK(ic);
 }

==== //depot/projects/vap/sys/net80211/ieee80211_var.h#39 (text+ko) ====

@@ -116,6 +116,7 @@
 	struct ifmedia		ic_media;	/* interface media config */
 	uint8_t			ic_myaddr[IEEE80211_ADDR_LEN];
 	struct callout		ic_inact;	/* inactivity processing */
+	struct task		ic_parent_task;	/* deferred parent processing */
 
 	uint32_t		ic_flags;	/* state flags */
 	uint32_t		ic_flags_ext;	/* extended state flags */


More information about the p4-projects mailing list