From 5c105d9f3fd086aff195d3849dcf847d6b0bd927 Mon Sep 17 00:00:00 2001 From: blogic Date: Fri, 5 Oct 2012 10:12:53 +0000 Subject: branch Attitude Adjustment git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/madwifi/patches/375-atim_tsf_update.patch | 141 ++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 package/madwifi/patches/375-atim_tsf_update.patch (limited to 'package/madwifi/patches/375-atim_tsf_update.patch') diff --git a/package/madwifi/patches/375-atim_tsf_update.patch b/package/madwifi/patches/375-atim_tsf_update.patch new file mode 100644 index 000000000..d1313aa56 --- /dev/null +++ b/package/madwifi/patches/375-atim_tsf_update.patch @@ -0,0 +1,141 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -161,6 +161,7 @@ static void ath_beacon_send(struct ath_s + 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 *); +@@ -2793,6 +2794,72 @@ ath_set_ack_bitrate(struct ath_softc *sc + 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, 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 is_5210 = 0; ++ ++ /* ++ * 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); ++ is_5210 = 1; ++ break; ++ case 5211: ++ case 5212: ++ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211); ++ atim = OS_REG_READ(ah, AR5K_TIMER3_5211); ++ break; ++ /* NB: 5416+ doesn't do ATIM in hw */ ++ case 5416: ++ default: ++ 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; ++} ++ ++ + /* + * Reset the hardware w/o losing operational state. This is + * basically a more efficient way of doing ath_stop, ath_init, +@@ -5294,6 +5361,7 @@ ath_beacon_config(struct ath_softc *sc, + 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) +@@ -5301,6 +5369,9 @@ ath_beacon_config(struct ath_softc *sc, + + 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; +@@ -5490,15 +5561,27 @@ ath_beacon_config(struct ath_softc *sc, + <= 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 ((sc->sc_opmode == HAL_M_IBSS) && 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, +@@ -6401,6 +6484,11 @@ ath_recv_mgmt(struct ieee80211vap * vap, + DPRINTF(sc, ATH_DEBUG_BEACON, + "Updated beacon timers\n"); + } ++ if ((sc->sc_opmode == HAL_M_IBSS) && ++ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) && ++ 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 */ + case IEEE80211_FC0_SUBTYPE_PROBE_RESP: + if (vap->iv_opmode == IEEE80211_M_IBSS && -- cgit v1.2.3