Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2008-2011 Atheros Communications 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
9 : : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 : : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 : : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 : : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 : : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 : : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 : : */
16 : :
17 : : #include "common.h"
18 : :
19 : : #define FUDGE 2
20 : :
21 : 0 : static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf,
22 : : unsigned int interval)
23 : : {
24 : 0 : unsigned int offset, divisor;
25 : :
26 : 0 : tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
27 : 0 : divisor = TU_TO_USEC(interval);
28 : 0 : div_u64_rem(tsf, divisor, &offset);
29 : :
30 : 0 : return (u32) tsf + divisor - offset;
31 : : }
32 : :
33 : : /*
34 : : * This sets up the beacon timers according to the timestamp of the last
35 : : * received beacon and the current TSF, configures PCF and DTIM
36 : : * handling, programs the sleep registers so the hardware will wakeup in
37 : : * time to receive beacons, and configures the beacon miss handling so
38 : : * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
39 : : * we've associated with.
40 : : */
41 : 0 : int ath9k_cmn_beacon_config_sta(struct ath_hw *ah,
42 : : struct ath_beacon_config *conf,
43 : : struct ath9k_beacon_state *bs)
44 : : {
45 : 0 : struct ath_common *common = ath9k_hw_common(ah);
46 : 0 : int dtim_intval;
47 : 0 : u64 tsf;
48 : :
49 : : /* No need to configure beacon if we are not associated */
50 [ # # ]: 0 : if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
51 [ # # ]: 0 : ath_dbg(common, BEACON,
52 : : "STA is not yet associated..skipping beacon config\n");
53 : 0 : return -EPERM;
54 : : }
55 : :
56 : 0 : memset(bs, 0, sizeof(*bs));
57 : 0 : conf->intval = conf->beacon_interval;
58 : :
59 : : /*
60 : : * Setup dtim parameters according to
61 : : * last beacon we received (which may be none).
62 : : */
63 : 0 : dtim_intval = conf->intval * conf->dtim_period;
64 : :
65 : : /*
66 : : * Pull nexttbtt forward to reflect the current
67 : : * TSF and calculate dtim state for the result.
68 : : */
69 : 0 : tsf = ath9k_hw_gettsf64(ah);
70 [ # # ]: 0 : conf->nexttbtt = ath9k_get_next_tbtt(ah, tsf, conf->intval);
71 : :
72 : 0 : bs->bs_intval = TU_TO_USEC(conf->intval);
73 : 0 : bs->bs_dtimperiod = conf->dtim_period * bs->bs_intval;
74 : 0 : bs->bs_nexttbtt = conf->nexttbtt;
75 : 0 : bs->bs_nextdtim = conf->nexttbtt;
76 [ # # ]: 0 : if (conf->dtim_period > 1)
77 : 0 : bs->bs_nextdtim = ath9k_get_next_tbtt(ah, tsf, dtim_intval);
78 : :
79 : : /*
80 : : * Calculate the number of consecutive beacons to miss* before taking
81 : : * a BMISS interrupt. The configuration is specified in TU so we only
82 : : * need calculate based on the beacon interval. Note that we clamp the
83 : : * result to at most 15 beacons.
84 : : */
85 : 0 : bs->bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, conf->intval);
86 [ # # ]: 0 : if (bs->bs_bmissthreshold > 15)
87 : 0 : bs->bs_bmissthreshold = 15;
88 [ # # ]: 0 : else if (bs->bs_bmissthreshold <= 0)
89 : 0 : bs->bs_bmissthreshold = 1;
90 : :
91 : : /*
92 : : * Calculate sleep duration. The configuration is given in ms.
93 : : * We ensure a multiple of the beacon period is used. Also, if the sleep
94 : : * duration is greater than the DTIM period then it makes senses
95 : : * to make it a multiple of that.
96 : : *
97 : : * XXX fixed at 100ms
98 : : */
99 : :
100 : 0 : bs->bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
101 : : conf->intval));
102 [ # # ]: 0 : if (bs->bs_sleepduration > bs->bs_dtimperiod)
103 : 0 : bs->bs_sleepduration = bs->bs_dtimperiod;
104 : :
105 : : /* TSF out of range threshold fixed at 1 second */
106 : 0 : bs->bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
107 : :
108 [ # # ]: 0 : ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n",
109 : : bs->bs_bmissthreshold, bs->bs_sleepduration);
110 : : return 0;
111 : : }
112 : : EXPORT_SYMBOL(ath9k_cmn_beacon_config_sta);
113 : :
114 : 0 : void ath9k_cmn_beacon_config_adhoc(struct ath_hw *ah,
115 : : struct ath_beacon_config *conf)
116 : : {
117 [ # # ]: 0 : struct ath_common *common = ath9k_hw_common(ah);
118 : :
119 : 0 : conf->intval = TU_TO_USEC(conf->beacon_interval);
120 : :
121 [ # # ]: 0 : if (conf->ibss_creator)
122 : 0 : conf->nexttbtt = conf->intval;
123 : : else
124 : 0 : conf->nexttbtt = ath9k_get_next_tbtt(ah, ath9k_hw_gettsf64(ah),
125 : : conf->beacon_interval);
126 : :
127 [ # # ]: 0 : if (conf->enable_beacon)
128 : 0 : ah->imask |= ATH9K_INT_SWBA;
129 : : else
130 : 0 : ah->imask &= ~ATH9K_INT_SWBA;
131 : :
132 [ # # # # ]: 0 : ath_dbg(common, BEACON,
133 : : "IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
134 : : (conf->enable_beacon) ? "Enable" : "Disable",
135 : : conf->nexttbtt, conf->intval, conf->beacon_interval);
136 : 0 : }
137 : : EXPORT_SYMBOL(ath9k_cmn_beacon_config_adhoc);
138 : :
139 : : /*
140 : : * For multi-bss ap support beacons are either staggered evenly over N slots or
141 : : * burst together. For the former arrange for the SWBA to be delivered for each
142 : : * slot. Slots that are not occupied will generate nothing.
143 : : */
144 : 0 : void ath9k_cmn_beacon_config_ap(struct ath_hw *ah,
145 : : struct ath_beacon_config *conf,
146 : : unsigned int bc_buf)
147 : : {
148 : 0 : struct ath_common *common = ath9k_hw_common(ah);
149 : :
150 : : /* NB: the beacon interval is kept internally in TU's */
151 : 0 : conf->intval = TU_TO_USEC(conf->beacon_interval);
152 : 0 : conf->intval /= bc_buf;
153 [ # # ]: 0 : conf->nexttbtt = ath9k_get_next_tbtt(ah, ath9k_hw_gettsf64(ah),
154 : : conf->beacon_interval);
155 : :
156 [ # # ]: 0 : if (conf->enable_beacon)
157 : 0 : ah->imask |= ATH9K_INT_SWBA;
158 : : else
159 : 0 : ah->imask &= ~ATH9K_INT_SWBA;
160 : :
161 [ # # # # ]: 0 : ath_dbg(common, BEACON,
162 : : "AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
163 : : (conf->enable_beacon) ? "Enable" : "Disable",
164 : : conf->nexttbtt, conf->intval, conf->beacon_interval);
165 : 0 : }
166 : : EXPORT_SYMBOL(ath9k_cmn_beacon_config_ap);
|