aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/375-atim_tsf_update.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/madwifi/patches/375-atim_tsf_update.patch')
-rw-r--r--package/madwifi/patches/375-atim_tsf_update.patch110
1 files changed, 96 insertions, 14 deletions
diff --git a/package/madwifi/patches/375-atim_tsf_update.patch b/package/madwifi/patches/375-atim_tsf_update.patch
index bbe380ed47..3800b90c1b 100644
--- a/package/madwifi/patches/375-atim_tsf_update.patch
+++ b/package/madwifi/patches/375-atim_tsf_update.patch
@@ -1,43 +1,79 @@
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -2785,6 +2785,44 @@
+@@ -161,6 +161,7 @@
+ static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
+ static void ath_beacon_free(struct ath_softc *);
+ static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
++static void ath_hw_beacon_stop(struct ath_softc *sc);
+ static int ath_desc_alloc(struct ath_softc *);
+ static void ath_desc_free(struct ath_softc *);
+ static void ath_desc_swap(struct ath_desc *);
+@@ -2783,6 +2784,72 @@
return 1;
}
++static void
++ath_hw_beacon_stop(struct ath_softc *sc)
++{
++ HAL_BEACON_TIMERS btimers;
++
++ btimers.bt_intval = 0;
++ btimers.bt_nexttbtt = 0;
++ btimers.bt_nextdba = 0xffffffff;
++ btimers.bt_nextswba = 0xffffffff;
++ btimers.bt_nextatim = 0;
++
++ ath_hal_setbeacontimers(sc->sc_ah, &btimers);
++}
++
+/* Fix up the ATIM window after TSF resync */
+static int
-+ath_hw_check_atim(struct ath_softc *sc, int window)
++ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
+{
+#define AR5K_TIMER0_5210 0x802c /* Next beacon time register */
+#define AR5K_TIMER0_5211 0x8028
+#define AR5K_TIMER3_5210 0x8038 /* End of ATIM window time register */
+#define AR5K_TIMER3_5211 0x8034
+ struct ath_hal *ah = sc->sc_ah;
++ int dev = sc->sc_ah->ah_macType;
+ unsigned int nbtt, atim;
-+ int dev = ar_device(sc->devid);
++ bool is_5210 = false;
+
++ /*
++ * check if the ATIM window is still correct:
++ * 1.) usually ATIM should be NBTT + window
++ * 2.) nbtt already updated
++ * 3.) nbtt already updated and has wrapped around
++ * 4.) atim has wrapped around
++ */
+ switch(dev) {
+ case 5210:
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
-+ if (atim - nbtt != window) {
-+ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
-+ return atim - nbtt;
-+ }
++ is_5210 = true;
+ break;
+ case 5211:
+ case 5212:
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
-+ if (atim - nbtt != window) {
-+ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
-+ return atim - nbtt;
-+ }
+ break;
+ /* NB: 5416+ doesn't do ATIM in hw */
++ case 5416:
+ default:
-+ break;
++ return 0;
++ }
++
++ if ((atim - nbtt != window) && /* 1.) */
++ (nbtt - atim != intval - window) && /* 2.) */
++ ((nbtt | 0x10000) - atim != intval - window) && /* 3.) */
++ ((atim | 0x10000) - nbtt != window)) { /* 4.) */
++ if (is_5210)
++ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
++ else
++ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
++ return atim - nbtt;
+ }
++
+ return 0;
+}
+
@@ -45,13 +81,59 @@
/*
* Reset the hardware w/o losing operational state. This is
* basically a more efficient way of doing ath_stop, ath_init,
-@@ -6391,6 +6429,11 @@
+@@ -5282,6 +5349,7 @@
+ u_int64_t tsf, hw_tsf;
+ u_int32_t tsftu, hw_tsftu;
+ u_int32_t intval, nexttbtt = 0;
++ unsigned long flags;
+ int reset_tsf = 0;
+
+ if (vap == NULL)
+@@ -5289,6 +5357,9 @@
+
+ ni = vap->iv_bss;
+
++ /* TSF calculation is timing critical - we don't want to be interrupted here */
++ local_irq_save(flags);
++
+ hw_tsf = ath_hal_gettsf64(ah);
+ tsf = le64_to_cpu(ni->ni_tstamp.tsf);
+ hw_tsftu = hw_tsf >> 10;
+@@ -5478,15 +5549,27 @@
+ <= ath_hal_sw_beacon_response_time)
+ nexttbtt += intval;
+ sc->sc_nexttbtt = nexttbtt;
++
++ /* stop beacons before reconfiguring the timers to avoid race
++ * conditions. ath_hal_beaconinit will start them again */
++ ath_hw_beacon_stop(sc);
++
+ ath_hal_beaconinit(ah, nexttbtt, intval);
+ if (intval & HAL_BEACON_RESET_TSF) {
+ sc->sc_last_tsf = 0;
+ }
+ sc->sc_bmisscount = 0;
+ ath_hal_intrset(ah, sc->sc_imask);
++
++ if (ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) {
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "fixed atim window after beacon init\n");
++ }
+ }
+
+ ath_beacon_config_debug:
++ local_irq_restore(flags);
++
+ /* We print all debug messages here, in order to preserve the
+ * time critical aspect of this function */
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+@@ -6389,6 +6472,11 @@
DPRINTF(sc, ATH_DEBUG_BEACON,
"Updated beacon timers\n");
}
+ if ((sc->sc_opmode == IEEE80211_M_IBSS) &&
+ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
-+ ath_hw_check_atim(sc, 1)) {
++ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
+ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
+ }
/* NB: Fall Through */