1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
Index: madwifi-ng-r2834-20071106/ath/if_ath.c
===================================================================
--- madwifi-ng-r2834-20071106.orig/ath/if_ath.c 2007-11-07 14:02:01.785472625 +0100
+++ madwifi-ng-r2834-20071106/ath/if_ath.c 2007-11-07 14:02:02.637521177 +0100
@@ -4559,16 +4559,31 @@
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni;
- u_int32_t nexttbtt, intval;
+ u_int32_t nexttbtt = 0;
+ u_int32_t intval;
+ u_int64_t tsf, hw_tsf;
+ u_int32_t tsftu, hw_tsftu;
+ int should_reset_tsf = 0;
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
ni = vap->iv_bss;
- /* extract tstamp from last beacon and convert to TU */
- nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4),
- LE_READ_4(ni->ni_tstamp.data));
+ hw_tsf = ath_hal_gettsf64(ah);
+ tsf = le64_to_cpu(ni->ni_tstamp.tsf);
+ hw_tsftu = hw_tsf >> 10;
+ tsftu = tsf >> 10;
+
+ /* we should reset hw TSF only once, so we increment
+ ni_tstamp.tsf to avoid resetting the hw TSF multiple
+ times */
+
+ if (tsf == 0) {
+ should_reset_tsf = 1;
+ ni->ni_tstamp.tsf = cpu_to_le64(1);
+ }
+
/* XXX conditionalize multi-bss support? */
if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
/*
@@ -4582,20 +4597,61 @@
if (sc->sc_stagbeacons)
intval /= ATH_BCBUF; /* for staggered beacons */
if ((sc->sc_nostabeacons) &&
- (vap->iv_opmode == IEEE80211_M_HOSTAP))
- nexttbtt = 0;
+ (vap->iv_opmode == IEEE80211_M_HOSTAP))
+ should_reset_tsf = 1;
} else
intval = ni->ni_intval & HAL_BEACON_PERIOD;
- if (nexttbtt == 0) /* e.g. for ap mode */
+
+#define FUDGE 2
+ sc->sc_syncbeacon = 0;
+ if (should_reset_tsf) {
+
+ /* We just created the interface and TSF will be reset to
+ zero, so next beacon will be sent at the next intval
+ time */
+
nexttbtt = intval;
- else if (intval) /* NB: can be 0 for monitor mode */
- nexttbtt = roundup(nexttbtt, intval);
- DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
- __func__, nexttbtt, intval, ni->ni_intval);
+ } else if (intval) { /* NB: can be 0 for monitor mode */
+ if (tsf == 1) {
+
+ /* We do not receive any beacons or probe response. Since
+ a beacon should be sent every 'intval' ms, we compute
+ the next beacon timestamp using the hardware TSF. We
+ ensure that it is at least FUDGE ms ahead of the
+ current TSF. Otherwise, we use the next beacon
+ timestamp again */
+
+ nexttbtt = roundup(hw_tsftu +1, intval);
+ while (nexttbtt <= hw_tsftu + FUDGE) {
+ nexttbtt += intval;
+ }
+ } else {
+ if (tsf > hw_tsf) {
+
+ /* We do receive a beacon from someone else in the past,
+ but the hw TSF has not been updated (otherwise we
+ would have tsf >= hw_tsf). Since we cannot use the
+ hardware TSF, we will do nothing and wait for the
+ next beacon. In order to do so, we set sc->syncbeacon
+ again */
+
+ sc->sc_syncbeacon = 1;
+ goto ath_beacon_config_debug;
+ } else {
+ /* We do receive a beacon in the past, normal case. We
+ make sure that the timestamp is at least FUDGE ms
+ ahead of the hardware TSF */
+
+ nexttbtt = tsftu + intval;
+ while (nexttbtt <= hw_tsftu + FUDGE) {
+ nexttbtt += intval;
+ }
+ }
+ }
+ }
+
if (ic->ic_opmode == IEEE80211_M_STA && !(sc->sc_nostabeacons)) {
HAL_BEACON_STATE bs;
- u_int64_t tsf;
- u_int32_t tsftu;
int dtimperiod, dtimcount;
int cfpperiod, cfpcount;
@@ -4611,13 +4667,13 @@
dtimcount = 0; /* XXX? */
cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
-#define FUDGE 2
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
*/
- tsf = ath_hal_gettsf64(ah);
- tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+ nexttbtt = tsftu;
+ if (nexttbtt == 0) /* e.g. for ap mode */
+ nexttbtt = intval;
do {
nexttbtt += intval;
if (--dtimcount < 0) {
@@ -4625,7 +4681,7 @@
if (--cfpcount < 0)
cfpcount = cfpperiod - 1;
}
- } while (nexttbtt < tsftu);
+ } while (nexttbtt < hw_tsftu + FUDGE);
#undef FUDGE
memset(&bs, 0, sizeof(bs));
bs.bs_intval = intval;
@@ -4677,7 +4733,7 @@
DPRINTF(sc, ATH_DEBUG_BEACON,
"%s: tsf %llu tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n",
__func__,
- (unsigned long long) tsf, tsftu,
+ (unsigned long long) hw_tsf, hw_tsftu,
bs.bs_intval,
bs.bs_nexttbtt,
bs.bs_dtimperiod,
@@ -4699,7 +4755,7 @@
ath_hal_intrset(ah, sc->sc_imask);
} else {
ath_hal_intrset(ah, 0);
- if (nexttbtt == intval)
+ if (should_reset_tsf)
intval |= HAL_BEACON_RESET_TSF;
if (ic->ic_opmode == IEEE80211_M_IBSS) {
/*
@@ -4736,8 +4792,40 @@
if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
ath_beacon_start_adhoc(sc, vap);
}
- sc->sc_syncbeacon = 0;
#undef TSF_TO_TU
+
+ ath_beacon_config_debug:
+
+ /* we print all debug messages here, in order to preserve the
+ time critical aspect of this function */
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: ni=%p tsf=%llu hw_tsf=%llu tsftu=%u hw_tsftu=%u\n",
+ __func__, ni, tsf, hw_tsf, tsftu, hw_tsftu);
+
+ if (should_reset_tsf) {
+ /* we just created the interface */
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: first beacon\n",__func__);
+ } else {
+ if (tsf == 1) {
+ /* we do not receive any beacons or probe response */
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: no beacon received...\n",__func__);
+ } else {
+ if (tsf > hw_tsf) {
+ /* we do receive a beacon and the hw TSF has not been updated */
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: beacon received, but TSF is incorrect\n",__func__);
+ } else {
+ /* we do receive a beacon in the past, normal case */
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: beacon received, TSF is correct\n",__func__);
+ }
+ }
+ }
+
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt=%u intval=%u\n",
+ __func__,nexttbtt, intval & HAL_BEACON_PERIOD);
}
static int
|