Skip to content

Commit

Permalink
rt2x00: Fix unbalanced mutex locking
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Jun 25, 2008
1 parent 2f9ec47 commit 99ade25
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 30 deletions.
36 changes: 21 additions & 15 deletions drivers/net/wireless/rt2x00/rt2500usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
goto exit_fail;

/*
* Write the data into the BBP.
Expand All @@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);

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,
Expand All @@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
return;
}
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
goto exit_fail;

/*
* Write the request into the BBP.
Expand All @@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
*value = 0xff;
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
goto exit_fail;

rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);

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,
Expand Down
36 changes: 21 additions & 15 deletions drivers/net/wireless/rt2x00/rt73usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
goto exit_fail;

/*
* Write the data into the BBP.
Expand All @@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,

rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
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,
Expand All @@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
goto exit_fail;

/*
* Write the request into the BBP.
Expand All @@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
*value = 0xff;
return;
}
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
goto exit_fail;

*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
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,
Expand Down

0 comments on commit 99ade25

Please sign in to comment.