aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Albert <jal2@gmx.de>2009-09-15 17:27:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:38 -0400
commit181af387033e20065e94363d07ecbace7738278c (patch)
tree7022e3a625e89ac9f1bf55bdf75eb95b88752485
parent7c52c07de8bd0433db6b3e0147544e5a2f01b786 (diff)
ar9170: handle overflow in tsf_low register during get_tsf
ar9170_op_get_tsf: handle a carry from TSF_L into TSF_H by reading TSF_H twice. Signed-off-by: Joerg Albert <jal2@gmx.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.c3
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.h1
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c24
3 files changed, 18 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c
index f57a6200167b..cf6f5c4174a6 100644
--- a/drivers/net/wireless/ath/ar9170/cmd.c
+++ b/drivers/net/wireless/ath/ar9170/cmd.c
@@ -72,8 +72,7 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
72 return err; 72 return err;
73} 73}
74 74
75static int ar9170_read_mreg(struct ar9170 *ar, int nregs, 75int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out)
76 const u32 *regs, u32 *out)
77{ 76{
78 int i, err; 77 int i, err;
79 __le32 *offs, *res; 78 __le32 *offs, *res;
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h
index a4f0e50e52b4..826c45e6b274 100644
--- a/drivers/net/wireless/ath/ar9170/cmd.h
+++ b/drivers/net/wireless/ath/ar9170/cmd.h
@@ -44,6 +44,7 @@
44int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); 44int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
45int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); 45int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
46int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); 46int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
47int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out);
47int ar9170_echo_test(struct ar9170 *ar, u32 v); 48int ar9170_echo_test(struct ar9170 *ar, u32 v);
48 49
49/* 50/*
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 81c6cf1135bc..de0ba2bf7691 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -2192,22 +2192,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
2192{ 2192{
2193 struct ar9170 *ar = hw->priv; 2193 struct ar9170 *ar = hw->priv;
2194 int err; 2194 int err;
2195 u32 tsf_low;
2196 u32 tsf_high;
2197 u64 tsf; 2195 u64 tsf;
2196#define NR 3
2197 static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H,
2198 AR9170_MAC_REG_TSF_L,
2199 AR9170_MAC_REG_TSF_H };
2200 u32 val[NR];
2201 int loops = 0;
2198 2202
2199 mutex_lock(&ar->mutex); 2203 mutex_lock(&ar->mutex);
2200 err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); 2204
2201 if (!err) 2205 while (loops++ < 10) {
2202 err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); 2206 err = ar9170_read_mreg(ar, NR, addr, val);
2207 if (err || val[0] == val[2])
2208 break;
2209 }
2210
2203 mutex_unlock(&ar->mutex); 2211 mutex_unlock(&ar->mutex);
2204 2212
2205 if (WARN_ON(err)) 2213 if (WARN_ON(err))
2206 return 0; 2214 return 0;
2207 2215 tsf = val[0];
2208 tsf = tsf_high; 2216 tsf = (tsf << 32) | val[1];
2209 tsf = (tsf << 32) | tsf_low;
2210 return tsf; 2217 return tsf;
2218#undef NR
2211} 2219}
2212 2220
2213static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 2221static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,