PERFORCE change 135700 for review
Sam Leffler
sam at FreeBSD.org
Tue Feb 19 04:57:47 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=135700
Change 135700 by sam at sam_ebb on 2008/02/19 04:56:47
Fixups to make multiple ap vaps work:
o allocate all the beacon buffers (not just 1!)
o fixup the state machine to to be multi-vap aware
o move newstate super call up so we have the bss node
setup before we do driver work that depends on it
o import fixups to set associd+bssid in newstate only when needed
While here add printfs to vap_create failure causes; may want to
move them to debug msgs eventually.
Affected files ...
.. //depot/projects/vap/sys/dev/ath/if_ath.c#25 edit
Differences ...
==== //depot/projects/vap/sys/dev/ath/if_ath.c#25 (text+ko) ====
@@ -738,8 +738,10 @@
/* XXX ic unlocked and race against add? */
switch (opmode) {
case IEEE80211_M_STA:
- if (sc->sc_nstavaps != 0) /* XXX only 1 sta for now */
+ if (sc->sc_nstavaps != 0) { /* XXX only 1 sta for now */
+ device_printf(sc->sc_dev, "only 1 sta vap supported\n");
return NULL;
+ }
if (sc->sc_nvaps) {
/*
* When there are multiple vaps we must fall
@@ -754,8 +756,11 @@
ic_opmode = opmode;
break;
case IEEE80211_M_IBSS:
- if (sc->sc_nvaps != 0) /* XXX only 1 for now */
+ if (sc->sc_nvaps != 0) { /* XXX only 1 for now */
+ device_printf(sc->sc_dev,
+ "only 1 ibss vap supported\n");
return NULL;
+ }
ic_opmode = opmode;
needbeacon = 1;
break;
@@ -772,8 +777,11 @@
needbeacon = 1;
/* fall thru... */
case IEEE80211_M_WDS:
- if (sc->sc_nvaps && ic->ic_opmode == IEEE80211_M_STA)
+ if (sc->sc_nvaps && ic->ic_opmode == IEEE80211_M_STA) {
+ device_printf(sc->sc_dev,
+ "wds not supported in sta mode\n");
return NULL;
+ }
if (opmode == IEEE80211_M_WDS) {
/*
* Silently remove any request for a unique
@@ -785,15 +793,20 @@
ic_opmode = IEEE80211_M_HOSTAP;
break;
default:
+ device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
- if (needbeacon & STAILQ_EMPTY(&sc->sc_bbuf))
+ if (needbeacon & STAILQ_EMPTY(&sc->sc_bbuf)) {
+ device_printf(sc->sc_dev, "no beacon buffer available\n");
return NULL;
+ }
avp = (struct ath_vap *) malloc(sizeof(struct ath_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
- if (avp == NULL)
+ if (avp == NULL) {
+ device_printf(sc->sc_dev, "unable to allocate memory\n");
return NULL;
+ }
if (opmode == IEEE80211_M_HOSTAP)
assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
@@ -3475,7 +3488,7 @@
}
error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
- "beacon", 1, 1);
+ "beacon", ATH_BCBUF, 1);
if (error != 0) {
ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
@@ -5397,6 +5410,22 @@
sc->sc_syncbeacon = 1;
}
+/*
+ * Walk the vap list and check if there any vap's in RUN state.
+ */
+static int
+ath_isanyrunningvaps(const struct ieee80211vap *this)
+{
+ const struct ieee80211com *ic = this->iv_ic;
+ const struct ieee80211vap *vap;
+
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ if (vap != this && vap->iv_state == IEEE80211_S_RUN)
+ return 1;
+ }
+ return 0;
+}
+
static int
ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
@@ -5404,8 +5433,8 @@
struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_vap *avp = ATH_VAP(vap);
struct ath_hal *ah = sc->sc_ah;
- struct ieee80211_node *ni;
- int i, error, stamode;
+ struct ieee80211_node *ni = NULL;
+ int i, error;
u_int32_t rfilt;
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
@@ -5427,40 +5456,41 @@
if (nstate == IEEE80211_S_INIT) {
/*
- * Shutdown host/driver operation:
+ * If there are no vaps left in RUN state then
+ * shutdown host/driver operation:
* o disable interrupts so we don't rx frames
* o clean any pending items on the task q
* o notify the rate control algorithm
*/
- sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
- ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
+ if (!ath_isanyrunningvaps(vap)) {
+ sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
+ /*
+ * Disable interrupts.
+ */
+ ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
+ sc->sc_beacons = 0;
#if 0
- /* XXX can't use taskqueue_drain 'cuz we're holding sc_mtx */
- taskqueue_drain(sc->sc_tq, &sc->sc_rxtask);
- taskqueue_drain(sc->sc_tq, &sc->sc_rxorntask);
- taskqueue_drain(sc->sc_tq, &sc->sc_bmisstask);
- taskqueue_drain(sc->sc_tq, &sc->sc_bstucktask);
+ /* XXX can't use taskqueue_drain 'cuz we're holding sc_mtx */
+ taskqueue_drain(sc->sc_tq, &sc->sc_rxtask);
+ taskqueue_drain(sc->sc_tq, &sc->sc_rxorntask);
+ taskqueue_drain(sc->sc_tq, &sc->sc_bmisstask);
+ taskqueue_drain(sc->sc_tq, &sc->sc_bstucktask);
#endif
+ }
ath_rate_newstate(vap, nstate);
- goto done;
+ return avp->av_newstate(vap, nstate, arg);
}
+
ni = vap->iv_bss;
-
rfilt = ath_calcrxfilter(sc);
- stamode = (sc->sc_opmode == HAL_M_STA || sc->sc_opmode == HAL_M_IBSS);
- if (stamode && nstate == IEEE80211_S_RUN) {
+ if (vap->iv_opmode == IEEE80211_M_STA && nstate == IEEE80211_S_RUN) {
sc->sc_curaid = ni->ni_associd;
IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid);
- } else
- sc->sc_curaid = 0;
-
+ ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
+ }
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
- __func__, rfilt, ether_sprintf(sc->sc_curbssid),
- sc->sc_curaid);
-
+ __func__, rfilt, ether_sprintf(sc->sc_curbssid), sc->sc_curaid);
ath_hal_setrxfilter(ah, rfilt);
- if (stamode)
- ath_hal_setassocid(ah, sc->sc_curbssid, ni->ni_associd);
if (vap->iv_opmode != IEEE80211_M_STA &&
(vap->iv_flags & IEEE80211_F_PRIVACY)) {
@@ -5468,23 +5498,26 @@
if (ath_hal_keyisvalid(ah, i))
ath_hal_keysetmac(ah, i, ni->ni_bssid);
}
-
/*
* Notify the rate control algorithm so rates
* are setup should ath_beacon_alloc be called.
*/
ath_rate_newstate(vap, nstate);
- if (nstate == IEEE80211_S_RUN) {
+ /*
+ * Invoke the parent method to do net80211 work.
+ */
+ error = avp->av_newstate(vap, nstate, arg);
+
+ if (error == 0 && nstate == IEEE80211_S_RUN) {
+ /* NB: collect bss node again, it may have changed */
+ ni = vap->iv_bss;
+
DPRINTF(sc, ATH_DEBUG_STATE,
- "%s(RUN): iv_flags=0x%08x iv=%d bssid=%s "
- "capinfo=0x%04x chan=%d\n"
- , __func__
- , vap->iv_flags
- , ni->ni_intval
- , ether_sprintf(ni->ni_bssid)
- , ni->ni_capinfo
- , ieee80211_chan2ieee(ic, ic->ic_curchan));
+ "%s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
+ "capinfo 0x%04x chan %d\n", __func__,
+ vap->iv_flags, ni->ni_intval, ether_sprintf(ni->ni_bssid),
+ ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
switch (vap->iv_opmode) {
case IEEE80211_M_HOSTAP:
@@ -5499,7 +5532,7 @@
* be called with beacon transmission active.
*/
ath_hal_stoptxdma(ah, sc->sc_bhalq);
- ath_beacon_free(sc);
+
error = ath_beacon_alloc(sc, ni);
if (error != 0)
goto bad;
@@ -5507,13 +5540,17 @@
* If joining an adhoc network defer beacon timer
* configuration to the next beacon frame so we
* have a current TSF to use. Otherwise we're
- * starting an ibss/bss so there's no need to delay.
+ * starting an ibss/bss so there's no need to delay;
+ * if this is the first vap moving to RUN state, then
+ * beacon state needs to be [re]configured.
*/
if (vap->iv_opmode == IEEE80211_M_IBSS &&
- vap->iv_bss->ni_tstamp.tsf != 0)
+ ni->ni_tstamp.tsf != 0) {
sc->sc_syncbeacon = 1;
- else
+ } else if (!sc->sc_beacons) {
ath_beacon_config(sc, vap);
+ sc->sc_beacons = 1;
+ }
break;
case IEEE80211_M_STA:
/*
@@ -5530,6 +5567,8 @@
*/
sc->sc_syncbeacon = 1;
break;
+ case IEEE80211_M_WDS:
+ break;
default:
break;
}
@@ -5544,24 +5583,19 @@
sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
+ /*
+ * Finally, start any timers.
+ */
+ if (sc->sc_calinterval != 0) {
+ /* start periodic recalibration timer */
+ callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
+ ath_calibrate, sc);
+ }
} else {
ath_hal_intrset(ah,
sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
}
-done:
- /*
- * Invoke the parent method to complete the work.
- */
- error = avp->av_newstate(vap, nstate, arg);
- /*
- * Finally, start any timers.
- */
- if (nstate == IEEE80211_S_RUN) {
- /* start periodic recalibration timer */
- callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
- ath_calibrate, sc);
- }
bad:
return error;
}
More information about the p4-projects
mailing list