diff options
author | Bruno Randolf <bruno@thinktube.com> | 2008-01-19 04:17:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:10:51 -0500 |
commit | 9804b98d57f9b3b02a8906b0b45f461ce0c08428 (patch) | |
tree | 6221cc08c4e9a71f45296fc9862f6e137d0712be /drivers/net | |
parent | e535c1ac7e431f85e9c8ead6dbc977a1e1906736 (diff) |
ath5k: better beacon timer calculation
update ath5k_beacon_update_timers() for better beacon timer calculation in a
variety of situations. most important is the possibility to call it with the
timestamp of a received beacon, when we detected that a HW merge has happened
and we need to reconfigure the beacon timers based on that.
we call this from the mac80211 callback reset_tsf now instead of beacon_update,
and there will be more use of it in the next patch.
drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 109 |
1 files changed, 92 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index de590163a07e..c49061c51688 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -290,6 +290,7 @@ static int ath5k_beacon_setup(struct ath5k_softc *sc, | |||
290 | struct ieee80211_tx_control *ctl); | 290 | struct ieee80211_tx_control *ctl); |
291 | static void ath5k_beacon_send(struct ath5k_softc *sc); | 291 | static void ath5k_beacon_send(struct ath5k_softc *sc); |
292 | static void ath5k_beacon_config(struct ath5k_softc *sc); | 292 | static void ath5k_beacon_config(struct ath5k_softc *sc); |
293 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | ||
293 | 294 | ||
294 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 295 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
295 | { | 296 | { |
@@ -1984,34 +1985,102 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
1984 | } | 1985 | } |
1985 | 1986 | ||
1986 | 1987 | ||
1988 | /** | ||
1989 | * ath5k_beacon_update_timers - update beacon timers | ||
1990 | * | ||
1991 | * @sc: struct ath5k_softc pointer we are operating on | ||
1992 | * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a | ||
1993 | * beacon timer update based on the current HW TSF. | ||
1994 | * | ||
1995 | * Calculate the next target beacon transmit time (TBTT) based on the timestamp | ||
1996 | * of a received beacon or the current local hardware TSF and write it to the | ||
1997 | * beacon timer registers. | ||
1998 | * | ||
1999 | * This is called in a variety of situations, e.g. when a beacon is received, | ||
2000 | * when a HW merge has been detected, but also when an new IBSS is created or | ||
2001 | * when we otherwise know we have to update the timers, but we keep it in this | ||
2002 | * function to have it all together in one place. | ||
2003 | */ | ||
1987 | static void | 2004 | static void |
1988 | ath5k_beacon_update_timers(struct ath5k_softc *sc) | 2005 | ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) |
1989 | { | 2006 | { |
1990 | struct ath5k_hw *ah = sc->ah; | 2007 | struct ath5k_hw *ah = sc->ah; |
1991 | u32 uninitialized_var(nexttbtt), intval, tsftu; | 2008 | u32 nexttbtt, intval, hw_tu, bc_tu; |
1992 | u64 tsf; | 2009 | u64 hw_tsf; |
1993 | 2010 | ||
1994 | intval = sc->bintval & AR5K_BEACON_PERIOD; | 2011 | intval = sc->bintval & AR5K_BEACON_PERIOD; |
1995 | if (WARN_ON(!intval)) | 2012 | if (WARN_ON(!intval)) |
1996 | return; | 2013 | return; |
1997 | 2014 | ||
1998 | /* current TSF converted to TU */ | 2015 | /* beacon TSF converted to TU */ |
1999 | tsf = ath5k_hw_get_tsf64(ah); | 2016 | bc_tu = TSF_TO_TU(bc_tsf); |
2000 | tsftu = TSF_TO_TU(tsf); | ||
2001 | 2017 | ||
2002 | /* | 2018 | /* current TSF converted to TU */ |
2003 | * Pull nexttbtt forward to reflect the current | 2019 | hw_tsf = ath5k_hw_get_tsf64(ah); |
2004 | * TSF. Add one intval otherwise the timespan | 2020 | hw_tu = TSF_TO_TU(hw_tsf); |
2005 | * can be too short for ibss merges. | ||
2006 | */ | ||
2007 | nexttbtt = tsftu + 2 * intval; | ||
2008 | 2021 | ||
2009 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 2022 | #define FUDGE 3 |
2010 | "hw tsftu %u nexttbtt %u intval %u\n", tsftu, nexttbtt, intval); | 2023 | /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ |
2024 | if (bc_tsf == -1) { | ||
2025 | /* | ||
2026 | * no beacons received, called internally. | ||
2027 | * just need to refresh timers based on HW TSF. | ||
2028 | */ | ||
2029 | nexttbtt = roundup(hw_tu + FUDGE, intval); | ||
2030 | } else if (bc_tsf == 0) { | ||
2031 | /* | ||
2032 | * no beacon received, probably called by ath5k_reset_tsf(). | ||
2033 | * reset TSF to start with 0. | ||
2034 | */ | ||
2035 | nexttbtt = intval; | ||
2036 | intval |= AR5K_BEACON_RESET_TSF; | ||
2037 | } else if (bc_tsf > hw_tsf) { | ||
2038 | /* | ||
2039 | * beacon received, SW merge happend but HW TSF not yet updated. | ||
2040 | * not possible to reconfigure timers yet, but next time we | ||
2041 | * receive a beacon with the same BSSID, the hardware will | ||
2042 | * automatically update the TSF and then we need to reconfigure | ||
2043 | * the timers. | ||
2044 | */ | ||
2045 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
2046 | "need to wait for HW TSF sync\n"); | ||
2047 | return; | ||
2048 | } else { | ||
2049 | /* | ||
2050 | * most important case for beacon synchronization between STA. | ||
2051 | * | ||
2052 | * beacon received and HW TSF has been already updated by HW. | ||
2053 | * update next TBTT based on the TSF of the beacon, but make | ||
2054 | * sure it is ahead of our local TSF timer. | ||
2055 | */ | ||
2056 | nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval); | ||
2057 | } | ||
2058 | #undef FUDGE | ||
2011 | 2059 | ||
2012 | intval |= AR5K_BEACON_ENA; | 2060 | intval |= AR5K_BEACON_ENA; |
2013 | |||
2014 | ath5k_hw_init_beacon(ah, nexttbtt, intval); | 2061 | ath5k_hw_init_beacon(ah, nexttbtt, intval); |
2062 | |||
2063 | /* | ||
2064 | * debugging output last in order to preserve the time critical aspect | ||
2065 | * of this function | ||
2066 | */ | ||
2067 | if (bc_tsf == -1) | ||
2068 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
2069 | "reconfigured timers based on HW TSF\n"); | ||
2070 | else if (bc_tsf == 0) | ||
2071 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
2072 | "reset HW TSF and timers\n"); | ||
2073 | else | ||
2074 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
2075 | "updated timers based on beacon TSF\n"); | ||
2076 | |||
2077 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
2078 | "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", | ||
2079 | bc_tsf, hw_tsf, bc_tu, hw_tu, nexttbtt); | ||
2080 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", | ||
2081 | intval & AR5K_BEACON_PERIOD, | ||
2082 | intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", | ||
2083 | intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); | ||
2015 | } | 2084 | } |
2016 | 2085 | ||
2017 | 2086 | ||
@@ -2045,7 +2114,6 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2045 | * only once here. | 2114 | * only once here. |
2046 | */ | 2115 | */ |
2047 | ath5k_beaconq_config(sc); | 2116 | ath5k_beaconq_config(sc); |
2048 | ath5k_beacon_update_timers(sc); | ||
2049 | 2117 | ||
2050 | if (!ath5k_hw_hasveol(ah)) | 2118 | if (!ath5k_hw_hasveol(ah)) |
2051 | sc->imask |= AR5K_INT_SWBA; | 2119 | sc->imask |= AR5K_INT_SWBA; |
@@ -2795,7 +2863,14 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) | |||
2795 | { | 2863 | { |
2796 | struct ath5k_softc *sc = hw->priv; | 2864 | struct ath5k_softc *sc = hw->priv; |
2797 | 2865 | ||
2798 | ath5k_hw_reset_tsf(sc->ah); | 2866 | /* |
2867 | * in IBSS mode we need to update the beacon timers too. | ||
2868 | * this will also reset the TSF if we call it with 0 | ||
2869 | */ | ||
2870 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS) | ||
2871 | ath5k_beacon_update_timers(sc, 0); | ||
2872 | else | ||
2873 | ath5k_hw_reset_tsf(sc->ah); | ||
2799 | } | 2874 | } |
2800 | 2875 | ||
2801 | static int | 2876 | static int |