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/ath_hal/ar5416/ar5416_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: ISC
    3  *
    4  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 
   26 #include "ar5416/ar5416.h"
   27 #include "ar5416/ar5416reg.h"
   28 #include "ar5416/ar5416phy.h"
   29 
   30 #define TU_TO_USEC(_tu)         ((_tu) << 10)
   31 #define ONE_EIGHTH_TU_TO_USEC(_tu8)     ((_tu8) << 7)
   32 
   33 /*
   34  * Return the hardware NextTBTT in TSF
   35  */
   36 uint64_t
   37 ar5416GetNextTBTT(struct ath_hal *ah)
   38 {
   39         return OS_REG_READ(ah, AR_NEXT_TBTT);
   40 }
   41 
   42 /*
   43  * Initialize all of the hardware registers used to
   44  * send beacons.  Note that for station operation the
   45  * driver calls ar5416SetStaBeaconTimers instead.
   46  */
   47 void
   48 ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
   49 {
   50         uint32_t bperiod;
   51         struct ath_hal_5212 *ahp = AH5212(ah);
   52 
   53         OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt));
   54         OS_REG_WRITE(ah, AR_NEXT_DBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba));
   55         OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba));
   56         OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim));
   57 
   58         bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);
   59         ahp->ah_beaconInterval = bt->bt_intval & HAL_BEACON_PERIOD;
   60         OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod);
   61         OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod);
   62         OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod);
   63         OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod);
   64 
   65         /*
   66          * Reset TSF if required.
   67          */
   68         if (bt->bt_intval & AR_BEACON_RESET_TSF)
   69                 ar5416ResetTsf(ah);
   70 
   71         /* enable timers */
   72         /* NB: flags == 0 handled specially for backwards compatibility */
   73         OS_REG_SET_BIT(ah, AR_TIMER_MODE,
   74             bt->bt_flags != 0 ? bt->bt_flags :
   75                 AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA);
   76 }
   77 
   78 /*
   79  * Initializes all of the hardware registers used to
   80  * send beacons.  Note that for station operation the
   81  * driver calls ar5212SetStaBeaconTimers instead.
   82  */
   83 void
   84 ar5416BeaconInit(struct ath_hal *ah,
   85         uint32_t next_beacon, uint32_t beacon_period)
   86 {
   87         HAL_BEACON_TIMERS bt;
   88 
   89         bt.bt_nexttbtt = next_beacon;
   90         /* 
   91          * TIMER1: in AP/adhoc mode this controls the DMA beacon
   92          * alert timer; otherwise it controls the next wakeup time.
   93          * TIMER2: in AP mode, it controls the SBA beacon alert
   94          * interrupt; otherwise it sets the start of the next CFP.
   95          */
   96         bt.bt_flags = 0;
   97         switch (AH_PRIVATE(ah)->ah_opmode) {
   98         case HAL_M_STA:
   99         case HAL_M_MONITOR:
  100                 bt.bt_nextdba = 0xffff;
  101                 bt.bt_nextswba = 0x7ffff;
  102                 bt.bt_flags |= AR_TIMER_MODE_TBTT;
  103                 break;
  104         case HAL_M_IBSS:
  105                 OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY);
  106                 bt.bt_flags |= AR_TIMER_MODE_NDP;
  107                 /* fall thru... */
  108         case HAL_M_HOSTAP:
  109                 bt.bt_nextdba = (next_beacon -
  110                     ah->ah_config.ah_dma_beacon_response_time) << 3;    /* 1/8 TU */
  111                 bt.bt_nextswba = (next_beacon -
  112                     ah->ah_config.ah_sw_beacon_response_time) << 3;     /* 1/8 TU */
  113                 bt.bt_flags |= AR_TIMER_MODE_TBTT
  114                             |  AR_TIMER_MODE_DBA
  115                             |  AR_TIMER_MODE_SWBA;
  116                 break;
  117         }
  118         /*
  119          * Set the ATIM window 
  120          * Our hardware does not support an ATIM window of 0
  121          * (beacons will not work).  If the ATIM windows is 0,
  122          * force it to 1.
  123          */
  124         bt.bt_nextatim = next_beacon + 1;
  125         bt.bt_intval = beacon_period &
  126                 (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
  127         ar5416SetBeaconTimers(ah, &bt);
  128 }
  129 
  130 #define AR_BEACON_PERIOD_MAX    0xffff
  131 
  132 void
  133 ar5416ResetStaBeaconTimers(struct ath_hal *ah)
  134 {
  135         uint32_t val;
  136 
  137         OS_REG_WRITE(ah, AR_NEXT_TBTT, 0);              /* no beacons */
  138         val = OS_REG_READ(ah, AR_STA_ID1);
  139         val |= AR_STA_ID1_PWR_SAV;              /* XXX */
  140         /* tell the h/w that the associated AP is not PCF capable */
  141         OS_REG_WRITE(ah, AR_STA_ID1,
  142                 val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF));
  143         OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX);
  144         OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX);
  145 }
  146 
  147 /*
  148  * Set all the beacon related bits on the h/w for stations
  149  * i.e. initializes the corresponding h/w timers;
  150  * also tells the h/w whether to anticipate PCF beacons
  151  */
  152 void
  153 ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
  154 {
  155         uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod;
  156 
  157         HALASSERT(bs->bs_intval != 0);
  158 
  159         /* NB: no cfp setting since h/w automatically takes care */
  160 
  161         OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bs->bs_nexttbtt));
  162 
  163         /*
  164          * Start the beacon timers by setting the BEACON register
  165          * to the beacon interval; no need to write tim offset since
  166          * h/w parses IEs.
  167          */
  168         OS_REG_WRITE(ah, AR5416_BEACON_PERIOD,
  169                          TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
  170         OS_REG_WRITE(ah, AR_DBA_PERIOD,
  171                          TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
  172 
  173         /*
  174          * Configure the BMISS interrupt.  Note that we
  175          * assume the caller blocks interrupts while enabling
  176          * the threshold.
  177          */
  178         HALASSERT(bs->bs_bmissthreshold <=
  179                 (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
  180         OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
  181                 AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
  182 
  183         /*
  184          * Program the sleep registers to correlate with the beacon setup.
  185          */
  186 
  187         /*
  188          * Oahu beacons timers on the station were used for power
  189          * save operation (waking up in anticipation of a beacon)
  190          * and any CFP function; Venice does sleep/power-save timers
  191          * differently - so this is the right place to set them up;
  192          * don't think the beacon timers are used by venice sta hw
  193          * for any useful purpose anymore
  194          * Setup venice's sleep related timers
  195          * Current implementation assumes sw processing of beacons -
  196          *   assuming an interrupt is generated every beacon which
  197          *   causes the hardware to become awake until the sw tells
  198          *   it to go to sleep again; beacon timeout is to allow for
  199          *   beacon jitter; cab timeout is max time to wait for cab
  200          *   after seeing the last DTIM or MORE CAB bit
  201          */
  202 
  203 /*
  204  * I've bumped these to 30TU for now.
  205  *
  206  * Some APs (AR933x/AR934x?) in 2GHz especially seem to not always
  207  * transmit beacon frames at exactly the right times and with it set
  208  * to 10TU, the NIC starts not waking up at the right times to hear
  209  * these slightly-larger-jitering beacons.  It also never recovers
  210  * from that (it doesn't resync? I'm not sure.)
  211  *
  212  * So for now bump this to 30TU.  Ideally we'd cap this based on
  213  * the beacon interval so the sum of CAB+BEACON timeouts never
  214  * exceeded the beacon interval.
  215  *
  216  * Now, since we're doing all the math in the ath(4) driver in TU
  217  * rather than TSF, we may be seeing the result of dumb rounding
  218  * errors causing the jitter to actually be a much bigger problem.
  219  * I'll have to investigate that with a fine tooth comb.
  220  */
  221 #define CAB_TIMEOUT_VAL     10 /* in TU */
  222 #define BEACON_TIMEOUT_VAL  10 /* in TU */
  223 #define SLEEP_SLOP          3  /* in TU */
  224 
  225         /*
  226          * For max powersave mode we may want to sleep for longer than a
  227          * beacon period and not want to receive all beacons; modify the
  228          * timers accordingly; make sure to align the next TIM to the
  229          * next DTIM if we decide to wake for DTIMs only
  230          */
  231         beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
  232         HALASSERT(beaconintval != 0);
  233         if (bs->bs_sleepduration > beaconintval) {
  234                 HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
  235                                 bs->bs_sleepduration);
  236                 beaconintval = bs->bs_sleepduration;
  237         }
  238         dtimperiod = bs->bs_dtimperiod;
  239         if (bs->bs_sleepduration > dtimperiod) {
  240                 HALASSERT(dtimperiod == 0 ||
  241                         roundup(bs->bs_sleepduration, dtimperiod) ==
  242                                 bs->bs_sleepduration);
  243                 dtimperiod = bs->bs_sleepduration;
  244         }
  245         HALASSERT(beaconintval <= dtimperiod);
  246         if (beaconintval == dtimperiod)
  247                 nextTbtt = bs->bs_nextdtim;
  248         else
  249                 nextTbtt = bs->bs_nexttbtt;
  250         nextdtim = bs->bs_nextdtim;
  251 
  252         OS_REG_WRITE(ah, AR_NEXT_DTIM,
  253                 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
  254         OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
  255 
  256         /* cab timeout is now in 1/8 TU */
  257         OS_REG_WRITE(ah, AR5416_SLEEP1,
  258                 SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT)
  259                 | AR5416_SLEEP1_ASSUME_DTIM);
  260 
  261         /* XXX autosleep? Use min beacon timeout; check ath9k -adrian */
  262         /* beacon timeout is now in 1/8 TU */
  263         OS_REG_WRITE(ah, AR5416_SLEEP2,
  264                 SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT));
  265 
  266         /* TIM_PERIOD and DTIM_PERIOD are now in uS. */
  267         OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
  268         OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
  269 
  270         OS_REG_SET_BIT(ah, AR_TIMER_MODE,
  271              AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM);
  272 
  273 #define HAL_TSFOOR_THRESHOLD    0x00004240 /* TSF OOR threshold (16k us) */
  274 
  275         /* TSF out of range threshold */
  276 //      OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
  277         OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, HAL_TSFOOR_THRESHOLD);
  278 
  279         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
  280             __func__, bs->bs_nextdtim);
  281         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
  282             __func__, nextTbtt);
  283         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n",
  284             __func__, beaconintval);
  285         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n",
  286             __func__, dtimperiod);
  287 #undef CAB_TIMEOUT_VAL
  288 #undef BEACON_TIMEOUT_VAL
  289 #undef SLEEP_SLOP
  290 }

Cache object: 24faef860789c2dae97796e701b63d91


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