The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/if_ath_beacon.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer,
   12  *    without modification.
   13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   14  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   15  *    redistribution must be conditioned upon including a substantially
   16  *    similar Disclaimer requirement for further binary redistribution.
   17  *
   18  * NO WARRANTY
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   21  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   22  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   23  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   24  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   27  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   29  * THE POSSIBILITY OF SUCH DAMAGES.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 /*
   36  * Driver for the Atheros Wireless LAN controller.
   37  *
   38  * This software is derived from work of Atsushi Onoe; his contribution
   39  * is greatly appreciated.
   40  */
   41 
   42 #include "opt_inet.h"
   43 #include "opt_ath.h"
   44 /*
   45  * This is needed for register operations which are performed
   46  * by the driver - eg, calls to ath_hal_gettsf32().
   47  *
   48  * It's also required for any AH_DEBUG checks in here, eg the
   49  * module dependencies.
   50  */
   51 #include "opt_ah.h"
   52 #include "opt_wlan.h"
   53 
   54 #include <sys/param.h>
   55 #include <sys/systm.h>
   56 #include <sys/sysctl.h>
   57 #include <sys/mbuf.h>
   58 #include <sys/malloc.h>
   59 #include <sys/lock.h>
   60 #include <sys/mutex.h>
   61 #include <sys/kernel.h>
   62 #include <sys/socket.h>
   63 #include <sys/sockio.h>
   64 #include <sys/errno.h>
   65 #include <sys/callout.h>
   66 #include <sys/bus.h>
   67 #include <sys/endian.h>
   68 #include <sys/kthread.h>
   69 #include <sys/taskqueue.h>
   70 #include <sys/priv.h>
   71 #include <sys/module.h>
   72 #include <sys/ktr.h>
   73 #include <sys/smp.h>    /* for mp_ncpus */
   74 
   75 #include <machine/bus.h>
   76 
   77 #include <net/if.h>
   78 #include <net/if_var.h>
   79 #include <net/if_dl.h>
   80 #include <net/if_media.h>
   81 #include <net/if_types.h>
   82 #include <net/if_arp.h>
   83 #include <net/ethernet.h>
   84 #include <net/if_llc.h>
   85 
   86 #include <net80211/ieee80211_var.h>
   87 #include <net80211/ieee80211_regdomain.h>
   88 #ifdef IEEE80211_SUPPORT_SUPERG
   89 #include <net80211/ieee80211_superg.h>
   90 #endif
   91 
   92 #include <net/bpf.h>
   93 
   94 #ifdef INET
   95 #include <netinet/in.h>
   96 #include <netinet/if_ether.h>
   97 #endif
   98 
   99 #include <dev/ath/if_athvar.h>
  100 
  101 #include <dev/ath/if_ath_debug.h>
  102 #include <dev/ath/if_ath_misc.h>
  103 #include <dev/ath/if_ath_tx.h>
  104 #include <dev/ath/if_ath_beacon.h>
  105 
  106 #ifdef ATH_TX99_DIAG
  107 #include <dev/ath/ath_tx99/ath_tx99.h>
  108 #endif
  109 
  110 /*
  111  * Setup a h/w transmit queue for beacons.
  112  */
  113 int
  114 ath_beaconq_setup(struct ath_softc *sc)
  115 {
  116         struct ath_hal *ah = sc->sc_ah;
  117         HAL_TXQ_INFO qi;
  118 
  119         memset(&qi, 0, sizeof(qi));
  120         qi.tqi_aifs = HAL_TXQ_USEDEFAULT;
  121         qi.tqi_cwmin = HAL_TXQ_USEDEFAULT;
  122         qi.tqi_cwmax = HAL_TXQ_USEDEFAULT;
  123         /* NB: for dynamic turbo, don't enable any other interrupts */
  124         qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE;
  125         if (sc->sc_isedma)
  126                 qi.tqi_qflags |= HAL_TXQ_TXOKINT_ENABLE |
  127                     HAL_TXQ_TXERRINT_ENABLE;
  128 
  129         return ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi);
  130 }
  131 
  132 /*
  133  * Setup the transmit queue parameters for the beacon queue.
  134  */
  135 int
  136 ath_beaconq_config(struct ath_softc *sc)
  137 {
  138 #define ATH_EXPONENT_TO_VALUE(v)        ((1<<(v))-1)
  139         struct ieee80211com *ic = &sc->sc_ic;
  140         struct ath_hal *ah = sc->sc_ah;
  141         HAL_TXQ_INFO qi;
  142 
  143         ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi);
  144         if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
  145             ic->ic_opmode == IEEE80211_M_MBSS) {
  146                 /*
  147                  * Always burst out beacon and CAB traffic.
  148                  */
  149                 qi.tqi_aifs = ATH_BEACON_AIFS_DEFAULT;
  150                 qi.tqi_cwmin = ATH_BEACON_CWMIN_DEFAULT;
  151                 qi.tqi_cwmax = ATH_BEACON_CWMAX_DEFAULT;
  152         } else {
  153                 struct chanAccParams chp;
  154                 struct wmeParams *wmep;
  155 
  156                 ieee80211_wme_ic_getparams(ic, &chp);
  157                 wmep = &chp.cap_wmeParams[WME_AC_BE];
  158 
  159                 /*
  160                  * Adhoc mode; important thing is to use 2x cwmin.
  161                  */
  162                 qi.tqi_aifs = wmep->wmep_aifsn;
  163                 qi.tqi_cwmin = 2*ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
  164                 qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
  165         }
  166 
  167         if (!ath_hal_settxqueueprops(ah, sc->sc_bhalq, &qi)) {
  168                 device_printf(sc->sc_dev, "unable to update parameters for "
  169                         "beacon hardware queue!\n");
  170                 return 0;
  171         } else {
  172                 ath_hal_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */
  173                 return 1;
  174         }
  175 #undef ATH_EXPONENT_TO_VALUE
  176 }
  177 
  178 /*
  179  * Allocate and setup an initial beacon frame.
  180  */
  181 int
  182 ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
  183 {
  184         struct ieee80211vap *vap = ni->ni_vap;
  185         struct ath_vap *avp = ATH_VAP(vap);
  186         struct ath_buf *bf;
  187         struct mbuf *m;
  188         int error;
  189 
  190         bf = avp->av_bcbuf;
  191         DPRINTF(sc, ATH_DEBUG_NODE, "%s: bf_m=%p, bf_node=%p\n",
  192             __func__, bf->bf_m, bf->bf_node);
  193         if (bf->bf_m != NULL) {
  194                 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
  195                 m_freem(bf->bf_m);
  196                 bf->bf_m = NULL;
  197         }
  198         if (bf->bf_node != NULL) {
  199                 ieee80211_free_node(bf->bf_node);
  200                 bf->bf_node = NULL;
  201         }
  202 
  203         /*
  204          * NB: the beacon data buffer must be 32-bit aligned;
  205          * we assume the mbuf routines will return us something
  206          * with this alignment (perhaps should assert).
  207          */
  208         m = ieee80211_beacon_alloc(ni);
  209         if (m == NULL) {
  210                 device_printf(sc->sc_dev, "%s: cannot get mbuf\n", __func__);
  211                 sc->sc_stats.ast_be_nombuf++;
  212                 return ENOMEM;
  213         }
  214         error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
  215                                      bf->bf_segs, &bf->bf_nseg,
  216                                      BUS_DMA_NOWAIT);
  217         if (error != 0) {
  218                 device_printf(sc->sc_dev,
  219                     "%s: cannot map mbuf, bus_dmamap_load_mbuf_sg returns %d\n",
  220                     __func__, error);
  221                 m_freem(m);
  222                 return error;
  223         }
  224 
  225         /*
  226          * Calculate a TSF adjustment factor required for staggered
  227          * beacons.  Note that we assume the format of the beacon
  228          * frame leaves the tstamp field immediately following the
  229          * header.
  230          */
  231         if (sc->sc_stagbeacons && avp->av_bslot > 0) {
  232                 uint64_t tsfadjust;
  233                 struct ieee80211_frame *wh;
  234 
  235                 /*
  236                  * The beacon interval is in TU's; the TSF is in usecs.
  237                  * We figure out how many TU's to add to align the timestamp
  238                  * then convert to TSF units and handle byte swapping before
  239                  * inserting it in the frame.  The hardware will then add this
  240                  * each time a beacon frame is sent.  Note that we align vap's
  241                  * 1..N and leave vap 0 untouched.  This means vap 0 has a
  242                  * timestamp in one beacon interval while the others get a
  243                  * timstamp aligned to the next interval.
  244                  */
  245                 tsfadjust = ni->ni_intval *
  246                     (ATH_BCBUF - avp->av_bslot) / ATH_BCBUF;
  247                 tsfadjust = htole64(tsfadjust << 10);   /* TU -> TSF */
  248 
  249                 DPRINTF(sc, ATH_DEBUG_BEACON,
  250                     "%s: %s beacons bslot %d intval %u tsfadjust %llu\n",
  251                     __func__, sc->sc_stagbeacons ? "stagger" : "burst",
  252                     avp->av_bslot, ni->ni_intval,
  253                     (long long unsigned) le64toh(tsfadjust));
  254 
  255                 wh = mtod(m, struct ieee80211_frame *);
  256                 memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust));
  257         }
  258         bf->bf_m = m;
  259         bf->bf_node = ieee80211_ref_node(ni);
  260 
  261         return 0;
  262 }
  263 
  264 /*
  265  * Setup the beacon frame for transmit.
  266  */
  267 static void
  268 ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
  269 {
  270 #define USE_SHPREAMBLE(_ic) \
  271         (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
  272                 == IEEE80211_F_SHPREAMBLE)
  273         struct ieee80211_node *ni = bf->bf_node;
  274         struct ieee80211com *ic = ni->ni_ic;
  275         struct mbuf *m = bf->bf_m;
  276         struct ath_hal *ah = sc->sc_ah;
  277         struct ath_desc *ds;
  278         int flags, antenna;
  279         const HAL_RATE_TABLE *rt;
  280         u_int8_t rix, rate;
  281         HAL_DMA_ADDR bufAddrList[4];
  282         uint32_t segLenList[4];
  283         HAL_11N_RATE_SERIES rc[4];
  284 
  285         DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: m %p len %u\n",
  286                 __func__, m, m->m_len);
  287 
  288         /* setup descriptors */
  289         ds = bf->bf_desc;
  290         bf->bf_last = bf;
  291         bf->bf_lastds = ds;
  292 
  293         flags = HAL_TXDESC_NOACK;
  294         if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
  295                 /* self-linked descriptor */
  296                 ath_hal_settxdesclink(sc->sc_ah, ds, bf->bf_daddr);
  297                 flags |= HAL_TXDESC_VEOL;
  298                 /*
  299                  * Let hardware handle antenna switching.
  300                  */
  301                 antenna = sc->sc_txantenna;
  302         } else {
  303                 ath_hal_settxdesclink(sc->sc_ah, ds, 0);
  304                 /*
  305                  * Switch antenna every 4 beacons.
  306                  * XXX assumes two antenna
  307                  */
  308                 if (sc->sc_txantenna != 0)
  309                         antenna = sc->sc_txantenna;
  310                 else if (sc->sc_stagbeacons && sc->sc_nbcnvaps != 0)
  311                         antenna = ((sc->sc_stats.ast_be_xmit / sc->sc_nbcnvaps) & 4 ? 2 : 1);
  312                 else
  313                         antenna = (sc->sc_stats.ast_be_xmit & 4 ? 2 : 1);
  314         }
  315 
  316         KASSERT(bf->bf_nseg == 1,
  317                 ("multi-segment beacon frame; nseg %u", bf->bf_nseg));
  318 
  319         /*
  320          * Calculate rate code.
  321          * XXX everything at min xmit rate
  322          */
  323         rix = 0;
  324         rt = sc->sc_currates;
  325         rate = rt->info[rix].rateCode;
  326         if (USE_SHPREAMBLE(ic))
  327                 rate |= rt->info[rix].shortPreamble;
  328         ath_hal_setuptxdesc(ah, ds
  329                 , m->m_len + IEEE80211_CRC_LEN  /* frame length */
  330                 , sizeof(struct ieee80211_frame)/* header length */
  331                 , HAL_PKT_TYPE_BEACON           /* Atheros packet type */
  332                 , ieee80211_get_node_txpower(ni)        /* txpower XXX */
  333                 , rate, 1                       /* series 0 rate/tries */
  334                 , HAL_TXKEYIX_INVALID           /* no encryption */
  335                 , antenna                       /* antenna mode */
  336                 , flags                         /* no ack, veol for beacons */
  337                 , 0                             /* rts/cts rate */
  338                 , 0                             /* rts/cts duration */
  339         );
  340 
  341         /*
  342          * The EDMA HAL currently assumes that _all_ rate control
  343          * settings are done in ath_hal_set11nratescenario(), rather
  344          * than in ath_hal_setuptxdesc().
  345          */
  346         if (sc->sc_isedma) {
  347                 memset(&rc, 0, sizeof(rc));
  348 
  349                 rc[0].ChSel = sc->sc_txchainmask;
  350                 rc[0].Tries = 1;
  351                 rc[0].Rate = rt->info[rix].rateCode;
  352                 rc[0].RateIndex = rix;
  353                 rc[0].tx_power_cap = 0x3f;
  354                 rc[0].PktDuration =
  355                     ath_hal_computetxtime(ah, rt, roundup(m->m_len, 4),
  356                         rix, 0, AH_TRUE);
  357                 ath_hal_set11nratescenario(ah, ds, 0, 0, rc, 4, flags);
  358         }
  359 
  360         /* NB: beacon's BufLen must be a multiple of 4 bytes */
  361         segLenList[0] = roundup(m->m_len, 4);
  362         segLenList[1] = segLenList[2] = segLenList[3] = 0;
  363         bufAddrList[0] = bf->bf_segs[0].ds_addr;
  364         bufAddrList[1] = bufAddrList[2] = bufAddrList[3] = 0;
  365         ath_hal_filltxdesc(ah, ds
  366                 , bufAddrList
  367                 , segLenList
  368                 , 0                             /* XXX desc id */
  369                 , sc->sc_bhalq                  /* hardware TXQ */
  370                 , AH_TRUE                       /* first segment */
  371                 , AH_TRUE                       /* last segment */
  372                 , ds                            /* first descriptor */
  373         );
  374 #if 0
  375         ath_desc_swap(ds);
  376 #endif
  377 #undef USE_SHPREAMBLE
  378 }
  379 
  380 void
  381 ath_beacon_update(struct ieee80211vap *vap, int item)
  382 {
  383         struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
  384 
  385         setbit(bo->bo_flags, item);
  386 }
  387 
  388 /*
  389  * Handle a beacon miss.
  390  */
  391 void
  392 ath_beacon_miss(struct ath_softc *sc)
  393 {
  394         HAL_SURVEY_SAMPLE hs;
  395         HAL_BOOL ret;
  396         uint32_t hangs;
  397 
  398         bzero(&hs, sizeof(hs));
  399 
  400         ret = ath_hal_get_mib_cycle_counts(sc->sc_ah, &hs);
  401 
  402         if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) && hangs != 0) {
  403                 DPRINTF(sc, ATH_DEBUG_BEACON,
  404                     "%s: hang=0x%08x\n",
  405                     __func__,
  406                     hangs);
  407         }
  408 
  409 #ifdef  ATH_DEBUG_ALQ
  410         if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_MISSED_BEACON))
  411                 if_ath_alq_post(&sc->sc_alq, ATH_ALQ_MISSED_BEACON, 0, NULL);
  412 #endif
  413 
  414         DPRINTF(sc, ATH_DEBUG_BEACON,
  415             "%s: valid=%d, txbusy=%u, rxbusy=%u, chanbusy=%u, "
  416             "extchanbusy=%u, cyclecount=%u\n",
  417             __func__,
  418             ret,
  419             hs.tx_busy,
  420             hs.rx_busy,
  421             hs.chan_busy,
  422             hs.ext_chan_busy,
  423             hs.cycle_count);
  424 }
  425 
  426 /*
  427  * Transmit a beacon frame at SWBA.  Dynamic updates to the
  428  * frame contents are done as needed and the slot time is
  429  * also adjusted based on current state.
  430  */
  431 void
  432 ath_beacon_proc(void *arg, int pending)
  433 {
  434         struct ath_softc *sc = arg;
  435         struct ath_hal *ah = sc->sc_ah;
  436         struct ieee80211vap *vap;
  437         struct ath_buf *bf;
  438         int slot, otherant;
  439         uint32_t bfaddr;
  440 
  441         DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: pending %u\n",
  442                 __func__, pending);
  443         /*
  444          * Check if the previous beacon has gone out.  If
  445          * not don't try to post another, skip this period
  446          * and wait for the next.  Missed beacons indicate
  447          * a problem and should not occur.  If we miss too
  448          * many consecutive beacons reset the device.
  449          */
  450         if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) {
  451 
  452                 sc->sc_bmisscount++;
  453                 sc->sc_stats.ast_be_missed++;
  454                 ath_beacon_miss(sc);
  455 
  456                 DPRINTF(sc, ATH_DEBUG_BEACON,
  457                         "%s: missed %u consecutive beacons\n",
  458                         __func__, sc->sc_bmisscount);
  459                 if (sc->sc_bmisscount >= ath_bstuck_threshold)
  460                         taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask);
  461                 return;
  462         }
  463         if (sc->sc_bmisscount != 0) {
  464                 DPRINTF(sc, ATH_DEBUG_BEACON,
  465                         "%s: resume beacon xmit after %u misses\n",
  466                         __func__, sc->sc_bmisscount);
  467                 sc->sc_bmisscount = 0;
  468 #ifdef  ATH_DEBUG_ALQ
  469                 if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_RESUME_BEACON))
  470                         if_ath_alq_post(&sc->sc_alq, ATH_ALQ_RESUME_BEACON, 0, NULL);
  471 #endif
  472         }
  473 
  474         if (sc->sc_stagbeacons) {                       /* staggered beacons */
  475                 struct ieee80211com *ic = &sc->sc_ic;
  476                 uint32_t tsftu;
  477 
  478                 tsftu = ath_hal_gettsf32(ah) >> 10;
  479                 /* XXX lintval */
  480                 slot = ((tsftu % ic->ic_lintval) * ATH_BCBUF) / ic->ic_lintval;
  481                 vap = sc->sc_bslot[(slot+1) % ATH_BCBUF];
  482                 bfaddr = 0;
  483                 if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) {
  484                         bf = ath_beacon_generate(sc, vap);
  485                         if (bf != NULL)
  486                                 bfaddr = bf->bf_daddr;
  487                 }
  488         } else {                                        /* burst'd beacons */
  489                 uint32_t *bflink = &bfaddr;
  490 
  491                 for (slot = 0; slot < ATH_BCBUF; slot++) {
  492                         vap = sc->sc_bslot[slot];
  493                         if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) {
  494                                 bf = ath_beacon_generate(sc, vap);
  495                                 /*
  496                                  * XXX TODO: this should use settxdesclinkptr()
  497                                  * otherwise it won't work for EDMA chipsets!
  498                                  */
  499                                 if (bf != NULL) {
  500                                         /* XXX should do this using the ds */
  501                                         *bflink = bf->bf_daddr;
  502                                         ath_hal_gettxdesclinkptr(sc->sc_ah,
  503                                             bf->bf_desc, &bflink);
  504                                 }
  505                         }
  506                 }
  507                 /*
  508                  * XXX TODO: this should use settxdesclinkptr()
  509                  * otherwise it won't work for EDMA chipsets!
  510                  */
  511                 *bflink = 0;                            /* terminate list */
  512         }
  513 
  514         /*
  515          * Handle slot time change when a non-ERP station joins/leaves
  516          * an 11g network.  The 802.11 layer notifies us via callback,
  517          * we mark updateslot, then wait one beacon before effecting
  518          * the change.  This gives associated stations at least one
  519          * beacon interval to note the state change.
  520          */
  521         /* XXX locking */
  522         if (sc->sc_updateslot == UPDATE) {
  523                 sc->sc_updateslot = COMMIT;     /* commit next beacon */
  524                 sc->sc_slotupdate = slot;
  525         } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
  526                 ath_setslottime(sc);            /* commit change to h/w */
  527 
  528         /*
  529          * Check recent per-antenna transmit statistics and flip
  530          * the default antenna if noticeably more frames went out
  531          * on the non-default antenna.
  532          * XXX assumes 2 anntenae
  533          */
  534         if (!sc->sc_diversity && (!sc->sc_stagbeacons || slot == 0)) {
  535                 otherant = sc->sc_defant & 1 ? 2 : 1;
  536                 if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2)
  537                         ath_setdefantenna(sc, otherant);
  538                 sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
  539         }
  540 
  541         /* Program the CABQ with the contents of the CABQ txq and start it */
  542         ATH_TXQ_LOCK(sc->sc_cabq);
  543         ath_beacon_cabq_start(sc);
  544         ATH_TXQ_UNLOCK(sc->sc_cabq);
  545 
  546         /* Program the new beacon frame if we have one for this interval */
  547         if (bfaddr != 0) {
  548                 /*
  549                  * Stop any current dma and put the new frame on the queue.
  550                  * This should never fail since we check above that no frames
  551                  * are still pending on the queue.
  552                  */
  553                 if (! sc->sc_isedma) {
  554                         if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) {
  555                                 DPRINTF(sc, ATH_DEBUG_ANY,
  556                                         "%s: beacon queue %u did not stop?\n",
  557                                         __func__, sc->sc_bhalq);
  558                         }
  559                 }
  560                 /* NB: cabq traffic should already be queued and primed */
  561 
  562                 ath_hal_puttxbuf(ah, sc->sc_bhalq, bfaddr);
  563                 ath_hal_txstart(ah, sc->sc_bhalq);
  564 
  565                 sc->sc_stats.ast_be_xmit++;
  566         }
  567 }
  568 
  569 static void
  570 ath_beacon_cabq_start_edma(struct ath_softc *sc)
  571 {
  572         struct ath_buf *bf, *bf_last;
  573         struct ath_txq *cabq = sc->sc_cabq;
  574 #if 0
  575         struct ath_buf *bfi;
  576         int i = 0;
  577 #endif
  578 
  579         ATH_TXQ_LOCK_ASSERT(cabq);
  580 
  581         if (TAILQ_EMPTY(&cabq->axq_q))
  582                 return;
  583         bf = TAILQ_FIRST(&cabq->axq_q);
  584         bf_last = TAILQ_LAST(&cabq->axq_q, axq_q_s);
  585 
  586         /*
  587          * This is a dirty, dirty hack to push the contents of
  588          * the cabq staging queue into the FIFO.
  589          *
  590          * This ideally should live in the EDMA code file
  591          * and only push things into the CABQ if there's a FIFO
  592          * slot.
  593          *
  594          * We can't treat this like a normal TX queue because
  595          * in the case of multi-VAP traffic, we may have to flush
  596          * the CABQ each new (staggered) beacon that goes out.
  597          * But for non-staggered beacons, we could in theory
  598          * handle multicast traffic for all VAPs in one FIFO
  599          * push.  Just keep all of this in mind if you're wondering
  600          * how to correctly/better handle multi-VAP CABQ traffic
  601          * with EDMA.
  602          */
  603 
  604         /*
  605          * Is the CABQ FIFO free? If not, complain loudly and
  606          * don't queue anything.  Maybe we'll flush the CABQ
  607          * traffic, maybe we won't.  But that'll happen next
  608          * beacon interval.
  609          */
  610         if (cabq->axq_fifo_depth >= HAL_TXFIFO_DEPTH) {
  611                 device_printf(sc->sc_dev,
  612                     "%s: Q%d: CAB FIFO queue=%d?\n",
  613                     __func__,
  614                     cabq->axq_qnum,
  615                     cabq->axq_fifo_depth);
  616                 return;
  617         }
  618 
  619         /*
  620          * Ok, so here's the gymnastics reqiured to make this
  621          * all sensible.
  622          */
  623 
  624         /*
  625          * Tag the first/last buffer appropriately.
  626          */
  627         bf->bf_flags |= ATH_BUF_FIFOPTR;
  628         bf_last->bf_flags |= ATH_BUF_FIFOEND;
  629 
  630 #if 0
  631         i = 0;
  632         TAILQ_FOREACH(bfi, &cabq->axq_q, bf_list) {
  633                 ath_printtxbuf(sc, bf, cabq->axq_qnum, i, 0);
  634                 i++;
  635         }
  636 #endif
  637 
  638         /*
  639          * We now need to push this set of frames onto the tail
  640          * of the FIFO queue.  We don't adjust the aggregate
  641          * count, only the queue depth counter(s).
  642          * We also need to blank the link pointer now.
  643          */
  644         TAILQ_CONCAT(&cabq->fifo.axq_q, &cabq->axq_q, bf_list);
  645         cabq->axq_link = NULL;
  646         cabq->fifo.axq_depth += cabq->axq_depth;
  647         cabq->axq_depth = 0;
  648 
  649         /* Bump FIFO queue */
  650         cabq->axq_fifo_depth++;
  651 
  652         /* Push the first entry into the hardware */
  653         ath_hal_puttxbuf(sc->sc_ah, cabq->axq_qnum, bf->bf_daddr);
  654         cabq->axq_flags |= ATH_TXQ_PUTRUNNING;
  655 
  656         /* NB: gated by beacon so safe to start here */
  657         ath_hal_txstart(sc->sc_ah, cabq->axq_qnum);
  658 
  659 }
  660 
  661 static void
  662 ath_beacon_cabq_start_legacy(struct ath_softc *sc)
  663 {
  664         struct ath_buf *bf;
  665         struct ath_txq *cabq = sc->sc_cabq;
  666 
  667         ATH_TXQ_LOCK_ASSERT(cabq);
  668         if (TAILQ_EMPTY(&cabq->axq_q))
  669                 return;
  670         bf = TAILQ_FIRST(&cabq->axq_q);
  671 
  672         /* Push the first entry into the hardware */
  673         ath_hal_puttxbuf(sc->sc_ah, cabq->axq_qnum, bf->bf_daddr);
  674         cabq->axq_flags |= ATH_TXQ_PUTRUNNING;
  675 
  676         /* NB: gated by beacon so safe to start here */
  677         ath_hal_txstart(sc->sc_ah, cabq->axq_qnum);
  678 }
  679 
  680 /*
  681  * Start CABQ transmission - this assumes that all frames are prepped
  682  * and ready in the CABQ.
  683  */
  684 void
  685 ath_beacon_cabq_start(struct ath_softc *sc)
  686 {
  687         struct ath_txq *cabq = sc->sc_cabq;
  688 
  689         ATH_TXQ_LOCK_ASSERT(cabq);
  690 
  691         if (TAILQ_EMPTY(&cabq->axq_q))
  692                 return;
  693 
  694         if (sc->sc_isedma)
  695                 ath_beacon_cabq_start_edma(sc);
  696         else
  697                 ath_beacon_cabq_start_legacy(sc);
  698 }
  699 
  700 struct ath_buf *
  701 ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
  702 {
  703         struct ath_vap *avp = ATH_VAP(vap);
  704         struct ath_txq *cabq = sc->sc_cabq;
  705         struct ath_buf *bf;
  706         struct mbuf *m;
  707         int nmcastq, error;
  708 
  709         KASSERT(vap->iv_state >= IEEE80211_S_RUN,
  710             ("not running, state %d", vap->iv_state));
  711         KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer"));
  712 
  713         /*
  714          * Update dynamic beacon contents.  If this returns
  715          * non-zero then we need to remap the memory because
  716          * the beacon frame changed size (probably because
  717          * of the TIM bitmap).
  718          */
  719         bf = avp->av_bcbuf;
  720         m = bf->bf_m;
  721         /* XXX lock mcastq? */
  722         nmcastq = avp->av_mcastq.axq_depth;
  723 
  724         if (ieee80211_beacon_update(bf->bf_node, m, nmcastq)) {
  725                 /* XXX too conservative? */
  726                 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
  727                 error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
  728                                              bf->bf_segs, &bf->bf_nseg,
  729                                              BUS_DMA_NOWAIT);
  730                 if (error != 0) {
  731                         if_printf(vap->iv_ifp,
  732                             "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
  733                             __func__, error);
  734                         return NULL;
  735                 }
  736         }
  737         if ((vap->iv_bcn_off.bo_tim[4] & 1) && cabq->axq_depth) {
  738                 DPRINTF(sc, ATH_DEBUG_BEACON,
  739                     "%s: cabq did not drain, mcastq %u cabq %u\n",
  740                     __func__, nmcastq, cabq->axq_depth);
  741                 sc->sc_stats.ast_cabq_busy++;
  742                 if (sc->sc_nvaps > 1 && sc->sc_stagbeacons) {
  743                         /*
  744                          * CABQ traffic from a previous vap is still pending.
  745                          * We must drain the q before this beacon frame goes
  746                          * out as otherwise this vap's stations will get cab
  747                          * frames from a different vap.
  748                          * XXX could be slow causing us to miss DBA
  749                          */
  750                         /*
  751                          * XXX TODO: this doesn't stop CABQ DMA - it assumes
  752                          * that since we're about to transmit a beacon, we've
  753                          * already stopped transmitting on the CABQ.  But this
  754                          * doesn't at all mean that the CABQ DMA QCU will
  755                          * accept a new TXDP!  So what, should we do a DMA
  756                          * stop? What if it fails?
  757                          *
  758                          * More thought is required here.
  759                          */
  760                         /*
  761                          * XXX can we even stop TX DMA here? Check what the
  762                          * reference driver does for cabq for beacons, given
  763                          * that stopping TX requires RX is paused.
  764                          */
  765                         ath_tx_draintxq(sc, cabq);
  766                 }
  767         }
  768         ath_beacon_setup(sc, bf);
  769         bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
  770 
  771         /*
  772          * XXX TODO: tie into net80211 for quiet time IE update and program
  773          * local AP timer if we require it.  The process of updating the
  774          * beacon will also update the IE with the relevant counters.
  775          */
  776 
  777         /*
  778          * Enable the CAB queue before the beacon queue to
  779          * insure cab frames are triggered by this beacon.
  780          */
  781         if (vap->iv_bcn_off.bo_tim[4] & 1) {
  782                 /* NB: only at DTIM */
  783                 ATH_TXQ_LOCK(&avp->av_mcastq);
  784                 if (nmcastq) {
  785                         struct ath_buf *bfm, *bfc_last;
  786 
  787                         /*
  788                          * Move frames from the s/w mcast q to the h/w cab q.
  789                          *
  790                          * XXX TODO: if we chain together multiple VAPs
  791                          * worth of CABQ traffic, should we keep the
  792                          * MORE data bit set on the last frame of each
  793                          * intermediary VAP (ie, only clear the MORE
  794                          * bit of the last frame on the last vap?)
  795                          */
  796                         bfm = TAILQ_FIRST(&avp->av_mcastq.axq_q);
  797                         ATH_TXQ_LOCK(cabq);
  798 
  799                         /*
  800                          * If there's already a frame on the CABQ, we
  801                          * need to link to the end of the last frame.
  802                          * We can't use axq_link here because
  803                          * EDMA descriptors require some recalculation
  804                          * (checksum) to occur.
  805                          */
  806                         bfc_last = ATH_TXQ_LAST(cabq, axq_q_s);
  807                         if (bfc_last != NULL) {
  808                                 ath_hal_settxdesclink(sc->sc_ah,
  809                                     bfc_last->bf_lastds,
  810                                     bfm->bf_daddr);
  811                         }
  812                         ath_txqmove(cabq, &avp->av_mcastq);
  813                         ATH_TXQ_UNLOCK(cabq);
  814                         /*
  815                          * XXX not entirely accurate, in case a mcast
  816                          * queue frame arrived before we grabbed the TX
  817                          * lock.
  818                          */
  819                         sc->sc_stats.ast_cabq_xmit += nmcastq;
  820                 }
  821                 ATH_TXQ_UNLOCK(&avp->av_mcastq);
  822         }
  823         return bf;
  824 }
  825 
  826 void
  827 ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
  828 {
  829         struct ath_vap *avp = ATH_VAP(vap);
  830         struct ath_hal *ah = sc->sc_ah;
  831         struct ath_buf *bf;
  832         struct mbuf *m;
  833         int error;
  834 
  835         KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer"));
  836 
  837         /*
  838          * Update dynamic beacon contents.  If this returns
  839          * non-zero then we need to remap the memory because
  840          * the beacon frame changed size (probably because
  841          * of the TIM bitmap).
  842          */
  843         bf = avp->av_bcbuf;
  844         m = bf->bf_m;
  845         if (ieee80211_beacon_update(bf->bf_node, m, 0)) {
  846                 /* XXX too conservative? */
  847                 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
  848                 error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
  849                                              bf->bf_segs, &bf->bf_nseg,
  850                                              BUS_DMA_NOWAIT);
  851                 if (error != 0) {
  852                         if_printf(vap->iv_ifp,
  853                             "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
  854                             __func__, error);
  855                         return;
  856                 }
  857         }
  858         ath_beacon_setup(sc, bf);
  859         bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
  860 
  861         /* NB: caller is known to have already stopped tx dma */
  862         ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
  863         ath_hal_txstart(ah, sc->sc_bhalq);
  864 }
  865 
  866 /*
  867  * Reclaim beacon resources and return buffer to the pool.
  868  */
  869 void
  870 ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf)
  871 {
  872 
  873         DPRINTF(sc, ATH_DEBUG_NODE, "%s: free bf=%p, bf_m=%p, bf_node=%p\n",
  874             __func__, bf, bf->bf_m, bf->bf_node);
  875         if (bf->bf_m != NULL) {
  876                 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
  877                 m_freem(bf->bf_m);
  878                 bf->bf_m = NULL;
  879         }
  880         if (bf->bf_node != NULL) {
  881                 ieee80211_free_node(bf->bf_node);
  882                 bf->bf_node = NULL;
  883         }
  884         TAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list);
  885 }
  886 
  887 /*
  888  * Reclaim beacon resources.
  889  */
  890 void
  891 ath_beacon_free(struct ath_softc *sc)
  892 {
  893         struct ath_buf *bf;
  894 
  895         TAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
  896                 DPRINTF(sc, ATH_DEBUG_NODE,
  897                     "%s: free bf=%p, bf_m=%p, bf_node=%p\n",
  898                         __func__, bf, bf->bf_m, bf->bf_node);
  899                 if (bf->bf_m != NULL) {
  900                         bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
  901                         m_freem(bf->bf_m);
  902                         bf->bf_m = NULL;
  903                 }
  904                 if (bf->bf_node != NULL) {
  905                         ieee80211_free_node(bf->bf_node);
  906                         bf->bf_node = NULL;
  907                 }
  908         }
  909 }
  910 
  911 /*
  912  * Configure the beacon and sleep timers.
  913  *
  914  * When operating as an AP this resets the TSF and sets
  915  * up the hardware to notify us when we need to issue beacons.
  916  *
  917  * When operating in station mode this sets up the beacon
  918  * timers according to the timestamp of the last received
  919  * beacon and the current TSF, configures PCF and DTIM
  920  * handling, programs the sleep registers so the hardware
  921  * will wakeup in time to receive beacons, and configures
  922  * the beacon miss handling so we'll receive a BMISS
  923  * interrupt when we stop seeing beacons from the AP
  924  * we've associated with.
  925  */
  926 void
  927 ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
  928 {
  929 #define TSF_TO_TU(_h,_l) \
  930         ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
  931 #define FUDGE   2
  932         struct ath_hal *ah = sc->sc_ah;
  933         struct ath_vap *avp;
  934         struct ieee80211com *ic = &sc->sc_ic;
  935         struct ieee80211_node *ni;
  936         u_int32_t nexttbtt, intval, tsftu;
  937         u_int32_t nexttbtt_u8, intval_u8;
  938         u_int64_t tsf, tsf_beacon;
  939 
  940         /*
  941          * Find the first VAP that we /can/ use a beacon configuration for.
  942          * If it's a STA VAP then if it has SWBMISS set we should ignore it.
  943          *
  944          * Yes, ideally we'd not have a STA without SWBMISS followed by an
  945          * AP STA, and yes this isn't ready for P2P/TSF2 logic on AR9300 and
  946          * later chips.
  947          */
  948         if (vap == NULL) {
  949                 IEEE80211_LOCK(ic);
  950                 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
  951                         /* A STA VAP w/ SWBMISS set can't be used for beaconing */
  952                         if ((vap->iv_opmode == IEEE80211_M_STA) &&
  953                             ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) != 0))
  954                                 continue;
  955                         break;
  956                 }
  957                 IEEE80211_UNLOCK(ic);
  958         }
  959 
  960         if (vap == NULL) {
  961                 device_printf(sc->sc_dev, "called with no valid vaps?\n");
  962                 return;
  963         }
  964 
  965         if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) != 0) {
  966                 device_printf(sc->sc_dev, "called on VAP with SWBMISS set?\n");
  967                 return;
  968         }
  969 
  970         /* Now that we have a vap, we can do this bit */
  971         avp = ATH_VAP(vap);
  972 
  973         ni = ieee80211_ref_node(vap->iv_bss);
  974 
  975         ATH_LOCK(sc);
  976         ath_power_set_power_state(sc, HAL_PM_AWAKE);
  977         ATH_UNLOCK(sc);
  978 
  979         /* Always clear the quiet IE timers; let the next update program them */
  980         ath_hal_set_quiet(ah, 0, 0, 0, HAL_QUIET_DISABLE);
  981         memset(&avp->quiet_ie, 0, sizeof(avp->quiet_ie));
  982 
  983         /* extract tstamp from last beacon and convert to TU */
  984         nexttbtt = TSF_TO_TU(le32dec(ni->ni_tstamp.data + 4),
  985                              le32dec(ni->ni_tstamp.data));
  986 
  987         tsf_beacon = ((uint64_t) le32dec(ni->ni_tstamp.data + 4)) << 32;
  988         tsf_beacon |= le32dec(ni->ni_tstamp.data);
  989 
  990         if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
  991             ic->ic_opmode == IEEE80211_M_MBSS) {
  992                 /*
  993                  * For multi-bss ap/mesh support beacons are either staggered
  994                  * evenly over N slots or burst together.  For the former
  995                  * arrange for the SWBA to be delivered for each slot.
  996                  * Slots that are not occupied will generate nothing.
  997                  */
  998                 /* NB: the beacon interval is kept internally in TU's */
  999                 intval = ni->ni_intval & HAL_BEACON_PERIOD;
 1000                 if (sc->sc_stagbeacons)
 1001                         intval /= ATH_BCBUF;
 1002         } else {
 1003                 /* NB: the beacon interval is kept internally in TU's */
 1004                 intval = ni->ni_intval & HAL_BEACON_PERIOD;
 1005         }
 1006 
 1007         /*
 1008          * Note: rounding up to the next intval can cause problems with
 1009          * bad APs when we're in powersave mode.
 1010          *
 1011          * In STA mode with powersave enabled, beacons are only received
 1012          * whenever the beacon timer fires to wake up the hardware.
 1013          * Now, if this is rounded up to the next intval, it assumes
 1014          * that the AP has started transmitting beacons at TSF values that
 1015          * are multiples of intval, versus say being 25 TU off.
 1016          *
 1017          * The specification (802.11-2012 10.1.3.2 - Beacon Generation in
 1018          * Infrastructure Networks) requires APs be beaconing at a
 1019          * mutiple of intval.  So, if bintval=100, then we shouldn't
 1020          * get beacons at intervals other than around multiples of 100.
 1021          */
 1022         if (nexttbtt == 0)              /* e.g. for ap mode */
 1023                 nexttbtt = intval;
 1024         else
 1025                 nexttbtt = roundup(nexttbtt, intval);
 1026 
 1027 
 1028         if (ic->ic_opmode == IEEE80211_M_STA && !sc->sc_swbmiss) {
 1029                 HAL_BEACON_STATE bs;
 1030                 int dtimperiod, dtimcount;
 1031                 int cfpperiod, cfpcount;
 1032 
 1033                 /*
 1034                  * Setup dtim and cfp parameters according to
 1035                  * last beacon we received (which may be none).
 1036                  */
 1037                 dtimperiod = ni->ni_dtim_period;
 1038                 if (dtimperiod <= 0)            /* NB: 0 if not known */
 1039                         dtimperiod = 1;
 1040                 dtimcount = ni->ni_dtim_count;
 1041                 if (dtimcount >= dtimperiod)    /* NB: sanity check */
 1042                         dtimcount = 0;          /* XXX? */
 1043                 cfpperiod = 1;                  /* NB: no PCF support yet */
 1044                 cfpcount = 0;
 1045                 /*
 1046                  * Pull nexttbtt forward to reflect the current
 1047                  * TSF and calculate dtim+cfp state for the result.
 1048                  */
 1049                 tsf = ath_hal_gettsf64(ah);
 1050                 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
 1051 
 1052                 DPRINTF(sc, ATH_DEBUG_BEACON,
 1053                     "%s: beacon tsf=%llu, hw tsf=%llu, nexttbtt=%u, tsftu=%u\n",
 1054                     __func__,
 1055                     (unsigned long long) tsf_beacon,
 1056                     (unsigned long long) tsf,
 1057                     nexttbtt,
 1058                     tsftu);
 1059                 DPRINTF(sc, ATH_DEBUG_BEACON,
 1060                     "%s: beacon tsf=%llu, hw tsf=%llu, tsf delta=%lld\n",
 1061                     __func__,
 1062                     (unsigned long long) tsf_beacon,
 1063                     (unsigned long long) tsf,
 1064                     (long long) tsf -
 1065                     (long long) tsf_beacon);
 1066 
 1067                 DPRINTF(sc, ATH_DEBUG_BEACON,
 1068                     "%s: nexttbtt=%llu, beacon tsf delta=%lld\n",
 1069                     __func__,
 1070                     (unsigned long long) nexttbtt,
 1071                     (long long) ((long long) nexttbtt * 1024LL) - (long long) tsf_beacon);
 1072 
 1073                 /* XXX cfpcount? */
 1074 
 1075                 if (nexttbtt > tsftu) {
 1076                         uint32_t countdiff, oldtbtt, remainder;
 1077 
 1078                         oldtbtt = nexttbtt;
 1079                         remainder = (nexttbtt - tsftu) % intval;
 1080                         nexttbtt = tsftu + remainder;
 1081 
 1082                         countdiff = (oldtbtt - nexttbtt) / intval % dtimperiod;
 1083                         if (dtimcount > countdiff) {
 1084                                 dtimcount -= countdiff;
 1085                         } else {
 1086                                 dtimcount += dtimperiod - countdiff;
 1087                         }
 1088                 } else { //nexttbtt <= tsftu
 1089                         uint32_t countdiff, oldtbtt, remainder;
 1090 
 1091                         oldtbtt = nexttbtt;
 1092                         remainder = (tsftu - nexttbtt) % intval;
 1093                         nexttbtt = tsftu - remainder + intval;
 1094                         countdiff = (nexttbtt - oldtbtt) / intval % dtimperiod;
 1095                         if (dtimcount > countdiff) {
 1096                                 dtimcount -= countdiff;
 1097                         } else {
 1098                                 dtimcount += dtimperiod - countdiff;
 1099                         }
 1100                 }
 1101 
 1102                 DPRINTF(sc, ATH_DEBUG_BEACON,
 1103                     "%s: adj nexttbtt=%llu, rx tsf delta=%lld\n",
 1104                     __func__,
 1105                     (unsigned long long) nexttbtt,
 1106                     (long long) ((long long)nexttbtt * 1024LL) - (long long)tsf);
 1107 
 1108                 memset(&bs, 0, sizeof(bs));
 1109                 bs.bs_intval = intval;
 1110                 bs.bs_nexttbtt = nexttbtt;
 1111                 bs.bs_dtimperiod = dtimperiod*intval;
 1112                 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
 1113                 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
 1114                 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
 1115                 bs.bs_cfpmaxduration = 0;
 1116 #if 0
 1117                 /*
 1118                  * The 802.11 layer records the offset to the DTIM
 1119                  * bitmap while receiving beacons; use it here to
 1120                  * enable h/w detection of our AID being marked in
 1121                  * the bitmap vector (to indicate frames for us are
 1122                  * pending at the AP).
 1123                  * XXX do DTIM handling in s/w to WAR old h/w bugs
 1124                  * XXX enable based on h/w rev for newer chips
 1125                  */
 1126                 bs.bs_timoffset = ni->ni_timoff;
 1127 #endif
 1128                 /*
 1129                  * Calculate the number of consecutive beacons to miss
 1130                  * before taking a BMISS interrupt.
 1131                  * Note that we clamp the result to at most 10 beacons.
 1132                  */
 1133                 bs.bs_bmissthreshold = vap->iv_bmissthreshold;
 1134                 if (bs.bs_bmissthreshold > 10)
 1135                         bs.bs_bmissthreshold = 10;
 1136                 else if (bs.bs_bmissthreshold <= 0)
 1137                         bs.bs_bmissthreshold = 1;
 1138 
 1139                 /*
 1140                  * Calculate sleep duration.  The configuration is
 1141                  * given in ms.  We insure a multiple of the beacon
 1142                  * period is used.  Also, if the sleep duration is
 1143                  * greater than the DTIM period then it makes senses
 1144                  * to make it a multiple of that.
 1145                  *
 1146                  * XXX fixed at 100ms
 1147                  */
 1148                 bs.bs_sleepduration =
 1149                         roundup(IEEE80211_MS_TO_TU(100), bs.bs_intval);
 1150                 if (bs.bs_sleepduration > bs.bs_dtimperiod)
 1151                         bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
 1152 
 1153                 DPRINTF(sc, ATH_DEBUG_BEACON,
 1154                         "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u "
 1155                         "nextdtim %u bmiss %u sleep %u cfp:period %u "
 1156                         "maxdur %u next %u timoffset %u\n"
 1157                         , __func__
 1158                         , tsf
 1159                         , tsftu
 1160                         , bs.bs_intval
 1161                         , bs.bs_nexttbtt
 1162                         , bs.bs_dtimperiod
 1163                         , bs.bs_nextdtim
 1164                         , bs.bs_bmissthreshold
 1165                         , bs.bs_sleepduration
 1166                         , bs.bs_cfpperiod
 1167                         , bs.bs_cfpmaxduration
 1168                         , bs.bs_cfpnext
 1169                         , bs.bs_timoffset
 1170                 );
 1171                 ath_hal_intrset(ah, 0);
 1172                 ath_hal_beacontimers(ah, &bs);
 1173                 sc->sc_imask |= HAL_INT_BMISS;
 1174                 ath_hal_intrset(ah, sc->sc_imask);
 1175         } else {
 1176                 ath_hal_intrset(ah, 0);
 1177                 if (nexttbtt == intval)
 1178                         intval |= HAL_BEACON_RESET_TSF;
 1179                 if (ic->ic_opmode == IEEE80211_M_IBSS) {
 1180                         /*
 1181                          * In IBSS mode enable the beacon timers but only
 1182                          * enable SWBA interrupts if we need to manually
 1183                          * prepare beacon frames.  Otherwise we use a
 1184                          * self-linked tx descriptor and let the hardware
 1185                          * deal with things.
 1186                          */
 1187                         intval |= HAL_BEACON_ENA;
 1188                         if (!sc->sc_hasveol)
 1189                                 sc->sc_imask |= HAL_INT_SWBA;
 1190                         if ((intval & HAL_BEACON_RESET_TSF) == 0) {
 1191                                 /*
 1192                                  * Pull nexttbtt forward to reflect
 1193                                  * the current TSF.
 1194                                  */
 1195                                 tsf = ath_hal_gettsf64(ah);
 1196                                 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
 1197                                 do {
 1198                                         nexttbtt += intval;
 1199                                 } while (nexttbtt < tsftu);
 1200                         }
 1201                         ath_beaconq_config(sc);
 1202                 } else if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
 1203                     ic->ic_opmode == IEEE80211_M_MBSS) {
 1204                         /*
 1205                          * In AP/mesh mode we enable the beacon timers
 1206                          * and SWBA interrupts to prepare beacon frames.
 1207                          */
 1208                         intval |= HAL_BEACON_ENA;
 1209                         sc->sc_imask |= HAL_INT_SWBA;   /* beacon prepare */
 1210                         ath_beaconq_config(sc);
 1211                 }
 1212 
 1213                 /*
 1214                  * Now dirty things because for now, the EDMA HAL has
 1215                  * nexttbtt and intval is TU/8.
 1216                  */
 1217                 if (sc->sc_isedma) {
 1218                         nexttbtt_u8 = (nexttbtt << 3) & HAL_BEACON_PERIOD_TU8;
 1219                         intval_u8 = (intval << 3) & HAL_BEACON_PERIOD_TU8;
 1220                         if (intval & HAL_BEACON_ENA)
 1221                                 intval_u8 |= HAL_BEACON_ENA;
 1222                         if (intval & HAL_BEACON_RESET_TSF)
 1223                                 intval_u8 |= HAL_BEACON_RESET_TSF;
 1224                         ath_hal_beaconinit(ah, nexttbtt_u8, intval_u8);
 1225                 } else
 1226                         ath_hal_beaconinit(ah, nexttbtt, intval);
 1227                 sc->sc_bmisscount = 0;
 1228                 ath_hal_intrset(ah, sc->sc_imask);
 1229                 /*
 1230                  * When using a self-linked beacon descriptor in
 1231                  * ibss mode load it once here.
 1232                  */
 1233                 if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
 1234                         ath_beacon_start_adhoc(sc, vap);
 1235         }
 1236         ieee80211_free_node(ni);
 1237 
 1238         tsf = ath_hal_gettsf64(ah);
 1239         DPRINTF(sc, ATH_DEBUG_BEACON,
 1240             "%s: nexttbtt %u intval %u (%u), tsf64=%llu tsfbeacon=%llu delta=%lld\n",
 1241             __func__, nexttbtt, intval, ni->ni_intval,
 1242             (unsigned long long) tsf,
 1243             (unsigned long long) tsf_beacon,
 1244             (long long) tsf -
 1245             (long long) tsf_beacon);
 1246 
 1247         ATH_LOCK(sc);
 1248         ath_power_restore_power_state(sc);
 1249         ATH_UNLOCK(sc);
 1250 #undef FUDGE
 1251 #undef TSF_TO_TU
 1252 }

Cache object: 5e4ff21b82fb408e5007bf963fbd6f79


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.