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/contrib/dev/ath/ath_hal/ar9300/ar9300_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  * Copyright (c) 2013 Qualcomm Atheros, Inc.
    3  *
    4  * Permission to use, copy, modify, and/or distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   14  * PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include "opt_ah.h"
   18 
   19 #include "ah.h"
   20 #include "ah_internal.h"
   21 
   22 #include "ar9300/ar9300.h"
   23 #include "ar9300/ar9300reg.h"
   24 
   25 #define TU_TO_USEC(_tu) ((_tu) << 10)
   26 #define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7)
   27 
   28 extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q);
   29 
   30 /*
   31  * Initializes all of the hardware registers used to
   32  * send beacons.  Note that for station operation the
   33  * driver calls ar9300_set_sta_beacon_timers instead.
   34  */
   35 void
   36 ar9300_beacon_init(struct ath_hal *ah,
   37     u_int32_t next_beacon, u_int32_t beacon_period, 
   38     u_int32_t beacon_period_fraction, HAL_OPMODE opmode)
   39 {
   40     u_int32_t               beacon_period_usec;
   41 
   42     HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP);
   43     if (opmode == HAL_M_IBSS) {
   44         OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
   45     }
   46     OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, ONE_EIGHTH_TU_TO_USEC(next_beacon));
   47     OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
   48         (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
   49         ah->ah_config.ah_dma_beacon_response_time));
   50     OS_REG_WRITE(ah, AR_NEXT_SWBA,
   51         (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
   52         ah->ah_config.ah_sw_beacon_response_time));
   53 
   54     beacon_period_usec =
   55         ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8);
   56 
   57     /* Add the fraction adjustment lost due to unit conversions. */
   58     beacon_period_usec += beacon_period_fraction;
   59 
   60     HALDEBUG(ah, HAL_DEBUG_BEACON,
   61         "%s: next_beacon=0x%08x, beacon_period=%d, opmode=%d, beacon_period_usec=%d\n",
   62         __func__, next_beacon, beacon_period, opmode, beacon_period_usec);
   63 
   64     OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec);
   65     OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec);
   66     OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec);
   67 
   68     /* reset TSF if required */
   69     if (beacon_period & HAL_BEACON_RESET_TSF) {
   70         ar9300_reset_tsf(ah);
   71     }
   72 
   73     /* enable timers */
   74     OS_REG_SET_BIT(ah, AR_TIMER_MODE,
   75         AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN);
   76 }
   77 
   78 /*
   79  * Set all the beacon related bits on the h/w for stations
   80  * i.e. initializes the corresponding h/w timers;
   81  */
   82 void
   83 ar9300_set_sta_beacon_timers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
   84 {
   85     u_int32_t next_tbtt, beaconintval, dtimperiod, beacontimeout;
   86     HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
   87 
   88     HALASSERT(bs->bs_intval != 0);
   89 
   90     /* no cfp setting since h/w automatically takes care */
   91     OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
   92 
   93     /*
   94      * Start the beacon timers by setting the BEACON register
   95      * to the beacon interval; no need to write tim offset since
   96      * h/w parses IEs.
   97      */
   98     OS_REG_WRITE(ah, AR_BEACON_PERIOD,
   99                  TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
  100     OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
  101                  TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
  102     /*
  103      * Configure the BMISS interrupt.  Note that we
  104      * assume the caller blocks interrupts while enabling
  105      * the threshold.
  106      */
  107     HALASSERT(bs->bs_bmissthreshold <=
  108         (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
  109     OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
  110         AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
  111 
  112     /*
  113      * Program the sleep registers to correlate with the beacon setup.
  114      */
  115 
  116     /*
  117      * Current implementation assumes sw processing of beacons -
  118      * assuming an interrupt is generated every beacon which
  119      * causes the hardware to become awake until the sw tells
  120      * it to go to sleep again; beacon timeout is to allow for
  121      * beacon jitter; cab timeout is max time to wait for cab
  122      * after seeing the last DTIM or MORE CAB bit
  123      */
  124 #define CAB_TIMEOUT_VAL         10 /* in TU */
  125 #define BEACON_TIMEOUT_VAL      10 /* in TU */
  126 #define MIN_BEACON_TIMEOUT_VAL   1 /* in 1/8 TU */
  127 #define SLEEP_SLOP               3 /* in TU */
  128 
  129     /*
  130      * For max powersave mode we may want to sleep for longer than a
  131      * beacon period and not want to receive all beacons; modify the
  132      * timers accordingly; make sure to align the next TIM to the
  133      * next DTIM if we decide to wake for DTIMs only
  134      */
  135     beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
  136     HALASSERT(beaconintval != 0);
  137     if (bs->bs_sleepduration > beaconintval) {
  138         HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
  139                 bs->bs_sleepduration);
  140         beaconintval = bs->bs_sleepduration;
  141     }
  142     dtimperiod = bs->bs_dtimperiod;
  143     if (bs->bs_sleepduration > dtimperiod) {
  144         HALASSERT(dtimperiod == 0 ||
  145             roundup(bs->bs_sleepduration, dtimperiod) ==
  146                 bs->bs_sleepduration);
  147         dtimperiod = bs->bs_sleepduration;
  148     }
  149     HALASSERT(beaconintval <= dtimperiod);
  150     if (beaconintval == dtimperiod) {
  151         next_tbtt = bs->bs_nextdtim;
  152     } else {
  153         next_tbtt = bs->bs_nexttbtt;
  154     }
  155 
  156     HALDEBUG(ah, HAL_DEBUG_BEACON,
  157         "%s: next DTIM %d\n", __func__, bs->bs_nextdtim);
  158     HALDEBUG(ah, HAL_DEBUG_BEACON,
  159         "%s: next beacon %d\n", __func__, next_tbtt);
  160     HALDEBUG(ah, HAL_DEBUG_BEACON,
  161         "%s: beacon period %d\n", __func__, beaconintval);
  162     HALDEBUG(ah, HAL_DEBUG_BEACON,
  163         "%s: DTIM period %d\n", __func__, dtimperiod);
  164 
  165     OS_REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
  166     OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(next_tbtt - SLEEP_SLOP));
  167 
  168     /* cab timeout is now in 1/8 TU */
  169     OS_REG_WRITE(ah, AR_SLEEP1,
  170         SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
  171         | AR_SLEEP1_ASSUME_DTIM);
  172 
  173     /* beacon timeout is now in 1/8 TU */
  174     if (p_cap->halAutoSleepSupport) {
  175         beacontimeout = (BEACON_TIMEOUT_VAL << 3);
  176     } else {
  177         /*
  178          * Use a very small value to make sure the timeout occurs before
  179          * the TBTT.  In this case the chip will not go back to sleep
  180          * automatically, instead it will wait for the SW to explicitly
  181          * set it to that mode.
  182          */
  183         beacontimeout = MIN_BEACON_TIMEOUT_VAL;
  184     }
  185 
  186     OS_REG_WRITE(ah, AR_SLEEP2,
  187         SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
  188 
  189     OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
  190     OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
  191 
  192     /* clear HOST AP related timers first */    
  193     OS_REG_CLR_BIT(ah, AR_TIMER_MODE, (AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN));
  194 
  195     OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN
  196                     | AR_DTIM_TIMER_EN);
  197 
  198     /* TSF out of range threshold */
  199     OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
  200 
  201 #undef CAB_TIMEOUT_VAL
  202 #undef BEACON_TIMEOUT_VAL
  203 #undef SLEEP_SLOP
  204 }

Cache object: 4d3ef1f483a62ea30b873310961ddfa5


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