[<prev] [next>] [day] [month] [year] [list]
Message-Id: <200612031919.04272.IvDoorn@gmail.com>
Date: Sun, 3 Dec 2006 19:19:04 +0100
From: Ivo van Doorn <ivdoorn@...il.com>
To: "John W. Linville" <linville@...driver.com>
Cc: netdev@...r.kernel.org
Subject: [PATCH 07/26] rt2x00: BBP busy check
rt61pci and rt73usb legacy drivers have hinted that there are
race conditions with the bbp register handling. This must be
fixed by doing a busy check before the actual read command.
At the same time we can remove duplicate code by putting that
busy check into a seperate function.
Signed-off-by Ivo van Doorn <IvDoorn@...il.com>
---
diff -rU3 wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-12-02 23:56:59.000000000 +0100
+++ wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-12-03 12:38:28.000000000 +0100
@@ -98,8 +98,7 @@
memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
}
-static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
- const u8 reg_id, const u8 value)
+static u32 rt2x00_bbp_check(const struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -107,14 +106,29 @@
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00_register_read(rt2x00dev, BBPCSR, ®);
if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto bbp_write;
+ return reg;
udelay(REGISTER_BUSY_DELAY);
}
- ERROR("BBPCSR register busy. Write failed.\n");
- return;
+ return 0xffff;
+}
-bbp_write:
+static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
+ const u8 reg_id, const u8 value)
+{
+ u32 reg;
+
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("BBPCSR register busy. Write failed.\n");
+ return;
+ }
+
+ /*
+ * Write the data into the BBP.
+ */
reg = 0;
rt2x00_set_field32(®, BBPCSR_VALUE, value);
rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id);
@@ -128,10 +142,17 @@
const u8 reg_id, u8 *value)
{
u32 reg;
- unsigned int i;
/*
- * First request the register we wish to read from.
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("BBPCSR register busy. Read failed.\n");
+ return;
+ }
+
+ /*
+ * Write the request into the BBP.
*/
reg = 0;
rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id);
@@ -140,17 +161,14 @@
rt2x00_register_write(rt2x00dev, BBPCSR, reg);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00_register_read(rt2x00dev, BBPCSR, ®);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
- return;
- }
- udelay(REGISTER_BUSY_DELAY);
- }
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ reg = rt2x00_bbp_check(rt2x00dev);
+ if (reg == 0xffff)
+ ERROR("BBPCSR register busy. Read failed.\n");
- ERROR("BBPCSR register busy. Read failed.\n");
- *value = 0xff;
+ *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
}
static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
diff -rU3 wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-12-03 00:09:32.000000000 +0100
+++ wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-12-03 12:34:39.000000000 +0100
@@ -98,8 +98,7 @@
memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
}
-static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
- const u8 reg_id, const u8 value)
+static u32 rt2x00_bbp_check(const struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -107,14 +106,29 @@
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00_register_read(rt2x00dev, BBPCSR, ®);
if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto bbp_write;
+ return reg;
udelay(REGISTER_BUSY_DELAY);
}
- ERROR("BBPCSR register busy. Write failed.\n");
- return;
+ return 0xffff;
+}
-bbp_write:
+static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
+ const u8 reg_id, const u8 value)
+{
+ u32 reg;
+
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("BBPCSR register busy. Write failed.\n");
+ return;
+ }
+
+ /*
+ * Write the data into the BBP.
+ */
reg = 0;
rt2x00_set_field32(®, BBPCSR_VALUE, value);
rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id);
@@ -128,10 +142,17 @@
const u8 reg_id, u8 *value)
{
u32 reg;
- unsigned int i;
/*
- * First request the register we wish to read from.
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("BBPCSR register busy. Read failed.\n");
+ return;
+ }
+
+ /*
+ * Write the request into the BBP.
*/
reg = 0;
rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id);
@@ -140,17 +161,14 @@
rt2x00_register_write(rt2x00dev, BBPCSR, reg);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00_register_read(rt2x00dev, BBPCSR, ®);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
- return;
- }
- udelay(REGISTER_BUSY_DELAY);
- }
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ reg = rt2x00_bbp_check(rt2x00dev);
+ if (reg == 0xffff)
+ ERROR("BBPCSR register busy. Read failed.\n");
- ERROR("BBPCSR register busy. Read failed.\n");
- *value = 0xff;
+ *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
}
static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
diff -rU3 wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-12-03 00:01:21.000000000 +0100
+++ wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-12-03 12:35:13.000000000 +0100
@@ -117,8 +117,7 @@
offset, 0x00, value, length);
}
-static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
- const u8 reg_id, const u8 value)
+static u16 rt2x00_bbp_check(const struct rt2x00_dev *rt2x00dev)
{
u16 reg;
unsigned int i;
@@ -126,14 +125,29 @@
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00_register_read(rt2x00dev, PHY_CSR8, ®);
if (!rt2x00_get_field16(reg, PHY_CSR8_BBP_BUSY))
- goto bbp_write;
+ return reg;
udelay(REGISTER_BUSY_DELAY);
}
- ERROR("BBPCSR register busy. Write failed.\n");
- return;
+ return 0xffff;
+}
-bbp_write:
+static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
+ const u8 reg_id, const u8 value)
+{
+ u16 reg;
+
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR8 register busy. Write failed.\n");
+ return;
+ }
+
+ /*
+ * Write the data into the BBP.
+ */
reg = 0;
rt2x00_set_field16(®, PHY_CSR7_BBP_DATA, value);
rt2x00_set_field16(®, PHY_CSR7_BBP_REG_ID, reg_id);
@@ -146,28 +160,35 @@
const u8 reg_id, u8 *value)
{
u16 reg;
- unsigned int i;
/*
- * First request the register we wish to read from.
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR8 register busy. Read failed.\n");
+ return;
+ }
+
+ /*
+ * Write the request into the BBP.
*/
+ reg =0;
rt2x00_set_field16(®, PHY_CSR7_BBP_REG_ID, reg_id);
rt2x00_set_field16(®, PHY_CSR7_BBP_READ_CONTROL, 1);
rt2x00_register_write(rt2x00dev, PHY_CSR7, reg);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00_register_read(rt2x00dev, PHY_CSR8, ®);
- if (!rt2x00_get_field16(reg, PHY_CSR8_BBP_BUSY)) {
- rt2x00_register_read(rt2x00dev, PHY_CSR7, ®);
- *value = rt2x00_get_field16(reg, PHY_CSR7_BBP_DATA);
- return;
- }
- udelay(REGISTER_BUSY_DELAY);
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR8 register busy. Read failed.\n");
+ *value = 0xff;
+ return;
}
- ERROR("BBPCSR register busy. Read failed.\n");
- *value = 0xff;
+ rt2x00_register_read(rt2x00dev, PHY_CSR7, ®);
+ *value = rt2x00_get_field16(reg, PHY_CSR7_BBP_DATA);
}
static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
diff -rU3 wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt61pci.c wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-12-03 00:04:48.000000000 +0100
+++ wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-12-03 12:35:34.000000000 +0100
@@ -105,8 +105,7 @@
memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
}
-static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
- const u8 reg_id, const u8 value)
+static u32 rt2x00_bbp_check(const struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -114,14 +113,29 @@
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00_register_read(rt2x00dev, PHY_CSR3, ®);
if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto bbp_write;
+ return reg;
udelay(REGISTER_BUSY_DELAY);
}
- ERROR("PHY_CSR3 register busy. Write failed.\n");
- return;
+ return 0xffff;
+}
-bbp_write:
+static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
+ const u8 reg_id, const u8 value)
+{
+ u32 reg;
+
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR3 register busy. Write failed.\n");
+ return;
+ }
+
+ /*
+ * Write the data into the BBP.
+ */
reg = 0;
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id);
@@ -135,10 +149,17 @@
const u8 reg_id, u8 *value)
{
u32 reg;
- unsigned int i;
/*
- * First request the register we wish to read from.
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR3 register busy. Read failed.\n");
+ return;
+ }
+
+ /*
+ * Write the request into the BBP.
*/
reg =0;
rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id);
@@ -147,17 +168,14 @@
rt2x00_register_write(rt2x00dev, PHY_CSR3, reg);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00_register_read(rt2x00dev, PHY_CSR3, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
- return;
- }
- udelay(REGISTER_BUSY_DELAY);
- }
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ reg = rt2x00_bbp_check(rt2x00dev);
+ if (reg == 0xffff)
+ ERROR("PHY_CSR3 register busy. Read failed.\n");
- ERROR("PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
+ *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
}
static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
diff -rU3 wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt73usb.c wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-d80211/drivers/net/wireless/d80211/rt2x00/rt73usb.c 2006-12-03 00:13:18.000000000 +0100
+++ wireless-dev-bbp/drivers/net/wireless/d80211/rt2x00/rt73usb.c 2006-12-03 12:35:52.000000000 +0100
@@ -119,8 +119,7 @@
offset, 0x00, value, length);
}
-static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
- const u8 reg_id, const u8 value)
+static u32 rt2x00_bbp_check(const struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -128,14 +127,29 @@
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00_register_read(rt2x00dev, PHY_CSR3, ®);
if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto bbp_write;
+ return reg;
udelay(REGISTER_BUSY_DELAY);
}
- ERROR("PHY_CSR3 register busy. Write failed.\n");
- return;
+ return 0xffff;
+}
-bbp_write:
+static void rt2x00_bbp_write(const struct rt2x00_dev *rt2x00dev,
+ const u8 reg_id, const u8 value)
+{
+ u32 reg;
+
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR3 register busy. Write failed.\n");
+ return;
+ }
+
+ /*
+ * Write the data into the BBP.
+ */
reg = 0;
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id);
@@ -149,10 +163,17 @@
const u8 reg_id, u8 *value)
{
u32 reg;
- unsigned int i;
/*
- * First request the register we wish to read from.
+ * Wait untill the BBP becomes ready.
+ */
+ if (rt2x00_bbp_check(rt2x00dev) == 0xffff) {
+ ERROR("PHY_CSR3 register busy. Read failed.\n");
+ return;
+ }
+
+ /*
+ * Write the request into the BBP.
*/
reg =0;
rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id);
@@ -161,17 +182,14 @@
rt2x00_register_write(rt2x00dev, PHY_CSR3, reg);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00_register_read(rt2x00dev, PHY_CSR3, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
- return;
- }
- udelay(REGISTER_BUSY_DELAY);
- }
+ /*
+ * Wait untill the BBP becomes ready.
+ */
+ reg = rt2x00_bbp_check(rt2x00dev);
+ if (reg == 0xffff)
+ ERROR("PHY_CSR3 register busy. Read failed.\n");
- ERROR("PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
+ *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
}
static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists