Commit 99ade259 authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville

rt2x00: Fix unbalanced mutex locking

The usb_cache_mutex was not correctly released
under all circumstances. Both rt73usb as rt2500usb
didn't release the mutex under certain conditions
when the register access failed. Obviously such
failure would lead to deadlocks.

In addition under similar circumstances when the
bbp register couldn't be read the value must be
set to 0xff to indicate that the value is wrong.
This too didn't happen under all circumstances.
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2f9ec47d
...@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, ...@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt2500usb_bbp_check(rt2x00dev); reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); goto exit_fail;
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
/* /*
* Write the data into the BBP. * Write the data into the BBP.
...@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, ...@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
mutex_unlock(&rt2x00dev->usb_cache_mutex); mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
exit_fail:
mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
} }
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
...@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, ...@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt2500usb_bbp_check(rt2x00dev); reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); goto exit_fail;
return;
}
/* /*
* Write the request into the BBP. * Write the request into the BBP.
...@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, ...@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt2500usb_bbp_check(rt2x00dev); reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); goto exit_fail;
*value = 0xff;
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg); rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
mutex_unlock(&rt2x00dev->usb_cache_mutex); mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
exit_fail:
mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
*value = 0xff;
} }
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
......
...@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, ...@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt73usb_bbp_check(rt2x00dev); reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); goto exit_fail;
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
/* /*
* Write the data into the BBP. * Write the data into the BBP.
...@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, ...@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
mutex_unlock(&rt2x00dev->usb_cache_mutex); mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
exit_fail:
mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
} }
static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
...@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, ...@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt73usb_bbp_check(rt2x00dev); reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); goto exit_fail;
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
/* /*
* Write the request into the BBP. * Write the request into the BBP.
...@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, ...@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready. * Wait until the BBP becomes ready.
*/ */
reg = rt73usb_bbp_check(rt2x00dev); reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); goto exit_fail;
*value = 0xff;
return;
}
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
mutex_unlock(&rt2x00dev->usb_cache_mutex); mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
exit_fail:
mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
*value = 0xff;
} }
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment