Skip to contentSkip to conversation

ar9170: handle overflow in tsf_low register during get_tsf

PATCH Superseded Joerg Albert 2 participants 3 messages Sep 15, 2009

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ar9170: handle overflow in tsf_low register during get_tsf

ar9170_op_get_tsf: handle a carry from register TSF_L into TSF_H by reading TSF_H twice. We also get rid of the mutex here and use read_mreg.

---
 drivers/net/wireless/ath/ar9170/cmd.c  |    3 +--
 drivers/net/wireless/ath/ar9170/cmd.h  |    1 +
 drivers/net/wireless/ath/ar9170/main.c |   30 +++++++++++++++++-------------
 3 files changed, 19 insertions(+), 15 deletions(-)
drivers/net/wireless/ath/ar9170/cmd.c +1 -2
index f57a620..cf6f5c4 100644
@@ -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;
drivers/net/wireless/ath/ar9170/cmd.h +1 -0
index a4f0e50..826c45e 100644
@@ -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);
 
 /*
drivers/net/wireless/ath/ar9170/main.c +17 -13
index c1f8c69..3457cd2 100644
@@ -2190,22 +2190,26 @@ 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;
+
+	while (loops++ < 100) {
+		err = ar9170_read_mreg(ar, NR, addr, val);
+		if (WARN_ON(err))
+			return 0;
+		if (val[0] == val[2])
+			break;
+	}
 
-	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);
-	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,
Signature · 1 line
1.6.0.4
#1 lore raw
Quoted 5 lines · On Tuesday 15 September 2009 22:27:09 Joerg Albert wrote:

ar9170_op_get_tsf: handle a carry from register TSF_L into TSF_H by reading TSF_H twice. We also get rid of the mutex here and use read_mreg.

NACK.

don't remove the mutex!

it ensures an exclusive access the driver's data structures (cmdbuf, [readlen and readbuf]) and synchronous control message transfer.

Regards,
Chr

Quoted 78 lines
---
 drivers/net/wireless/ath/ar9170/cmd.c  |    3 +--
 drivers/net/wireless/ath/ar9170/cmd.h  |    1 +
 drivers/net/wireless/ath/ar9170/main.c |   30 +++++++++++++++++-------------
 3 files changed, 19 insertions(+), 15 deletions(-)
drivers/net/wireless/ath/ar9170/cmd.c +1 -2
index f57a620..cf6f5c4 100644
@@ -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;
drivers/net/wireless/ath/ar9170/cmd.h +1 -0
index a4f0e50..826c45e 100644
@@ -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);
 
 /*
drivers/net/wireless/ath/ar9170/main.c +17 -13
index c1f8c69..3457cd2 100644
@@ -2190,22 +2190,26 @@ 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;
+
+	while (loops++ < 100) {
+		err = ar9170_read_mreg(ar, NR, addr, val);
+		if (WARN_ON(err))
+			return 0;
+		if (val[0] == val[2])
+			break;
+	}
 
-	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);
-	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,

#2 lore raw

PATCH v2 1/1 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.

---
Sorry for the re-spin.

 drivers/net/wireless/ath/ar9170/cmd.c  |    3 +--
 drivers/net/wireless/ath/ar9170/cmd.h  |    1 +
 drivers/net/wireless/ath/ar9170/main.c |   24 ++++++++++++++++--------
 3 files changed, 18 insertions(+), 10 deletions(-)
drivers/net/wireless/ath/ar9170/cmd.c +1 -2
index f57a620..cf6f5c4 100644
@@ -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;
drivers/net/wireless/ath/ar9170/cmd.h +1 -0
index a4f0e50..826c45e 100644
@@ -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);
 
 /*
drivers/net/wireless/ath/ar9170/main.c +16 -8
index c1f8c69..f45c530 100644
@@ -2190,22 +2190,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,
Signature · 1 line
1.6.0.4