According to tests, both TSF lower and upper registers kept counting, so
a rollover of the lower part can happen after the upper part has been
read, as shown in the following log where the upper part is read first
and the lower part next.
tsf = {00000003-fffffffd}
tsf = {00000003-00000001}
tsf = {00000004-0000000b}
This patch corrects this by reading the upper part once again in such
case. It has been tested in an IBSS network where artifical IBSS merges
have been done in order to trigger hundreds of rollover for the TSF
lower part.
Signed-off-by: Benoit Papillault <[email protected]>
---
drivers/net/wireless/ath/ath5k/pcu.c | 21 +++++++++++++++++++--
1 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c
b/drivers/net/wireless/ath/ath5k/pcu.c
index aefe84f..4b24c15 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -593,10 +593,27 @@ u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
*/
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
{
- u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ u32 tsf_lower, tsf_upper;
+
+ /*
+ * While reading TSF upper and then lower part, the clock is still
+ * counting so the lower part can rollover just after reading the
+ * upper part. In this case, we expect the lower part to be quite
+ * small (let's say less than 100us) and we would just need to read
+ * the upper part again to get the correct value.
+ *
+ * Tested on AR2425 (AR5001)
+ */
+
+ tsf_upper = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+
+ if (tsf_lower < 100)
+ tsf_upper = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+
ATH5K_TRACE(ah->ah_sc);
- return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
+ return (((u64)tsf_upper << 32) | tsf_lower);
}
/**
--
1.5.6.5
_______________________________________________
ath5k-devel mailing list
[email protected]
https://lists.ath5k.org/mailman/listinfo/ath5k-devel