PERFORCE change 137801 for review

Sam Leffler sam at FreeBSD.org
Sat Mar 15 21:00:16 UTC 2008


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

Change 137801 by sam at sam_ebb on 2008/03/15 20:59:48

	checkpoint temporary hack to split post state change work
	into a callback; going to explore a better solution next

Affected files ...

.. //depot/projects/vap/sys/dev/usb/if_rum.c#10 edit
.. //depot/projects/vap/sys/dev/usb/if_ural.c#12 edit
.. //depot/projects/vap/sys/dev/usb/if_zyd.c#11 edit
.. //depot/projects/vap/sys/dev/wpi/if_wpi.c#11 edit
.. //depot/projects/vap/sys/net80211/ieee80211_proto.c#24 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#32 edit

Differences ...

==== //depot/projects/vap/sys/dev/usb/if_rum.c#10 (text+ko) ====

@@ -801,13 +801,10 @@
 
 	RUM_UNLOCK(sc);
 
-	IEEE80211_LOCK(ic);	/*XXX*/
+	IEEE80211_LOCK(ic);
 	rvp->newstate(vap, sc->sc_state, sc->sc_arg);
-	if (sc->sc_state == IEEE80211_S_RUN) {
-		/* XXX compensate for deferred handling of newstate */
-		vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		if_start(vap->iv_ifp);
-	}
+	if (vap->iv_newstate_cb != NULL)
+		vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
 	IEEE80211_UNLOCK(ic);
 }
 
@@ -825,11 +822,13 @@
 	sc->sc_arg = arg;
 
 	usb_rem_task(sc->sc_udev, &sc->sc_task);
-	if (nstate == IEEE80211_S_INIT)
+	if (nstate == IEEE80211_S_INIT) {
 		rvp->newstate(vap, nstate, arg);
-	else
+		return 0;
+	} else {
 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
-	return 0;
+		return EINPROGRESS;
+	}
 }
 
 /* quickly determine if a given rate is CCK or OFDM */

==== //depot/projects/vap/sys/dev/usb/if_ural.c#12 (text+ko) ====

@@ -808,13 +808,10 @@
 
 	RAL_UNLOCK(sc);
 
-	IEEE80211_LOCK(ic);	/*XXX*/
+	IEEE80211_LOCK(ic);
 	uvp->newstate(vap, sc->sc_state, sc->sc_arg);
-	if (sc->sc_state == IEEE80211_S_RUN) {
-		/* XXX compensate for deferred handling of newstate */
-		vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		if_start(vap->iv_ifp);
-	}
+	if (vap->iv_newstate_cb != NULL)
+		vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
 	IEEE80211_UNLOCK(ic);
 }
 
@@ -857,11 +854,13 @@
 	sc->sc_arg = arg;
 
 	usb_rem_task(sc->sc_udev, &sc->sc_task);
-	if (nstate == IEEE80211_S_INIT)
+	if (nstate == IEEE80211_S_INIT) {
 		uvp->newstate(vap, nstate, arg);
-	else
+		return 0;
+	} else {
 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
-	return 0;
+		return EINPROGRESS;
+	}
 }
 
 /* quickly determine if a given rate is CCK or OFDM */

==== //depot/projects/vap/sys/dev/usb/if_zyd.c#11 (text+ko) ====

@@ -708,9 +708,6 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
 	struct zyd_vap *zvp = ZYD_VAP(vap);
-	enum ieee80211_state ostate;
-
-	ostate = vap->iv_state;
 
 	switch (sc->sc_state) {
 	case IEEE80211_S_RUN:
@@ -740,13 +737,10 @@
 		break;
 	}
 
-	IEEE80211_LOCK(ic);	/*XXX*/
+	IEEE80211_LOCK(ic);
 	zvp->newstate(vap, sc->sc_state, sc->sc_arg);
-	if (sc->sc_state == IEEE80211_S_RUN) {
-		/* XXX compensate for deferred handling of newstate */
-		vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		if_start(vap->iv_ifp);
-	}
+	if (vap->iv_newstate_cb != NULL)
+		vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
 	IEEE80211_UNLOCK(ic);
 }
 
@@ -763,12 +757,13 @@
 	sc->sc_state = nstate;
 	sc->sc_arg = arg;
 
-	if (nstate == IEEE80211_S_INIT)
+	if (nstate == IEEE80211_S_INIT) {
 		zvp->newstate(vap, nstate, arg);
-	else
+		return 0;
+	} else {
 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
-
-	return 0;
+		return EINPROGRESS;
+	}
 }
 
 static int

==== //depot/projects/vap/sys/dev/wpi/if_wpi.c#11 (text+ko) ====

@@ -1256,6 +1256,7 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	struct wpi_softc *sc = ifp->if_softc;
+	int error;
 
 	DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
 		ieee80211_state_name[vap->iv_state],
@@ -1265,11 +1266,13 @@
 
 	if (nstate == IEEE80211_S_AUTH) {
 		/* Delay the auth transition until we can update the firmware */
-		return wpi_queue_cmd(sc, WPI_AUTH, arg, WPI_QUEUE_NORMAL);
+		error = wpi_queue_cmd(sc, WPI_AUTH, arg, WPI_QUEUE_NORMAL);
+		return (error != 0 ? error : EINPROGRESS);
 	}
 	if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
 		/* set the association id first */
