ath9k: improve precision of beacon timer calculations
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 561-ath9k_fix_staggered_beacons.patch
1 --- a/drivers/net/wireless/ath/ath9k/beacon.c
2 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
3 @@ -57,8 +57,8 @@ int ath_beaconq_config(struct ath_softc
4
5 /*
6 * Associates the beacon frame buffer with a transmit descriptor. Will set
7 - * up all required antenna switch parameters, rate codes, and channel flags.
8 - * Beacons are always sent out at the lowest rate, and are not retried.
9 + * up rate codes, and channel flags. Beacons are always sent out at the
10 + * lowest rate, and are not retried.
11 */
12 static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
13 struct ath_buf *bf, int rateidx)
14 @@ -68,7 +68,7 @@ static void ath_beacon_setup(struct ath_
15 struct ath_common *common = ath9k_hw_common(ah);
16 struct ath_desc *ds;
17 struct ath9k_11n_rate_series series[4];
18 - int flags, antenna, ctsrate = 0, ctsduration = 0;
19 + int flags, ctsrate = 0, ctsduration = 0;
20 struct ieee80211_supported_band *sband;
21 u8 rate = 0;
22
23 @@ -76,12 +76,6 @@ static void ath_beacon_setup(struct ath_
24 flags = ATH9K_TXDESC_NOACK;
25
26 ds->ds_link = 0;
27 - /*
28 - * Switch antenna every beacon.
29 - * Should only switch every beacon period, not for every SWBA
30 - * XXX assumes two antennae
31 - */
32 - antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
33
34 sband = &sc->sbands[common->hw->conf.channel->band];
35 rate = sband->bitrates[rateidx].hw_value;
36 @@ -278,7 +272,7 @@ int ath_beacon_alloc(struct ath_softc *s
37 return -ENOMEM;
38
39 tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
40 - sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
41 + sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp);
42 /* Calculate a TSF adjustment factor required for staggered beacons. */
43 if (avp->av_bslot > 0) {
44 u64 tsfadjust;
45 @@ -294,8 +288,8 @@ int ath_beacon_alloc(struct ath_softc *s
46 * adjustment. Other slots are adjusted to get the timestamp
47 * close to the TBTT for the BSS.
48 */
49 - tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
50 - avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
51 + tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF;
52 + avp->tsf_adjust = cpu_to_le64(tsfadjust);
53
54 ath_dbg(common, ATH_DBG_BEACON,
55 "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
56 @@ -401,8 +395,9 @@ void ath_beacon_tasklet(unsigned long da
57 intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
58
59 tsf = ath9k_hw_gettsf64(ah);
60 - tsftu = TSF_TO_TU(tsf>>32, tsf);
61 - slot = ((tsftu % intval) * ATH_BCBUF) / intval;
62 + tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
63 + tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
64 + slot = (tsftu % (intval * ATH_BCBUF)) / intval;
65 /*
66 * Reverse the slot order to get slot 0 on the TBTT offset that does
67 * not require TSF adjustment and other slots adding
68 @@ -415,7 +410,7 @@ void ath_beacon_tasklet(unsigned long da
69
70 ath_dbg(common, ATH_DBG_BEACON,
71 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
72 - slot, tsf, tsftu, intval, vif);
73 + slot, tsf, tsftu / ATH_BCBUF, intval, vif);
74
75 bfaddr = 0;
76 if (vif) {
77 @@ -463,13 +458,17 @@ static void ath9k_beacon_init(struct ath
78 u32 next_beacon,
79 u32 beacon_period)
80 {
81 - if (beacon_period & ATH9K_BEACON_RESET_TSF)
82 + if (sc->sc_flags & SC_OP_TSF_RESET) {
83 ath9k_ps_wakeup(sc);
84 + ath9k_hw_reset_tsf(sc->sc_ah);
85 + }
86
87 ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
88
89 - if (beacon_period & ATH9K_BEACON_RESET_TSF)
90 + if (sc->sc_flags & SC_OP_TSF_RESET) {
91 ath9k_ps_restore(sc);
92 + sc->sc_flags &= ~SC_OP_TSF_RESET;
93 + }
94 }
95
96 /*
97 @@ -484,18 +483,14 @@ static void ath_beacon_config_ap(struct
98 u32 nexttbtt, intval;
99
100 /* NB: the beacon interval is kept internally in TU's */
101 - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
102 + intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
103 intval /= ATH_BCBUF; /* for staggered beacons */
104 nexttbtt = intval;
105
106 - if (sc->sc_flags & SC_OP_TSF_RESET)
107 - intval |= ATH9K_BEACON_RESET_TSF;
108 -
109 /*
110 * In AP mode we enable the beacon timers and SWBA interrupts to
111 * prepare beacon frames.
112 */
113 - intval |= ATH9K_BEACON_ENA;
114 ah->imask |= ATH9K_INT_SWBA;
115 ath_beaconq_config(sc);
116
117 @@ -505,11 +500,6 @@ static void ath_beacon_config_ap(struct
118 ath9k_beacon_init(sc, nexttbtt, intval);
119 sc->beacon.bmisscnt = 0;
120 ath9k_hw_set_interrupts(ah, ah->imask);
121 -
122 - /* Clear the reset TSF flag, so that subsequent beacon updation
123 - will not reset the HW TSF. */
124 -
125 - sc->sc_flags &= ~SC_OP_TSF_RESET;
126 }
127
128 /*
129 @@ -643,25 +633,20 @@ static void ath_beacon_config_adhoc(stru
130 {
131 struct ath_hw *ah = sc->sc_ah;
132 struct ath_common *common = ath9k_hw_common(ah);
133 - u64 tsf;
134 - u32 tsftu, intval, nexttbtt;
135 -
136 - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
137 -
138 + u32 tsf, delta, intval, nexttbtt;
139
140 - /* Pull nexttbtt forward to reflect the current TSF */
141 + tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
142 + intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
143
144 - nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
145 - if (nexttbtt == 0)
146 - nexttbtt = intval;
147 - else if (intval)
148 - nexttbtt = roundup(nexttbtt, intval);
149 -
150 - tsf = ath9k_hw_gettsf64(ah);
151 - tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
152 - do {
153 - nexttbtt += intval;
154 - } while (nexttbtt < tsftu);
155 + if (!sc->beacon.bc_tstamp)
156 + nexttbtt = tsf + intval;
157 + else {
158 + if (tsf > sc->beacon.bc_tstamp)
159 + delta = (tsf - sc->beacon.bc_tstamp);
160 + else
161 + delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
162 + nexttbtt = tsf + roundup(delta, intval);
163 + }
164
165 ath_dbg(common, ATH_DBG_BEACON,
166 "IBSS nexttbtt %u intval %u (%u)\n",
167 @@ -672,7 +657,6 @@ static void ath_beacon_config_adhoc(stru
168 * if we need to manually prepare beacon frames. Otherwise we use a
169 * self-linked tx descriptor and let the hardware deal with things.
170 */
171 - intval |= ATH9K_BEACON_ENA;
172 ah->imask |= ATH9K_INT_SWBA;
173
174 ath_beaconq_config(sc);
175 --- a/drivers/net/wireless/ath/ath9k/hw.c
176 +++ b/drivers/net/wireless/ath/ath9k/hw.c
177 @@ -1706,21 +1706,15 @@ void ath9k_hw_beaconinit(struct ath_hw *
178 case NL80211_IFTYPE_MESH_POINT:
179 REG_SET_BIT(ah, AR_TXCFG,
180 AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
181 - REG_WRITE(ah, AR_NEXT_NDP_TIMER,
182 - TU_TO_USEC(next_beacon +
183 - (ah->atim_window ? ah->
184 - atim_window : 1)));
185 + REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
186 + TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
187 flags |= AR_NDP_TIMER_EN;
188 case NL80211_IFTYPE_AP:
189 - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
190 - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
191 - TU_TO_USEC(next_beacon -
192 - ah->config.
193 - dma_beacon_response_time));
194 - REG_WRITE(ah, AR_NEXT_SWBA,
195 - TU_TO_USEC(next_beacon -
196 - ah->config.
197 - sw_beacon_response_time));
198 + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
199 + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon -
200 + TU_TO_USEC(ah->config.dma_beacon_response_time));
201 + REG_WRITE(ah, AR_NEXT_SWBA, next_beacon -
202 + TU_TO_USEC(ah->config.sw_beacon_response_time));
203 flags |=
204 AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
205 break;
206 @@ -1732,18 +1726,13 @@ void ath9k_hw_beaconinit(struct ath_hw *
207 break;
208 }
209
210 - REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
211 - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
212 - REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
213 - REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
214 + REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
215 + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
216 + REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
217 + REG_WRITE(ah, AR_NDP_PERIOD, beacon_period);
218
219 REGWRITE_BUFFER_FLUSH(ah);
220
221 - beacon_period &= ~ATH9K_BEACON_ENA;
222 - if (beacon_period & ATH9K_BEACON_RESET_TSF) {
223 - ath9k_hw_reset_tsf(ah);
224 - }
225 -
226 REG_SET_BIT(ah, AR_TIMER_MODE, flags);
227 }
228 EXPORT_SYMBOL(ath9k_hw_beaconinit);
229 @@ -2404,10 +2393,11 @@ static u32 rightmost_index(struct ath_ge
230 return timer_table->gen_timer_index[b];
231 }
232
233 -static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
234 +u32 ath9k_hw_gettsf32(struct ath_hw *ah)
235 {
236 return REG_READ(ah, AR_TSF_L32);
237 }
238 +EXPORT_SYMBOL(ath9k_hw_gettsf32);
239
240 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
241 void (*trigger)(void *),
242 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
243 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
244 @@ -392,7 +392,7 @@ struct ath_beacon {
245 u32 beaconq;
246 u32 bmisscnt;
247 u32 ast_be_xmit;
248 - u64 bc_tstamp;
249 + u32 bc_tstamp;
250 struct ieee80211_vif *bslot[ATH_BCBUF];
251 int slottime;
252 int slotupdate;
253 --- a/drivers/net/wireless/ath/ath9k/hw.h
254 +++ b/drivers/net/wireless/ath/ath9k/hw.h
255 @@ -412,8 +412,6 @@ struct ath9k_beacon_state {
256 u32 bs_nextdtim;
257 u32 bs_intval;
258 #define ATH9K_BEACON_PERIOD 0x0000ffff
259 -#define ATH9K_BEACON_ENA 0x00800000
260 -#define ATH9K_BEACON_RESET_TSF 0x01000000
261 #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
262 u32 bs_dtimperiod;
263 u16 bs_cfpperiod;
264 @@ -927,6 +925,7 @@ void ath9k_hw_setopmode(struct ath_hw *a
265 void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
266 void ath9k_hw_setbssidmask(struct ath_hw *ah);
267 void ath9k_hw_write_associd(struct ath_hw *ah);
268 +u32 ath9k_hw_gettsf32(struct ath_hw *ah);
269 u64 ath9k_hw_gettsf64(struct ath_hw *ah);
270 void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
271 void ath9k_hw_reset_tsf(struct ath_hw *ah);
272 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
273 +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
274 @@ -155,7 +155,7 @@ static void ath9k_htc_beacon_config_ap(s
275 nexttbtt = intval;
276
277 if (priv->op_flags & OP_TSF_RESET) {
278 - intval |= ATH9K_BEACON_RESET_TSF;
279 + ath9k_hw_reset_tsf(priv->ah);
280 priv->op_flags &= ~OP_TSF_RESET;
281 } else {
282 /*
283 @@ -168,8 +168,6 @@ static void ath9k_htc_beacon_config_ap(s
284 } while (nexttbtt < tsftu);
285 }
286
287 - intval |= ATH9K_BEACON_ENA;
288 -
289 if (priv->op_flags & OP_ENABLE_BEACON)
290 imask |= ATH9K_INT_SWBA;
291
292 @@ -178,7 +176,7 @@ static void ath9k_htc_beacon_config_ap(s
293 bss_conf->beacon_interval, nexttbtt, imask);
294
295 WMI_CMD(WMI_DISABLE_INTR_CMDID);
296 - ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
297 + ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
298 priv->bmiss_cnt = 0;
299 htc_imask = cpu_to_be32(imask);
300 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
301 @@ -207,7 +205,6 @@ static void ath9k_htc_beacon_config_adho
302 nexttbtt += intval;
303 } while (nexttbtt < tsftu);
304
305 - intval |= ATH9K_BEACON_ENA;
306 if (priv->op_flags & OP_ENABLE_BEACON)
307 imask |= ATH9K_INT_SWBA;
308
309 @@ -216,7 +213,7 @@ static void ath9k_htc_beacon_config_adho
310 bss_conf->beacon_interval, nexttbtt, imask);
311
312 WMI_CMD(WMI_DISABLE_INTR_CMDID);
313 - ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
314 + ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
315 priv->bmiss_cnt = 0;
316 htc_imask = cpu_to_be32(imask);
317 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);