Author: bschmidt
Date: Wed Feb  9 18:09:27 2011
New Revision: 218492
URL: http://svn.freebsd.org/changeset/base/218492

Log:
  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

Modified:
  head/sys/dev/usb/wlan/if_run.c
  head/sys/dev/usb/wlan/if_runvar.h

Modified: head/sys/dev/usb/wlan/if_run.c
==============================================================================
--- head/sys/dev/usb/wlan/if_run.c      Wed Feb  9 16:41:06 2011        
(r218491)
+++ head/sys/dev/usb/wlan/if_run.c      Wed Feb  9 18:09:27 2011        
(r218492)
@@ -388,6 +388,7 @@ static void run_scan_end(struct ieee8021
 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_soft
 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, e
                        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 *v
 {
        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, co
            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);

Modified: head/sys/dev/usb/wlan/if_runvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runvar.h   Wed Feb  9 16:41:06 2011        
(r218491)
+++ head/sys/dev/usb/wlan/if_runvar.h   Wed Feb  9 18:09:27 2011        
(r218492)
@@ -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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to