-		return wpi_queue_cmd(sc, WPI_RUN, arg, WPI_QUEUE_NORMAL);
+		error = wpi_queue_cmd(sc, WPI_RUN, arg, WPI_QUEUE_NORMAL);
+		return (error != 0 ? error : EINPROGRESS);
 	}
 	if (nstate == IEEE80211_S_RUN) {
 		/* RUN -> RUN transition; just restart the timers */
@@ -3580,28 +3583,35 @@
 	case WPI_AUTH:
 		/* The node must be registered in the firmware before auth */
 		error = wpi_auth(sc, vap);
+		WPI_UNLOCK(sc);
 		if (error != 0) {
 			device_printf(sc->sc_dev,
 			    "%s: could not move to auth state, error %d\n",
 			    __func__, error);
-			WPI_UNLOCK(sc);
 			return;
 		}
-		/* Send the auth frame now */
+		IEEE80211_LOCK(ic);
 		WPI_VAP(vap)->newstate(vap, IEEE80211_S_AUTH, arg);
-		break;
+		if (vap->iv_newstate_cb != NULL)
+			vap->iv_newstate_cb(vap, IEEE80211_S_AUTH, arg);
+		IEEE80211_UNLOCK(ic);
+		goto again;
 
 	case WPI_RUN:
 		error = wpi_run(sc, vap);
+		WPI_UNLOCK(sc);
 		if (error != 0) {
 			device_printf(sc->sc_dev,
 			    "%s: could not move to run state, error %d\n",
 			    __func__, error);
-			WPI_UNLOCK(sc);
 			return;
 		}
+		IEEE80211_LOCK(ic);
 		WPI_VAP(vap)->newstate(vap, IEEE80211_S_RUN, arg);
-		break;
+		if (vap->iv_newstate_cb != NULL)
+			vap->iv_newstate_cb(vap, IEEE80211_S_RUN, arg);
+		IEEE80211_UNLOCK(ic);
+		goto again;
 	}
 	WPI_UNLOCK(sc);
 

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

@@ -1473,6 +1473,53 @@
 }
 
 /*
+ * Handle post state change work common to all operating modes.
+ */
+static void
+ieee80211_newstate_cb(struct ieee80211vap *vap, 
+	enum ieee80211_state nstate, int arg)
+{
+	struct ieee80211com *ic = vap->iv_ic;
+
+	IEEE80211_LOCK_ASSERT(ic);
+
+	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
+	    "%s: %s arg %d\n", __func__, ieee80211_state_name[nstate], arg);
+
+	if (nstate == IEEE80211_S_RUN) {
+		/*
+		 * OACTIVE may be set on the vap if the upper layer
+		 * tried to transmit (e.g. IPv6 NDP) before we reach
+		 * RUN state.  Clear it and restart xmit.
+		 *
+		 * Note this can also happen as a result of SLEEP->RUN
+		 * (i.e. coming out of power save mode).
+		 */
+		vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		if_start(vap->iv_ifp);
+
+		/* bring up any vaps waiting on us */
+		wakeupwaiting(vap);
+	} else if (nstate == IEEE80211_S_INIT) {
+		/*
+		 * Flush the scan cache if we did the last scan (XXX?)
+		 * and flush any frames on send queues from this vap.
+		 * Note the mgt q is used only for legacy drivers and
+		 * will go away shortly.
+		 */
+		ieee80211_scan_flush(vap);
+
+		/* XXX can skip this if not using ic_mgtq */
+		/* flush any frames for this vap in the shared q's */
+		ieee80211_flush_ifq(&ic->ic_mgtq, vap);
+		/* XXX NB: cast for altq */
+		ieee80211_flush_ifq((struct ifqueue *)
+		    &ic->ic_ifp->if_snd, vap);
+	}
+	vap->iv_newstate_cb = NULL;
+}
+
+/*
  * Public interface for initiating a state machine change.
  * This routine single-threads the request and coordinates
  * the scheduling of multiple vaps for the purpose of selecting
@@ -1624,29 +1671,18 @@
 	default:
 		break;
 	}
-	rc = vap->iv_newstate(vap, nstate, arg);
 	/* XXX on transition RUN->CAC do we need to set nstate = iv_state? */
 	if (ostate != nstate) {
 		/*
-		 * Handle work common to all operating modes.
+		 * Arrange for work to happen after state change completes.
+		 * If this happens asynchronously the caller must arrange
+		 * for the com lock to be held.
 		 */
-		if (nstate == IEEE80211_S_RUN) {
-			vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-			if_start(vap->iv_ifp);
-
-			/* bring up any vaps waiting on us */
-			wakeupwaiting(vap);
-		} else if (nstate == IEEE80211_S_INIT) {
-			ieee80211_scan_flush(vap);
-
-			/* XXX can skip this if not using ic_mgtq */
-			/* flush any frames for this vap in the shared q's */
-			ieee80211_flush_ifq(&ic->ic_mgtq, vap);
-			/* XXX NB: cast for altq */
-			ieee80211_flush_ifq((struct ifqueue *)
-			    &ic->ic_ifp->if_snd, vap);
-		}
+		vap->iv_newstate_cb = ieee80211_newstate_cb;
 	}
+	rc = vap->iv_newstate(vap, nstate, arg);
+	if (rc == 0)
+		vap->iv_newstate_cb(vap, nstate, arg);
 done:
 	return rc;
 }

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

@@ -293,6 +293,8 @@
 	uint32_t		iv_htcaps;	/* HT capabilities */
 	enum ieee80211_opmode	iv_opmode;	/* operation mode */
 	enum ieee80211_state	iv_state;	/* state machine state */
+	void			(*iv_newstate_cb)(struct ieee80211vap *,
+				    enum ieee80211_state, int);
 	struct callout		iv_mgtsend;	/* mgmt frame response timer */
 						/* inactivity timer settings */
 	int			iv_inact_init;	/* setting for new station */


More information about the p4-projects mailing list