From: Ivo van Doorn <ivdoorn@gmail.com>
To: "John W. Linville" <linville@tuxdriver.com>
Cc: netdev@vger.kernel.org
Subject: [PATCH 07/26] rt2x00: BBP busy check
Date: Sun, 3 Dec 2006 19:19:04 +0100 [thread overview]
Message-ID: <200612031919.04272.IvDoorn@gmail.com> (raw)
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@gmail.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,
reply other threads:[~2006-12-03 18:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200612031919.04272.IvDoorn@gmail.com \
--to=ivdoorn@gmail.com \
--cc=linville@tuxdriver.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).