64bd1c1973ba472159a8127670edc653aa1a12af
[openwrt/svn-archive/archive.git] / 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 @@ -2792,6 +2793,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 @@ -5291,6 +5358,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 @@ -5298,6 +5366,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 @@ -5487,15 +5558,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 @@ -6398,6 +6481,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 &&