ar9170: handle overflow in tsf_low register during get_tsf
authorJoerg Albert <jal2@gmx.de>
Tue, 15 Sep 2009 21:27:53 +0000 (23:27 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 7 Oct 2009 20:39:38 +0000 (16:39 -0400)
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>
drivers/net/wireless/ath/ar9170/cmd.c
drivers/net/wireless/ath/ar9170/cmd.h
drivers/net/wireless/ath/ar9170/main.c

index f57a620..cf6f5c4 100644 (file)
@@ -72,8 +72,7 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
        return err;
 }
 
-static int ar9170_read_mreg(struct ar9170 *ar, int nregs,
-                           const u32 *regs, u32 *out)
+int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out)
 {
        int i, err;
        __le32 *offs, *res;
index a4f0e50..826c45e 100644 (file)
@@ -44,6 +44,7 @@
 int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
 int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
 int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
+int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out);
 int ar9170_echo_test(struct ar9170 *ar, u32 v);
 
 /*
index 81c6cf1..de0ba2b 100644 (file)
@@ -2192,22 +2192,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
 {
        struct ar9170 *ar = hw->priv;
        int err;
-       u32 tsf_low;
-       u32 tsf_high;
        u64 tsf;
+#define NR 3
+       static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H,
+                                   AR9170_MAC_REG_TSF_L,
+                                   AR9170_MAC_REG_TSF_H };
+       u32 val[NR];
+       int loops = 0;
 
        mutex_lock(&ar->mutex);
-       err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low);
-       if (!err)
-               err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high);
+
+       while (loops++ < 10) {
+               err = ar9170_read_mreg(ar, NR, addr, val);
+               if (err || val[0] == val[2])
+                       break;
+       }
+
        mutex_unlock(&ar->mutex);
 
        if (WARN_ON(err))
                return 0;
-
-       tsf = tsf_high;
-       tsf = (tsf << 32) | tsf_low;
+       tsf = val[0];
+       tsf = (tsf << 32) | val[1];
        return tsf;
+#undef NR
 }
 
 static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,