ar5416_beacon.c revision 185380
1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $Id: ar5416_beacon.c,v 1.8 2008/11/11 01:03:12 sam Exp $ 18 */ 19#include "opt_ah.h" 20 21#ifdef AH_SUPPORT_AR5416 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 32/* 33 * Initialize all of the hardware registers used to 34 * send beacons. Note that for station operation the 35 * driver calls ar5416SetStaBeaconTimers instead. 36 */ 37void 38ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt) 39{ 40 uint32_t bperiod; 41 42 OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt)); 43 OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3); 44 OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3); 45 OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim)); 46 47 bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD); 48 OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, bperiod); 49 OS_REG_WRITE(ah, AR_DBA_PERIOD, bperiod); 50 OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod); 51 OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod); 52 53 /* 54 * Reset TSF if required. 55 */ 56 if (bt->bt_intval & AR_BEACON_RESET_TSF) 57 ar5416ResetTsf(ah); 58 59 /* enable timers */ 60 /* NB: flags == 0 handled specially for backwards compatibility */ 61 OS_REG_SET_BIT(ah, AR_TIMER_MODE, 62 bt->bt_flags != 0 ? bt->bt_flags : 63 AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA); 64} 65 66/* 67 * Initializes all of the hardware registers used to 68 * send beacons. Note that for station operation the 69 * driver calls ar5212SetStaBeaconTimers instead. 70 */ 71void 72ar5416BeaconInit(struct ath_hal *ah, 73 uint32_t next_beacon, uint32_t beacon_period) 74{ 75 HAL_BEACON_TIMERS bt; 76 77 bt.bt_nexttbtt = next_beacon; 78 /* 79 * TIMER1: in AP/adhoc mode this controls the DMA beacon 80 * alert timer; otherwise it controls the next wakeup time. 81 * TIMER2: in AP mode, it controls the SBA beacon alert 82 * interrupt; otherwise it sets the start of the next CFP. 83 */ 84 bt.bt_flags = 0; 85 switch (AH_PRIVATE(ah)->ah_opmode) { 86 case HAL_M_STA: 87 case HAL_M_MONITOR: 88 bt.bt_nextdba = 0xffff; 89 bt.bt_nextswba = 0x7ffff; 90 bt.bt_flags |= AR_TIMER_MODE_TBTT; 91 break; 92 case HAL_M_IBSS: 93 OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ATIM_TXPOLICY); 94 bt.bt_flags |= AR_TIMER_MODE_NDP; 95 /* fall thru... */ 96 case HAL_M_HOSTAP: 97 bt.bt_nextdba = (next_beacon - 98 ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ 99 bt.bt_nextswba = (next_beacon - 100 ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ 101 bt.bt_flags |= AR_TIMER_MODE_TBTT 102 | AR_TIMER_MODE_DBA 103 | AR_TIMER_MODE_SWBA; 104 break; 105 } 106 /* 107 * Set the ATIM window 108 * Our hardware does not support an ATIM window of 0 109 * (beacons will not work). If the ATIM windows is 0, 110 * force it to 1. 111 */ 112 bt.bt_nextatim = next_beacon + 1; 113 bt.bt_intval = beacon_period & 114 (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN); 115 ar5416SetBeaconTimers(ah, &bt); 116} 117 118#define AR_BEACON_PERIOD_MAX 0xffff 119 120void 121ar5416ResetStaBeaconTimers(struct ath_hal *ah) 122{ 123 uint32_t val; 124 125 OS_REG_WRITE(ah, AR_NEXT_TBTT, 0); /* no beacons */ 126 val = OS_REG_READ(ah, AR_STA_ID1); 127 val |= AR_STA_ID1_PWR_SAV; /* XXX */ 128 /* tell the h/w that the associated AP is not PCF capable */ 129 OS_REG_WRITE(ah, AR_STA_ID1, 130 val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF)); 131 OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, AR_BEACON_PERIOD_MAX); 132 OS_REG_WRITE(ah, AR_DBA_PERIOD, AR_BEACON_PERIOD_MAX); 133} 134 135/* 136 * Set all the beacon related bits on the h/w for stations 137 * i.e. initializes the corresponding h/w timers; 138 * also tells the h/w whether to anticipate PCF beacons 139 */ 140void 141ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) 142{ 143 uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; 144 145 HALASSERT(bs->bs_intval != 0); 146 147 /* NB: no cfp setting since h/w automatically takes care */ 148 149 OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt); 150 151 /* 152 * Start the beacon timers by setting the BEACON register 153 * to the beacon interval; no need to write tim offset since 154 * h/w parses IEs. 155 */ 156 OS_REG_WRITE(ah, AR5416_BEACON_PERIOD, 157 TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); 158 OS_REG_WRITE(ah, AR_DBA_PERIOD, 159 TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); 160 161 /* 162 * Configure the BMISS interrupt. Note that we 163 * assume the caller blocks interrupts while enabling 164 * the threshold. 165 */ 166 HALASSERT(bs->bs_bmissthreshold <= 167 (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S)); 168 OS_REG_RMW_FIELD(ah, AR_RSSI_THR, 169 AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); 170 171 /* 172 * Program the sleep registers to correlate with the beacon setup. 173 */ 174 175 /* 176 * Oahu beacons timers on the station were used for power 177 * save operation (waking up in anticipation of a beacon) 178 * and any CFP function; Venice does sleep/power-save timers 179 * differently - so this is the right place to set them up; 180 * don't think the beacon timers are used by venice sta hw 181 * for any useful purpose anymore 182 * Setup venice's sleep related timers 183 * Current implementation assumes sw processing of beacons - 184 * assuming an interrupt is generated every beacon which 185 * causes the hardware to become awake until the sw tells 186 * it to go to sleep again; beacon timeout is to allow for 187 * beacon jitter; cab timeout is max time to wait for cab 188 * after seeing the last DTIM or MORE CAB bit 189 */ 190#define CAB_TIMEOUT_VAL 10 /* in TU */ 191#define BEACON_TIMEOUT_VAL 10 /* in TU */ 192#define SLEEP_SLOP 3 /* in TU */ 193 194 /* 195 * For max powersave mode we may want to sleep for longer than a 196 * beacon period and not want to receive all beacons; modify the 197 * timers accordingly; make sure to align the next TIM to the 198 * next DTIM if we decide to wake for DTIMs only 199 */ 200 beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; 201 HALASSERT(beaconintval != 0); 202 if (bs->bs_sleepduration > beaconintval) { 203 HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == 204 bs->bs_sleepduration); 205 beaconintval = bs->bs_sleepduration; 206 } 207 dtimperiod = bs->bs_dtimperiod; 208 if (bs->bs_sleepduration > dtimperiod) { 209 HALASSERT(dtimperiod == 0 || 210 roundup(bs->bs_sleepduration, dtimperiod) == 211 bs->bs_sleepduration); 212 dtimperiod = bs->bs_sleepduration; 213 } 214 HALASSERT(beaconintval <= dtimperiod); 215 if (beaconintval == dtimperiod) 216 nextTbtt = bs->bs_nextdtim; 217 else 218 nextTbtt = bs->bs_nexttbtt; 219 nextdtim = bs->bs_nextdtim; 220 221 OS_REG_WRITE(ah, AR_NEXT_DTIM, 222 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); 223 OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); 224 225 /* cab timeout is now in 1/8 TU */ 226 OS_REG_WRITE(ah, AR_SLEEP1, 227 SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT) 228 | AR_SLEEP1_ASSUME_DTIM); 229 /* beacon timeout is now in 1/8 TU */ 230 OS_REG_WRITE(ah, AR_SLEEP2, 231 SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT)); 232 233 OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); 234 OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); 235 OS_REG_SET_BIT(ah, AR_TIMER_MODE, 236 AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM); 237 HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", 238 __func__, bs->bs_nextdtim); 239 HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", 240 __func__, nextTbtt); 241 HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", 242 __func__, beaconintval); 243 HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", 244 __func__, dtimperiod); 245#undef CAB_TIMEOUT_VAL 246#undef BEACON_TIMEOUT_VAL 247#undef SLEEP_SLOP 248} 249#endif /* AH_SUPPORT_AR5416 */ 250