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: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Ivo van Doorn 2008-06-20 22:11:00 +02:00 committed by John W. Linville
parent 2f9ec47d09
commit 99ade2597e
2 changed files with 42 additions and 30 deletions

View File

@ -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,
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,
* 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,
* 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,

View File

@ -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,
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,
* 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,
* 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,