diff options
author | bschmidt <bschmidt@FreeBSD.org> | 2011-02-09 18:09:27 +0000 |
---|---|---|
committer | bschmidt <bschmidt@FreeBSD.org> | 2011-02-09 18:09:27 +0000 |
commit | 598c1bd381d1ea8f9635b9f5abff942a9bdc251c (patch) | |
tree | 9deb326f4b025ca797aa57a1207eab65471dfeb0 | |
parent | 6887fd3d2c4a856e6b9c0d44617c072919980034 (diff) | |
download | FreeBSD-src-598c1bd381d1ea8f9635b9f5abff942a9bdc251c.zip FreeBSD-src-598c1bd381d1ea8f9635b9f5abff942a9bdc251c.tar.gz |
Rework beacon handling re-enable run_updateslot().
Drivers which rely on net80211 to create the beacon need to call
ieee80211_beacon_update() on iv_update_beacon() calls. This is required
that certain bits, e.g. TIM, get updated. A call to ieee80211_beacon_alloc()
is not enough because it does not care about flags which can only change
during runtime. By design a beacon is supposed to be allocated only once
while moving into RUN state.
To handle all possible calls to iv_update_beacon() the run_updateslot()
function has been revived and run_updateprot() has been added.
run_updateslot() handles slot time changes and run_updateprot() changes
to protection, both can change while nodes associate/leave.
Submitted by: Alexander Zagrebin <alex at zagrebin.ru>,
PseudoCylon <moonlightakkiy atyahoo.ca>
MFC after: 3 weeks
-rw-r--r-- | sys/dev/usb/wlan/if_run.c | 86 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_runvar.h | 1 |
2 files changed, 78 insertions, 9 deletions
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 211fa07..bd81643 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -388,6 +388,7 @@ static void run_scan_end(struct ieee80211com *); static void run_update_beacon(struct ieee80211vap *, int); static void run_update_beacon_cb(void *); static void run_updateprot(struct ieee80211com *); +static void run_updateprot_cb(void *); static void run_usb_timeout_cb(void *); static void run_reset_livelock(struct run_softc *); static void run_enable_tsf_sync(struct run_softc *); @@ -398,6 +399,7 @@ static void run_set_leds(struct run_softc *, uint16_t); static void run_set_bssid(struct run_softc *, const uint8_t *); static void run_set_macaddr(struct run_softc *, const uint8_t *); static void run_updateslot(struct ifnet *); +static void run_updateslot_cb(void *); static void run_update_mcast(struct ifnet *); static int8_t run_rssi2dbm(struct run_softc *, uint8_t, uint8_t); static void run_update_promisc_locked(struct ifnet *); @@ -674,7 +676,7 @@ run_attach(device_t self) ic->ic_set_channel = run_set_channel; ic->ic_node_alloc = run_node_alloc; ic->ic_newassoc = run_newassoc; - //ic->ic_updateslot = run_updateslot; + ic->ic_updateslot = run_updateslot; ic->ic_update_mcast = run_update_mcast; ic->ic_wme.wme_update = run_wme_update; ic->ic_raw_xmit = run_raw_xmit; @@ -856,6 +858,9 @@ run_vap_delete(struct ieee80211vap *vap) RUN_LOCK(sc); + m_freem(rvp->beacon_mbuf); + rvp->beacon_mbuf = NULL; + rvp_id = rvp->rvp_id; sc->ratectl_run &= ~(1 << rvp_id); sc->rvp_bmap &= ~(1 << rvp_id); @@ -1790,6 +1795,9 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->runbmap |= bid; } + m_freem(rvp->beacon_mbuf); + rvp->beacon_mbuf = NULL; + switch (vap->iv_opmode) { case IEEE80211_M_HOSTAP: case IEEE80211_M_MBSS: @@ -3901,8 +3909,29 @@ run_update_beacon(struct ieee80211vap *vap, int item) { struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_vap *rvp = RUN_VAP(vap); + int mcast = 0; uint32_t i; + KASSERT(vap != NULL, ("no beacon")); + + switch (item) { + case IEEE80211_BEACON_ERP: + run_updateslot(ic->ic_ifp); + break; + case IEEE80211_BEACON_HTINFO: + run_updateprot(ic); + break; + case IEEE80211_BEACON_TIM: + mcast = 1; /*TODO*/ + break; + default: + break; + } + + setbit(rvp->bo.bo_flags, item); + ieee80211_beacon_update(vap->iv_bss, &rvp->bo, rvp->beacon_mbuf, mcast); + i = RUN_CMDQ_GET(&sc->cmdq_store); DPRINTF("cmdq_store=%d\n", i); sc->cmdq[i].func = run_update_beacon_cb; @@ -3916,6 +3945,7 @@ static void run_update_beacon_cb(void *arg) { struct ieee80211vap *vap = arg; + struct run_vap *rvp = RUN_VAP(vap); struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; struct rt2860_txwi txwi; @@ -3925,8 +3955,17 @@ run_update_beacon_cb(void *arg) if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) return; - if ((m = ieee80211_beacon_alloc(vap->iv_bss, &RUN_VAP(vap)->bo)) == NULL) - return; + /* + * No need to call ieee80211_beacon_update(), run_update_beacon() + * is taking care of apropriate calls. + */ + if (rvp->beacon_mbuf == NULL) { + rvp->beacon_mbuf = ieee80211_beacon_alloc(vap->iv_bss, + &rvp->bo); + if (rvp->beacon_mbuf == NULL) + return; + } + m = rvp->beacon_mbuf; memset(&txwi, 0, sizeof txwi); txwi.wcid = 0xff; @@ -3941,13 +3980,11 @@ run_update_beacon_cb(void *arg) txwi.flags = RT2860_TX_TS; txwi.xflags = RT2860_TX_NSEQ; - run_write_region_1(sc, RT2860_BCN_BASE(RUN_VAP(vap)->rvp_id), + run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id), (uint8_t *)&txwi, sizeof txwi); - run_write_region_1(sc, RT2860_BCN_BASE(RUN_VAP(vap)->rvp_id) + sizeof txwi, + run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + sizeof txwi, mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1); /* roundup len */ - m_freem(m); - return; } @@ -3955,6 +3992,20 @@ static void run_updateprot(struct ieee80211com *ic) { struct run_softc *sc = ic->ic_ifp->if_softc; + uint32_t i; + + i = RUN_CMDQ_GET(&sc->cmdq_store); + DPRINTF("cmdq_store=%d\n", i); + sc->cmdq[i].func = run_updateprot_cb; + sc->cmdq[i].arg0 = ic; + ieee80211_runtask(ic, &sc->cmdq_task); +} + +static void +run_updateprot_cb(void *arg) +{ + struct ieee80211com *ic = arg; + struct run_softc *sc = ic->ic_ifp->if_softc; uint32_t tmp; tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; @@ -4164,12 +4215,29 @@ run_set_macaddr(struct run_softc *sc, const uint8_t *addr) addr[4] | addr[5] << 8 | 0xff << 16); } -/* ARGSUSED */ static void run_updateslot(struct ifnet *ifp) { struct run_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; + uint32_t i; + + i = RUN_CMDQ_GET(&sc->cmdq_store); + DPRINTF("cmdq_store=%d\n", i); + sc->cmdq[i].func = run_updateslot_cb; + sc->cmdq[i].arg0 = ifp; + ieee80211_runtask(ic, &sc->cmdq_task); + + return; +} + +/* ARGSUSED */ +static void +run_updateslot_cb(void *arg) +{ + struct ifnet *ifp = arg; + struct run_softc *sc = ifp->if_softc; + struct ieee80211com *ic = ifp->if_l2com; uint32_t tmp; run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp); @@ -4747,7 +4815,7 @@ run_init_locked(struct run_softc *sc) run_set_chan(sc, ic->ic_curchan); /* setup initial protection mode */ - run_updateprot(ic); + run_updateprot_cb(ic); /* turn radio LED on */ run_set_leds(sc, RT2860_LED_RADIO); diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index df4f25c..b558bce 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -121,6 +121,7 @@ struct run_cmdq { struct run_vap { struct ieee80211vap vap; struct ieee80211_beacon_offsets bo; + struct mbuf *beacon_mbuf; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); |