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