Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+21 −15
Original line number Diff line number Diff line
@@ -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.
@@ -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,
@@ -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.
@@ -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,
+21 −15
Original line number Diff line number Diff line
@@ -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.
@@ -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,
@@ -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.
@@ -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,