|
@@ -52,6 +52,8 @@
|
|
|
* between each attampt. When the busy bit is still set at that time,
|
|
|
* the access attempt is considered to have failed,
|
|
|
* and we will print an error.
|
|
|
+ * If the usb_cache_mutex is already held then the _lock variants must
|
|
|
+ * be used instead.
|
|
|
*/
|
|
|
static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
|
|
|
const unsigned int offset,
|
|
@@ -64,6 +66,17 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
|
|
|
*value = le16_to_cpu(reg);
|
|
|
}
|
|
|
|
|
|
+static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
|
|
+ const unsigned int offset,
|
|
|
+ u16 *value)
|
|
|
+{
|
|
|
+ __le16 reg;
|
|
|
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
|
|
|
+ USB_VENDOR_REQUEST_IN, offset,
|
|
|
+ ®, sizeof(u16), REGISTER_TIMEOUT);
|
|
|
+ *value = le16_to_cpu(reg);
|
|
|
+}
|
|
|
+
|
|
|
static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
|
|
|
const unsigned int offset,
|
|
|
void *value, const u16 length)
|
|
@@ -84,6 +97,16 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
|
|
|
®, sizeof(u16), REGISTER_TIMEOUT);
|
|
|
}
|
|
|
|
|
|
+static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
|
|
+ const unsigned int offset,
|
|
|
+ u16 value)
|
|
|
+{
|
|
|
+ __le16 reg = cpu_to_le16(value);
|
|
|
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
|
|
|
+ USB_VENDOR_REQUEST_OUT, offset,
|
|
|
+ ®, sizeof(u16), REGISTER_TIMEOUT);
|
|
|
+}
|
|
|
+
|
|
|
static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
|
|
const unsigned int offset,
|
|
|
void *value, const u16 length)
|
|
@@ -100,7 +123,7 @@ static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
|
|
|
unsigned int i;
|
|
|
|
|
|
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
|
|
- rt2500usb_register_read(rt2x00dev, PHY_CSR8, ®);
|
|
|
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®);
|
|
|
if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
|
|
|
break;
|
|
|
udelay(REGISTER_BUSY_DELAY);
|
|
@@ -114,12 +137,15 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
|
|
{
|
|
|
u16 reg;
|
|
|
|
|
|
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
|
|
|
+
|
|
|
/*
|
|
|
* 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;
|
|
|
}
|
|
|
|
|
@@ -131,7 +157,9 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
|
|
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
|
|
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0);
|
|
|
|
|
|
- rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
|
|
|
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
|
|
+
|
|
|
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
|
|
|
}
|
|
|
|
|
|
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
|
@@ -139,6 +167,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
|
|
{
|
|
|
u16 reg;
|
|
|
|
|
|
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
|
|
|
+
|
|
|
/*
|
|
|
* Wait until the BBP becomes ready.
|
|
|
*/
|
|
@@ -155,7 +185,7 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
|
|
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
|
|
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1);
|
|
|
|
|
|
- rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
|
|
|
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
|
|
|
|
|
/*
|
|
|
* Wait until the BBP becomes ready.
|
|
@@ -164,11 +194,14 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *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;
|
|
|
}
|
|
|
|
|
|
- rt2500usb_register_read(rt2x00dev, PHY_CSR7, ®);
|
|
|
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);
|
|
|
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
|
|
|
+
|
|
|
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
|
|
|
}
|
|
|
|
|
|
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
|
@@ -180,20 +213,23 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
|
|
if (!word)
|
|
|
return;
|
|
|
|
|
|
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
|
|
|
+
|
|
|
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
|
|
- rt2500usb_register_read(rt2x00dev, PHY_CSR10, ®);
|
|
|
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®);
|
|
|
if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
|
|
|
goto rf_write;
|
|
|
udelay(REGISTER_BUSY_DELAY);
|
|
|
}
|
|
|
|
|
|
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
|
|
|
ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
|
|
|
return;
|
|
|
|
|
|
rf_write:
|
|
|
reg = 0;
|
|
|
rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value);
|
|
|
- rt2500usb_register_write(rt2x00dev, PHY_CSR9, reg);
|
|
|
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
|
|
|
|
|
|
reg = 0;
|
|
|
rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16);
|
|
@@ -201,8 +237,10 @@ rf_write:
|
|
|
rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0);
|
|
|
rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1);
|
|
|
|
|
|
- rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg);
|
|
|
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
|
|
|
rt2x00_rf_write(rt2x00dev, word, value);
|
|
|
+
|
|
|
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
|