Root/package/madwifi/patches/375-atim_tsf_update.patch

1--- a/ath/if_ath.c
2+++ b/ath/if_ath.c
3@@ -161,6 +161,7 @@ static void ath_beacon_send(struct ath_s
4 static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
5 static void ath_beacon_free(struct ath_softc *);
6 static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
7+static void ath_hw_beacon_stop(struct ath_softc *sc);
8 static int ath_desc_alloc(struct ath_softc *);
9 static void ath_desc_free(struct ath_softc *);
10 static void ath_desc_swap(struct ath_desc *);
11@@ -2793,6 +2794,72 @@ ath_set_ack_bitrate(struct ath_softc *sc
12     return 1;
13 }
14 
15+static void
16+ath_hw_beacon_stop(struct ath_softc *sc)
17+{
18+ HAL_BEACON_TIMERS btimers;
19+
20+ btimers.bt_intval = 0;
21+ btimers.bt_nexttbtt = 0;
22+ btimers.bt_nextdba = 0xffffffff;
23+ btimers.bt_nextswba = 0xffffffff;
24+ btimers.bt_nextatim = 0;
25+
26+ ath_hal_setbeacontimers(sc->sc_ah, &btimers);
27+}
28+
29+/* Fix up the ATIM window after TSF resync */
30+static int
31+ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
32+{
33+#define AR5K_TIMER0_5210 0x802c /* Next beacon time register */
34+#define AR5K_TIMER0_5211 0x8028
35+#define AR5K_TIMER3_5210 0x8038 /* End of ATIM window time register */
36+#define AR5K_TIMER3_5211 0x8034
37+ struct ath_hal *ah = sc->sc_ah;
38+ int dev = sc->sc_ah->ah_macType;
39+ unsigned int nbtt, atim;
40+ int is_5210 = 0;
41+
42+ /*
43+ * check if the ATIM window is still correct:
44+ * 1.) usually ATIM should be NBTT + window
45+ * 2.) nbtt already updated
46+ * 3.) nbtt already updated and has wrapped around
47+ * 4.) atim has wrapped around
48+ */
49+ switch(dev) {
50+ case 5210:
51+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
52+ atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
53+ is_5210 = 1;
54+ break;
55+ case 5211:
56+ case 5212:
57+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
58+ atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
59+ break;
60+ /* NB: 5416+ doesn't do ATIM in hw */
61+ case 5416:
62+ default:
63+ return 0;
64+ }
65+
66+ if ((atim - nbtt != window) && /* 1.) */
67+ (nbtt - atim != intval - window) && /* 2.) */
68+ ((nbtt | 0x10000) - atim != intval - window) && /* 3.) */
69+ ((atim | 0x10000) - nbtt != window)) { /* 4.) */
70+ if (is_5210)
71+ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
72+ else
73+ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
74+ return atim - nbtt;
75+ }
76+
77+ return 0;
78+}
79+
80+
81 /*
82  * Reset the hardware w/o losing operational state. This is
83  * basically a more efficient way of doing ath_stop, ath_init,
84@@ -5294,6 +5361,7 @@ ath_beacon_config(struct ath_softc *sc,
85     u_int64_t tsf, hw_tsf;
86     u_int32_t tsftu, hw_tsftu;
87     u_int32_t intval, nexttbtt = 0;
88+ unsigned long flags;
89     int reset_tsf = 0;
90 
91     if (vap == NULL)
92@@ -5301,6 +5369,9 @@ ath_beacon_config(struct ath_softc *sc,
93 
94     ni = vap->iv_bss;
95 
96+ /* TSF calculation is timing critical - we don't want to be interrupted here */
97+ local_irq_save(flags);
98+
99     hw_tsf = ath_hal_gettsf64(ah);
100     tsf = le64_to_cpu(ni->ni_tstamp.tsf);
101     hw_tsftu = hw_tsf >> 10;
102@@ -5490,15 +5561,27 @@ ath_beacon_config(struct ath_softc *sc,
103                 <= ath_hal_sw_beacon_response_time)
104             nexttbtt += intval;
105         sc->sc_nexttbtt = nexttbtt;
106+
107+ /* stop beacons before reconfiguring the timers to avoid race
108+ * conditions. ath_hal_beaconinit will start them again */
109+ ath_hw_beacon_stop(sc);
110+
111         ath_hal_beaconinit(ah, nexttbtt, intval);
112         if (intval & HAL_BEACON_RESET_TSF) {
113             sc->sc_last_tsf = 0;
114         }
115         sc->sc_bmisscount = 0;
116         ath_hal_intrset(ah, sc->sc_imask);
117+
118+ if ((sc->sc_opmode == HAL_M_IBSS) && ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) {
119+ DPRINTF(sc, ATH_DEBUG_BEACON,
120+ "fixed atim window after beacon init\n");
121+ }
122     }
123 
124 ath_beacon_config_debug:
125+ local_irq_restore(flags);
126+
127     /* We print all debug messages here, in order to preserve the
128      * time critical aspect of this function */
129     DPRINTF(sc, ATH_DEBUG_BEACON,
130@@ -6401,6 +6484,11 @@ ath_recv_mgmt(struct ieee80211vap * vap,
131             DPRINTF(sc, ATH_DEBUG_BEACON,
132                 "Updated beacon timers\n");
133         }
134+ if ((sc->sc_opmode == HAL_M_IBSS) &&
135+ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
136+ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
137+ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
138+ }
139         /* NB: Fall Through */
140     case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
141         if (vap->iv_opmode == IEEE80211_M_IBSS &&
142

Archive Download this file



interactive