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_tdma.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 #ifdef IEEE80211_SUPPORT_TDMA
   92 #include <net80211/ieee80211_tdma.h>
   93 #endif
   94 
   95 #include <net/bpf.h>
   96 
   97 #ifdef INET
   98 #include <netinet/in.h>
   99 #include <netinet/if_ether.h>
  100 #endif
  101 
  102 #include <dev/ath/if_athvar.h>
  103 #include <dev/ath/ath_hal/ah_devid.h>           /* XXX for softled */
  104 #include <dev/ath/ath_hal/ah_diagcodes.h>
  105 
  106 #include <dev/ath/if_ath_debug.h>
  107 #include <dev/ath/if_ath_misc.h>
  108 #include <dev/ath/if_ath_tsf.h>
  109 #include <dev/ath/if_ath_tx.h>
  110 #include <dev/ath/if_ath_sysctl.h>
  111 #include <dev/ath/if_ath_led.h>
  112 #include <dev/ath/if_ath_keycache.h>
  113 #include <dev/ath/if_ath_rx.h>
  114 #include <dev/ath/if_ath_beacon.h>
  115 #include <dev/ath/if_athdfs.h>
  116 
  117 #ifdef ATH_TX99_DIAG
  118 #include <dev/ath/ath_tx99/ath_tx99.h>
  119 #endif
  120 
  121 #ifdef  ATH_DEBUG_ALQ
  122 #include <dev/ath/if_ath_alq.h>
  123 #endif
  124 
  125 #ifdef IEEE80211_SUPPORT_TDMA
  126 #include <dev/ath/if_ath_tdma.h>
  127 
  128 static void     ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt,
  129                     u_int32_t bintval);
  130 static void     ath_tdma_bintvalsetup(struct ath_softc *sc,
  131                     const struct ieee80211_tdma_state *tdma);
  132 #endif /* IEEE80211_SUPPORT_TDMA */
  133 
  134 #ifdef IEEE80211_SUPPORT_TDMA
  135 static void
  136 ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
  137 {
  138         struct ath_hal *ah = sc->sc_ah;
  139         HAL_BEACON_TIMERS bt;
  140 
  141         bt.bt_intval = bintval | HAL_BEACON_ENA;
  142         bt.bt_nexttbtt = nexttbtt;
  143         bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep;
  144         bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep;
  145         bt.bt_nextatim = nexttbtt+1;
  146         /* Enables TBTT, DBA, SWBA timers by default */
  147         bt.bt_flags = 0;
  148 #if 0
  149         DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  150             "%s: intval=%d (0x%08x) nexttbtt=%u (0x%08x), nextdba=%u (0x%08x), nextswba=%u (0x%08x),nextatim=%u (0x%08x)\n",
  151             __func__,
  152             bt.bt_intval,
  153             bt.bt_intval,
  154             bt.bt_nexttbtt,
  155             bt.bt_nexttbtt,
  156             bt.bt_nextdba,
  157             bt.bt_nextdba,
  158             bt.bt_nextswba,
  159             bt.bt_nextswba,
  160             bt.bt_nextatim,
  161             bt.bt_nextatim);
  162 #endif
  163 
  164 #ifdef  ATH_DEBUG_ALQ
  165         if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_TDMA_TIMER_SET)) {
  166                 struct if_ath_alq_tdma_timer_set t;
  167                 t.bt_intval = htobe32(bt.bt_intval);
  168                 t.bt_nexttbtt = htobe32(bt.bt_nexttbtt);
  169                 t.bt_nextdba = htobe32(bt.bt_nextdba);
  170                 t.bt_nextswba = htobe32(bt.bt_nextswba);
  171                 t.bt_nextatim = htobe32(bt.bt_nextatim);
  172                 t.bt_flags = htobe32(bt.bt_flags);
  173                 t.sc_tdmadbaprep = htobe32(sc->sc_tdmadbaprep);
  174                 t.sc_tdmaswbaprep = htobe32(sc->sc_tdmaswbaprep);
  175                 if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TDMA_TIMER_SET,
  176                     sizeof(t), (char *) &t);
  177         }
  178 #endif
  179 
  180         DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  181             "%s: nexttbtt=%u (0x%08x), nexttbtt tsf=%lld (0x%08llx)\n",
  182             __func__,
  183             bt.bt_nexttbtt,
  184             bt.bt_nexttbtt,
  185             (long long) ( ((u_int64_t) (bt.bt_nexttbtt)) << 10),
  186             (long long) ( ((u_int64_t) (bt.bt_nexttbtt)) << 10));
  187         ath_hal_beaconsettimers(ah, &bt);
  188 }
  189 
  190 /*
  191  * Calculate the beacon interval.  This is periodic in the
  192  * superframe for the bss.  We assume each station is configured
  193  * identically wrt transmit rate so the guard time we calculate
  194  * above will be the same on all stations.  Note we need to
  195  * factor in the xmit time because the hardware will schedule
  196  * a frame for transmit if the start of the frame is within
  197  * the burst time.  When we get hardware that properly kills
  198  * frames in the PCU we can reduce/eliminate the guard time.
  199  *
  200  * Roundup to 1024 is so we have 1 TU buffer in the guard time
  201  * to deal with the granularity of the nexttbtt timer.  11n MAC's
  202  * with 1us timer granularity should allow us to reduce/eliminate
  203  * this.
  204  */
  205 static void
  206 ath_tdma_bintvalsetup(struct ath_softc *sc,
  207         const struct ieee80211_tdma_state *tdma)
  208 {
  209         /* copy from vap state (XXX check all vaps have same value?) */
  210         sc->sc_tdmaslotlen = tdma->tdma_slotlen;
  211 
  212         sc->sc_tdmabintval = roundup((sc->sc_tdmaslotlen+sc->sc_tdmaguard) *
  213                 tdma->tdma_slotcnt, 1024);
  214         sc->sc_tdmabintval >>= 10;              /* TSF -> TU */
  215         if (sc->sc_tdmabintval & 1)
  216                 sc->sc_tdmabintval++;
  217 
  218         if (tdma->tdma_slot == 0) {
  219                 /*
  220                  * Only slot 0 beacons; other slots respond.
  221                  */
  222                 sc->sc_imask |= HAL_INT_SWBA;
  223                 sc->sc_tdmaswba = 0;            /* beacon immediately */
  224         } else {
  225                 /* XXX all vaps must be slot 0 or slot !0 */
  226                 sc->sc_imask &= ~HAL_INT_SWBA;
  227         }
  228 }
  229 
  230 /*
  231  * Max 802.11 overhead.  This assumes no 4-address frames and
  232  * the encapsulation done by ieee80211_encap (llc).  We also
  233  * include potential crypto overhead.
  234  */
  235 #define IEEE80211_MAXOVERHEAD \
  236         (sizeof(struct ieee80211_qosframe) \
  237          + sizeof(struct llc) \
  238          + IEEE80211_ADDR_LEN \
  239          + IEEE80211_WEP_IVLEN \
  240          + IEEE80211_WEP_KIDLEN \
  241          + IEEE80211_WEP_CRCLEN \
  242          + IEEE80211_WEP_MICLEN \
  243          + IEEE80211_CRC_LEN)
  244 
  245 /*
  246  * Setup initially for tdma operation.  Start the beacon
  247  * timers and enable SWBA if we are slot 0.  Otherwise
  248  * we wait for slot 0 to arrive so we can sync up before
  249  * starting to transmit.
  250  */
  251 void
  252 ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
  253 {
  254         struct ath_hal *ah = sc->sc_ah;
  255         struct ieee80211com *ic = &sc->sc_ic;
  256         const struct ieee80211_txparam *tp;
  257         const struct ieee80211_tdma_state *tdma = NULL;
  258         int rix;
  259 
  260         if (vap == NULL) {
  261                 vap = TAILQ_FIRST(&ic->ic_vaps);   /* XXX */
  262                 if (vap == NULL) {
  263                         device_printf(sc->sc_dev, "%s: no vaps?\n", __func__);
  264                         return;
  265                 }
  266         }
  267         /* XXX should take a locked ref to iv_bss */
  268         tp = vap->iv_bss->ni_txparms;
  269         /*
  270          * Calculate the guard time for each slot.  This is the
  271          * time to send a maximal-size frame according to the
  272          * fixed/lowest transmit rate.  Note that the interface
  273          * mtu does not include the 802.11 overhead so we must
  274          * tack that on (ath_hal_computetxtime includes the
  275          * preamble and plcp in its calculation).
  276          */
  277         tdma = vap->iv_tdma;
  278         if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
  279                 rix = ath_tx_findrix(sc, tp->ucastrate);
  280         else
  281                 rix = ath_tx_findrix(sc, tp->mcastrate);
  282 
  283         /*
  284          * If the chip supports enforcing TxOP on transmission,
  285          * we can just delete the guard window.  It isn't at all required.
  286          */
  287         if (sc->sc_hasenforcetxop) {
  288                 sc->sc_tdmaguard = 0;
  289         } else {
  290                 /* XXX short preamble assumed */
  291                 /* XXX non-11n rate assumed */
  292                 sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates,
  293                     if_getmtu(vap->iv_ifp) + IEEE80211_MAXOVERHEAD, rix, AH_TRUE,
  294                     AH_TRUE);
  295         }
  296 
  297         ath_hal_intrset(ah, 0);
  298 
  299         ath_beaconq_config(sc);                 /* setup h/w beacon q */
  300         if (sc->sc_setcca)
  301                 ath_hal_setcca(ah, AH_FALSE);   /* disable CCA */
  302         ath_tdma_bintvalsetup(sc, tdma);        /* calculate beacon interval */
  303         ath_tdma_settimers(sc, sc->sc_tdmabintval,
  304                 sc->sc_tdmabintval | HAL_BEACON_RESET_TSF);
  305         sc->sc_syncbeacon = 0;
  306 
  307         sc->sc_avgtsfdeltap = TDMA_DUMMY_MARKER;
  308         sc->sc_avgtsfdeltam = TDMA_DUMMY_MARKER;
  309 
  310         ath_hal_intrset(ah, sc->sc_imask);
  311 
  312         DPRINTF(sc, ATH_DEBUG_TDMA, "%s: slot %u len %uus cnt %u "
  313             "bsched %u guard %uus bintval %u TU dba prep %u\n", __func__,
  314             tdma->tdma_slot, tdma->tdma_slotlen, tdma->tdma_slotcnt,
  315             tdma->tdma_bintval, sc->sc_tdmaguard, sc->sc_tdmabintval,
  316             sc->sc_tdmadbaprep);
  317 
  318 #ifdef  ATH_DEBUG_ALQ
  319         if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_TDMA_TIMER_CONFIG)) {
  320                 struct if_ath_alq_tdma_timer_config t;
  321 
  322                 t.tdma_slot = htobe32(tdma->tdma_slot);
  323                 t.tdma_slotlen = htobe32(tdma->tdma_slotlen);
  324                 t.tdma_slotcnt = htobe32(tdma->tdma_slotcnt);
  325                 t.tdma_bintval = htobe32(tdma->tdma_bintval);
  326                 t.tdma_guard = htobe32(sc->sc_tdmaguard);
  327                 t.tdma_scbintval = htobe32(sc->sc_tdmabintval);
  328                 t.tdma_dbaprep = htobe32(sc->sc_tdmadbaprep);
  329 
  330                 if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TDMA_TIMER_CONFIG,
  331                     sizeof(t), (char *) &t);
  332         }
  333 #endif  /* ATH_DEBUG_ALQ */
  334 }
  335 
  336 /*
  337  * Update tdma operation.  Called from the 802.11 layer
  338  * when a beacon is received from the TDMA station operating
  339  * in the slot immediately preceding us in the bss.  Use
  340  * the rx timestamp for the beacon frame to update our
  341  * beacon timers so we follow their schedule.  Note that
  342  * by using the rx timestamp we implicitly include the
  343  * propagation delay in our schedule.
  344  *
  345  * XXX TODO: since the changes for the AR5416 and later chips
  346  * involved changing the TSF/TU calculations, we need to make
  347  * sure that various calculations wrap consistently.
  348  *
  349  * A lot of the problems stemmed from the calculations wrapping
  350  * at 65,535 TU.  Since a lot of the math is still being done in
  351  * TU, please audit it to ensure that when the TU values programmed
  352  * into the timers wrap at (2^31)-1 TSF, all the various terms
  353  * wrap consistently.
  354  */
  355 void
  356 ath_tdma_update(struct ieee80211_node *ni,
  357         const struct ieee80211_tdma_param *tdma, int changed)
  358 {
  359 #define TSF_TO_TU(_h,_l) \
  360         ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
  361 #define TU_TO_TSF(_tu)  (((u_int64_t)(_tu)) << 10)
  362         struct ieee80211vap *vap = ni->ni_vap;
  363         struct ieee80211com *ic = ni->ni_ic;
  364         struct ath_softc *sc = ic->ic_softc;
  365         struct ath_hal *ah = sc->sc_ah;
  366         const HAL_RATE_TABLE *rt = sc->sc_currates;
  367         u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;
  368         u_int32_t txtime, nextslottu;
  369         int32_t tudelta, tsfdelta;
  370         const struct ath_rx_status *rs;
  371         int rix;
  372 
  373         sc->sc_stats.ast_tdma_update++;
  374 
  375         /*
  376          * Check for and adopt configuration changes.
  377          */
  378         if (changed != 0) {
  379                 const struct ieee80211_tdma_state *ts = vap->iv_tdma;
  380 
  381                 ath_tdma_bintvalsetup(sc, ts);
  382                 if (changed & TDMA_UPDATE_SLOTLEN)
  383                         ath_wme_update(ic);
  384 
  385                 DPRINTF(sc, ATH_DEBUG_TDMA,
  386                     "%s: adopt slot %u slotcnt %u slotlen %u us "
  387                     "bintval %u TU\n", __func__,
  388                     ts->tdma_slot, ts->tdma_slotcnt, ts->tdma_slotlen,
  389                     sc->sc_tdmabintval);
  390 
  391                 /* XXX right? */
  392                 ath_hal_intrset(ah, sc->sc_imask);
  393                 /* NB: beacon timers programmed below */
  394         }
  395 
  396         /* extend rx timestamp to 64 bits */
  397         rs = sc->sc_lastrs;
  398         tsf = ath_hal_gettsf64(ah);
  399         rstamp = ath_extend_tsf(sc, rs->rs_tstamp, tsf);
  400         /*
  401          * The rx timestamp is set by the hardware on completing
  402          * reception (at the point where the rx descriptor is DMA'd
  403          * to the host).  To find the start of our next slot we
  404          * must adjust this time by the time required to send
  405          * the packet just received.
  406          */
  407         rix = rt->rateCodeToIndex[rs->rs_rate];
  408 
  409         /*
  410          * To calculate the packet duration for legacy rates, we
  411          * only need the rix and preamble.
  412          *
  413          * For 11n non-aggregate frames, we also need the channel
  414          * width and short/long guard interval.
  415          *
  416          * For 11n aggregate frames, the required hacks are a little
  417          * more subtle.  You need to figure out the frame duration
  418          * for each frame, including the delimiters.  However, when
  419          * a frame isn't received successfully, we won't hear it
  420          * (unless you enable reception of CRC errored frames), so
  421          * your duration calculation is going to be off.
  422          *
  423          * However, we can assume that the beacon frames won't be
  424          * transmitted as aggregate frames, so we should be okay.
  425          * Just add a check to ensure that we aren't handed something
  426          * bad.
  427          *
  428          * For ath_hal_pkt_txtime() - for 11n rates, shortPreamble is
  429          * actually short guard interval. For legacy rates,
  430          * it's short preamble.
  431          */
  432         txtime = ath_hal_pkt_txtime(ah, rt, rs->rs_datalen,
  433             rix,
  434             !! (rs->rs_flags & HAL_RX_2040),
  435             (rix & 0x80) ?
  436               (! (rs->rs_flags & HAL_RX_GI)) : rt->info[rix].shortPreamble,
  437             AH_TRUE);
  438         /* NB: << 9 is to cvt to TU and /2 */
  439         nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9);
  440 
  441         /*
  442          * For 802.11n chips: nextslottu needs to be the full TSF space,
  443          * not just 0..65535 TU.
  444          */
  445         nextslottu = TSF_TO_TU(nextslot>>32, nextslot);
  446         /*
  447          * Retrieve the hardware NextTBTT in usecs
  448          * and calculate the difference between what the
  449          * other station thinks and what we have programmed.  This
  450          * lets us figure how to adjust our timers to match.  The
  451          * adjustments are done by pulling the TSF forward and possibly
  452          * rewriting the beacon timers.
  453          */
  454         /*
  455          * The logic here assumes the nexttbtt counter is in TSF
  456          * but the prr-11n NICs are in TU.  The HAL shifts them
  457          * to TSF but there's two important differences:
  458          *
  459          * + The TU->TSF values have 0's for the low 9 bits, and
  460          * + The counter wraps at TU_TO_TSF(HAL_BEACON_PERIOD + 1) for
  461          *   the pre-11n NICs, but not for the 11n NICs.
  462          *
  463          * So for now, just make sure the nexttbtt value we get
  464          * matches the second issue or once nexttbtt exceeds this
  465          * value, tsfdelta ends up becoming very negative and all
  466          * of the adjustments get very messed up.
  467          */
  468 
  469         /*
  470          * We need to track the full nexttbtt rather than having it
  471          * truncated at HAL_BEACON_PERIOD, as programming the
  472          * nexttbtt (and related) registers for the 11n chips is
  473          * actually going to take the full 32 bit space, rather than
  474          * just 0..65535 TU.
  475          */
  476         nexttbtt_full = ath_hal_getnexttbtt(ah);
  477         nexttbtt = nexttbtt_full % (TU_TO_TSF(HAL_BEACON_PERIOD + 1));
  478         tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
  479 
  480         DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  481             "rs->rstamp %llu rstamp %llu tsf %llu txtime %d, nextslot %llu, "
  482             "nextslottu %d, nextslottume %d\n",
  483             (unsigned long long) rs->rs_tstamp,
  484             (unsigned long long) rstamp,
  485             (unsigned long long) tsf, txtime,
  486             (unsigned long long) nextslot,
  487             nextslottu, TSF_TO_TU(nextslot >> 32, nextslot));
  488         DPRINTF(sc, ATH_DEBUG_TDMA,
  489             "  beacon tstamp: %llu (0x%016llx)\n",
  490             (unsigned long long) le64toh(ni->ni_tstamp.tsf),
  491             (unsigned long long) le64toh(ni->ni_tstamp.tsf));
  492 
  493         DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  494             "nexttbtt %llu (0x%08llx) tsfdelta %d avg +%d/-%d\n",
  495             (unsigned long long) nexttbtt,
  496             (long long) nexttbtt,
  497             tsfdelta,
  498             TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam));
  499 
  500         if (tsfdelta < 0) {
  501                 TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
  502                 TDMA_SAMPLE(sc->sc_avgtsfdeltam, -tsfdelta);
  503                 tsfdelta = -tsfdelta % 1024;
  504                 nextslottu++;
  505         } else if (tsfdelta > 0) {
  506                 TDMA_SAMPLE(sc->sc_avgtsfdeltap, tsfdelta);
  507                 TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
  508                 tsfdelta = 1024 - (tsfdelta % 1024);
  509                 nextslottu++;
  510         } else {
  511                 TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
  512                 TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
  513         }
  514         tudelta = nextslottu - TSF_TO_TU(nexttbtt_full >> 32, nexttbtt_full);
  515 
  516 #ifdef  ATH_DEBUG_ALQ
  517         if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_TDMA_BEACON_STATE)) {
  518                 struct if_ath_alq_tdma_beacon_state t;
  519                 t.rx_tsf = htobe64(rstamp);
  520                 t.beacon_tsf = htobe64(le64toh(ni->ni_tstamp.tsf));
  521                 t.tsf64 = htobe64(tsf);
  522                 t.nextslot_tsf = htobe64(nextslot);
  523                 t.nextslot_tu = htobe32(nextslottu);
  524                 t.txtime = htobe32(txtime);
  525                 if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TDMA_BEACON_STATE,
  526                     sizeof(t), (char *) &t);
  527         }
  528 
  529         if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_TDMA_SLOT_CALC)) {
  530                 struct if_ath_alq_tdma_slot_calc t;
  531 
  532                 t.nexttbtt = htobe64(nexttbtt_full);
  533                 t.next_slot = htobe64(nextslot);
  534                 t.tsfdelta = htobe32(tsfdelta);
  535                 t.avg_plus = htobe32(TDMA_AVG(sc->sc_avgtsfdeltap));
  536                 t.avg_minus = htobe32(TDMA_AVG(sc->sc_avgtsfdeltam));
  537 
  538                 if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TDMA_SLOT_CALC,
  539                     sizeof(t), (char *) &t);
  540         }
  541 #endif
  542 
  543         /*
  544          * Copy sender's timetstamp into tdma ie so they can
  545          * calculate roundtrip time.  We submit a beacon frame
  546          * below after any timer adjustment.  The frame goes out
  547          * at the next TBTT so the sender can calculate the
  548          * roundtrip by inspecting the tdma ie in our beacon frame.
  549          *
  550          * NB: This tstamp is subtlely preserved when
  551          *     IEEE80211_BEACON_TDMA is marked (e.g. when the
  552          *     slot position changes) because ieee80211_add_tdma
  553          *     skips over the data.
  554          */
  555         memcpy(vap->iv_bcn_off.bo_tdma +
  556                 __offsetof(struct ieee80211_tdma_param, tdma_tstamp),
  557                 &ni->ni_tstamp.data, 8);
  558 #if 0
  559         DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  560             "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n",
  561             (unsigned long long) tsf, (unsigned long long) nextslot,
  562             (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta);
  563 #endif
  564         /*
  565          * Adjust the beacon timers only when pulling them forward
  566          * or when going back by less than the beacon interval.
  567          * Negative jumps larger than the beacon interval seem to
  568          * cause the timers to stop and generally cause instability.
  569          * This basically filters out jumps due to missed beacons.
  570          */
  571         if (tudelta != 0 && (tudelta > 0 || -tudelta < sc->sc_tdmabintval)) {
  572                 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  573                     "%s: calling ath_tdma_settimers; nextslottu=%d, bintval=%d\n",
  574                     __func__,
  575                     nextslottu,
  576                     sc->sc_tdmabintval);
  577                 ath_tdma_settimers(sc, nextslottu, sc->sc_tdmabintval);
  578                 sc->sc_stats.ast_tdma_timers++;
  579         }
  580         if (tsfdelta > 0) {
  581                 uint64_t tsf;
  582 
  583                 /* XXX should just teach ath_hal_adjusttsf() to do this */
  584                 tsf = ath_hal_gettsf64(ah);
  585                 ath_hal_settsf64(ah, tsf + tsfdelta);
  586                 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
  587                     "%s: calling ath_hal_adjusttsf: TSF=%llu, tsfdelta=%d\n",
  588                     __func__,
  589                     (unsigned long long) tsf,
  590                     tsfdelta);
  591 
  592 #ifdef  ATH_DEBUG_ALQ
  593                 if (if_ath_alq_checkdebug(&sc->sc_alq,
  594                     ATH_ALQ_TDMA_TSF_ADJUST)) {
  595                         struct if_ath_alq_tdma_tsf_adjust t;
  596 
  597                         t.tsfdelta = htobe32(tsfdelta);
  598                         t.tsf64_old = htobe64(tsf);
  599                         t.tsf64_new = htobe64(tsf + tsfdelta);
  600                         if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TDMA_TSF_ADJUST,
  601                             sizeof(t), (char *) &t);
  602                 }
  603 #endif  /* ATH_DEBUG_ALQ */
  604                 sc->sc_stats.ast_tdma_tsf++;
  605         }
  606         ath_tdma_beacon_send(sc, vap);          /* prepare response */
  607 #undef TU_TO_TSF
  608 #undef TSF_TO_TU
  609 }
  610 
  611 /*
  612  * Transmit a beacon frame at SWBA.  Dynamic updates
  613  * to the frame contents are done as needed.
  614  */
  615 void
  616 ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap)
  617 {
  618         struct ath_hal *ah = sc->sc_ah;
  619         struct ath_buf *bf;
  620         int otherant;
  621 
  622         /*
  623          * Check if the previous beacon has gone out.  If
  624          * not don't try to post another, skip this period
  625          * and wait for the next.  Missed beacons indicate
  626          * a problem and should not occur.  If we miss too
  627          * many consecutive beacons reset the device.
  628          */
  629         if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) {
  630                 sc->sc_bmisscount++;
  631                 DPRINTF(sc, ATH_DEBUG_BEACON,
  632                         "%s: missed %u consecutive beacons\n",
  633                         __func__, sc->sc_bmisscount);
  634                 if (sc->sc_bmisscount >= ath_bstuck_threshold)
  635                         taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask);
  636                 return;
  637         }
  638         if (sc->sc_bmisscount != 0) {
  639                 DPRINTF(sc, ATH_DEBUG_BEACON,
  640                         "%s: resume beacon xmit after %u misses\n",
  641                         __func__, sc->sc_bmisscount);
  642                 sc->sc_bmisscount = 0;
  643         }
  644 
  645         /*
  646          * Check recent per-antenna transmit statistics and flip
  647          * the default antenna if noticeably more frames went out
  648          * on the non-default antenna.
  649          * XXX assumes 2 anntenae
  650          */
  651         if (!sc->sc_diversity) {
  652                 otherant = sc->sc_defant & 1 ? 2 : 1;
  653                 if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2)
  654                         ath_setdefantenna(sc, otherant);
  655                 sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
  656         }
  657 
  658         bf = ath_beacon_generate(sc, vap);
  659         /* XXX We don't do cabq traffic, but just for completeness .. */
  660         ATH_TXQ_LOCK(sc->sc_cabq);
  661         ath_beacon_cabq_start(sc);
  662         ATH_TXQ_UNLOCK(sc->sc_cabq);
  663 
  664         if (bf != NULL) {
  665                 /*
  666                  * Stop any current dma and put the new frame on the queue.
  667                  * This should never fail since we check above that no frames
  668                  * are still pending on the queue.
  669                  */
  670                 if ((! sc->sc_isedma) &&
  671                     (! ath_hal_stoptxdma(ah, sc->sc_bhalq))) {
  672                         DPRINTF(sc, ATH_DEBUG_ANY,
  673                                 "%s: beacon queue %u did not stop?\n",
  674                                 __func__, sc->sc_bhalq);
  675                         /* NB: the HAL still stops DMA, so proceed */
  676                 }
  677                 ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
  678                 ath_hal_txstart(ah, sc->sc_bhalq);
  679 
  680                 sc->sc_stats.ast_be_xmit++;             /* XXX per-vap? */
  681 
  682                 /*
  683                  * Record local TSF for our last send for use
  684                  * in arbitrating slot collisions.
  685                  */
  686                 /* XXX should take a locked ref to iv_bss */
  687                 vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah);
  688         }
  689 }
  690 #endif /* IEEE80211_SUPPORT_TDMA */

Cache object: 0c3901185aad82e551c61ef4271751bf


[ 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.