aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Baker <linux@baker-net.org.uk>2007-10-27 07:43:29 -0400
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:03:03 -0500
commit3d82346c5d0ff0a413c387c6edaadc0ca29a0971 (patch)
tree790b3fcc6ccee693d9ac343626d1296c736a7851
parent4bd7c452a468af30bb3c4d9c3adcdaf3f3c6048c (diff)
rt2x00: Place mutex around USB register access
There is a buffer, csr_cache which is used to hold copies of data being passed to the USB stack which can get corrupted if multiple threads attempt to access CSR registers simultaneously. There is also the possibility if multiple threads try to access BBP or RF registers for the multiple USB operations needed to get interleaved leading to incorrect results. This patch introduces a mutex to prevent such simultaneous access. The interleaved access problem may also affect the PCI devices but if so that will be handled in a follow-up patch. Signed-off-by: Adam Baker <linux@baker-net.org.uk> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c32
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c42
5 files changed, 131 insertions, 16 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index c89103786b1c..a00420e9626b 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -52,6 +52,8 @@
52 * between each attampt. When the busy bit is still set at that time, 52 * between each attampt. When the busy bit is still set at that time,
53 * the access attempt is considered to have failed, 53 * the access attempt is considered to have failed,
54 * and we will print an error. 54 * and we will print an error.
55 * If the usb_cache_mutex is already held then the _lock variants must
56 * be used instead.
55 */ 57 */
56static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, 58static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
57 const unsigned int offset, 59 const unsigned int offset,
@@ -64,6 +66,17 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
64 *value = le16_to_cpu(reg); 66 *value = le16_to_cpu(reg);
65} 67}
66 68
69static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
70 const unsigned int offset,
71 u16 *value)
72{
73 __le16 reg;
74 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
75 USB_VENDOR_REQUEST_IN, offset,
76 &reg, sizeof(u16), REGISTER_TIMEOUT);
77 *value = le16_to_cpu(reg);
78}
79
67static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, 80static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
68 const unsigned int offset, 81 const unsigned int offset,
69 void *value, const u16 length) 82 void *value, const u16 length)
@@ -84,6 +97,16 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
84 &reg, sizeof(u16), REGISTER_TIMEOUT); 97 &reg, sizeof(u16), REGISTER_TIMEOUT);
85} 98}
86 99
100static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
101 const unsigned int offset,
102 u16 value)
103{
104 __le16 reg = cpu_to_le16(value);
105 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
106 USB_VENDOR_REQUEST_OUT, offset,
107 &reg, sizeof(u16), REGISTER_TIMEOUT);
108}
109
87static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, 110static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
88 const unsigned int offset, 111 const unsigned int offset,
89 void *value, const u16 length) 112 void *value, const u16 length)
@@ -100,7 +123,7 @@ static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
100 unsigned int i; 123 unsigned int i;
101 124
102 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 125 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
103 rt2500usb_register_read(rt2x00dev, PHY_CSR8, &reg); 126 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, &reg);
104 if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) 127 if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
105 break; 128 break;
106 udelay(REGISTER_BUSY_DELAY); 129 udelay(REGISTER_BUSY_DELAY);
@@ -114,12 +137,15 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
114{ 137{
115 u16 reg; 138 u16 reg;
116 139
140 mutex_lock(&rt2x00dev->usb_cache_mutex);
141
117 /* 142 /*
118 * Wait until the BBP becomes ready. 143 * Wait until the BBP becomes ready.
119 */ 144 */
120 reg = rt2500usb_bbp_check(rt2x00dev); 145 reg = rt2500usb_bbp_check(rt2x00dev);
121 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 146 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
122 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); 147 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
148 mutex_unlock(&rt2x00dev->usb_cache_mutex);
123 return; 149 return;
124 } 150 }
125 151
@@ -131,7 +157,9 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
131 rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word); 157 rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
132 rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0); 158 rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
133 159
134 rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); 160 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
161
162 mutex_unlock(&rt2x00dev->usb_cache_mutex);
135} 163}
136 164
137static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, 165static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -139,6 +167,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
139{ 167{
140 u16 reg; 168 u16 reg;
141 169
170 mutex_lock(&rt2x00dev->usb_cache_mutex);
171
142 /* 172 /*
143 * Wait until the BBP becomes ready. 173 * Wait until the BBP becomes ready.
144 */ 174 */
@@ -155,7 +185,7 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
155 rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word); 185 rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
156 rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1); 186 rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
157 187
158 rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); 188 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
159 189
160 /* 190 /*
161 * Wait until the BBP becomes ready. 191 * Wait until the BBP becomes ready.
@@ -164,11 +194,14 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
164 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 194 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
165 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); 195 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
166 *value = 0xff; 196 *value = 0xff;
197 mutex_unlock(&rt2x00dev->usb_cache_mutex);
167 return; 198 return;
168 } 199 }
169 200
170 rt2500usb_register_read(rt2x00dev, PHY_CSR7, &reg); 201 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
171 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); 202 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
203
204 mutex_unlock(&rt2x00dev->usb_cache_mutex);
172} 205}
173 206
174static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, 207static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -180,20 +213,23 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
180 if (!word) 213 if (!word)
181 return; 214 return;
182 215
216 mutex_lock(&rt2x00dev->usb_cache_mutex);
217
183 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 218 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
184 rt2500usb_register_read(rt2x00dev, PHY_CSR10, &reg); 219 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, &reg);
185 if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) 220 if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
186 goto rf_write; 221 goto rf_write;
187 udelay(REGISTER_BUSY_DELAY); 222 udelay(REGISTER_BUSY_DELAY);
188 } 223 }
189 224
225 mutex_unlock(&rt2x00dev->usb_cache_mutex);
190 ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); 226 ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
191 return; 227 return;
192 228
193rf_write: 229rf_write:
194 reg = 0; 230 reg = 0;
195 rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value); 231 rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
196 rt2500usb_register_write(rt2x00dev, PHY_CSR9, reg); 232 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
197 233
198 reg = 0; 234 reg = 0;
199 rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16); 235 rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
@@ -201,8 +237,10 @@ rf_write:
201 rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0); 237 rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
202 rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1); 238 rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
203 239
204 rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg); 240 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
205 rt2x00_rf_write(rt2x00dev, word, value); 241 rt2x00_rf_write(rt2x00dev, word, value);
242
243 mutex_unlock(&rt2x00dev->usb_cache_mutex);
206} 244}
207 245
208#ifdef CONFIG_RT2X00_LIB_DEBUGFS 246#ifdef CONFIG_RT2X00_LIB_DEBUGFS
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 2cd2c9fab1a5..75c9a766e421 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -31,6 +31,7 @@
31#include <linux/skbuff.h> 31#include <linux/skbuff.h>
32#include <linux/workqueue.h> 32#include <linux/workqueue.h>
33#include <linux/firmware.h> 33#include <linux/firmware.h>
34#include <linux/mutex.h>
34 35
35#include <net/mac80211.h> 36#include <net/mac80211.h>
36 37
@@ -659,6 +660,18 @@ struct rt2x00_dev {
659 void *csr_cache; 660 void *csr_cache;
660 661
661 /* 662 /*
663 * Mutex to protect register accesses on USB devices.
664 * There are 2 reasons this is needed, one is to ensure
665 * use of the csr_cache (for USB devices) by one thread
666 * isn't corrupted by another thread trying to access it.
667 * The other is that access to BBP and RF registers
668 * require multiple BUS transactions and if another thread
669 * attempted to access one of those registers at the same
670 * time one of the writes could silently fail.
671 */
672 struct mutex usb_cache_mutex;
673
674 /*
662 * Interface configuration. 675 * Interface configuration.
663 */ 676 */
664 struct interface interface; 677 struct interface interface;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index ab97b0600ec8..a8f0f80ddd21 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -31,6 +31,7 @@
31#include <linux/kernel.h> 31#include <linux/kernel.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/usb.h> 33#include <linux/usb.h>
34#include <linux/bug.h>
34 35
35#include "rt2x00.h" 36#include "rt2x00.h"
36#include "rt2x00usb.h" 37#include "rt2x00usb.h"
@@ -52,6 +53,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
52 (requesttype == USB_VENDOR_REQUEST_IN) ? 53 (requesttype == USB_VENDOR_REQUEST_IN) ?
53 usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); 54 usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
54 55
56
55 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 57 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
56 status = usb_control_msg(usb_dev, pipe, request, requesttype, 58 status = usb_control_msg(usb_dev, pipe, request, requesttype,
57 value, offset, buffer, buffer_length, 59 value, offset, buffer, buffer_length,
@@ -76,13 +78,15 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
76} 78}
77EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); 79EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
78 80
79int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, 81int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
80 const u8 request, const u8 requesttype, 82 const u8 request, const u8 requesttype,
81 const u16 offset, void *buffer, 83 const u16 offset, void *buffer,
82 const u16 buffer_length, const int timeout) 84 const u16 buffer_length, const int timeout)
83{ 85{
84 int status; 86 int status;
85 87
88 BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex));
89
86 /* 90 /*
87 * Check for Cache availability. 91 * Check for Cache availability.
88 */ 92 */
@@ -103,6 +107,25 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
103 107
104 return status; 108 return status;
105} 109}
110EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
111
112int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
113 const u8 request, const u8 requesttype,
114 const u16 offset, void *buffer,
115 const u16 buffer_length, const int timeout)
116{
117 int status;
118
119 mutex_lock(&rt2x00dev->usb_cache_mutex);
120
121 status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
122 requesttype, offset, buffer,
123 buffer_length, timeout);
124
125 mutex_unlock(&rt2x00dev->usb_cache_mutex);
126
127 return status;
128}
106EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); 129EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
107 130
108/* 131/*
@@ -507,6 +530,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
507 rt2x00dev->dev = usb_intf; 530 rt2x00dev->dev = usb_intf;
508 rt2x00dev->ops = ops; 531 rt2x00dev->ops = ops;
509 rt2x00dev->hw = hw; 532 rt2x00dev->hw = hw;
533 mutex_init(&rt2x00dev->usb_cache_mutex);
510 534
511 rt2x00dev->usb_maxpacket = 535 rt2x00dev->usb_maxpacket =
512 usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); 536 usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 53282b036927..2fa45c57a73f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -113,6 +113,14 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
113 const u16 buffer_length, const int timeout); 113 const u16 buffer_length, const int timeout);
114 114
115/* 115/*
116 * A version of rt2x00usb_vendor_request_buff which must be called
117 * if the usb_cache_mutex is already held. */
118int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
119 const u8 request, const u8 requesttype,
120 const u16 offset, void *buffer,
121 const u16 buffer_length, const int timeout);
122
123/*
116 * Simple wrapper around rt2x00usb_vendor_request to write a single 124 * Simple wrapper around rt2x00usb_vendor_request to write a single
117 * command to the device. Since we don't use the buffer argument we 125 * command to the device. Since we don't use the buffer argument we
118 * don't have to worry about kmalloc here. 126 * don't have to worry about kmalloc here.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d89db266757c..7caa3639dadf 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -52,6 +52,7 @@
52 * between each attampt. When the busy bit is still set at that time, 52 * between each attampt. When the busy bit is still set at that time,
53 * the access attempt is considered to have failed, 53 * the access attempt is considered to have failed,
54 * and we will print an error. 54 * and we will print an error.
55 * The _lock versions must be used if you already hold the usb_cache_mutex
55 */ 56 */
56static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, 57static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
57 const unsigned int offset, u32 *value) 58 const unsigned int offset, u32 *value)
@@ -63,6 +64,16 @@ static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
63 *value = le32_to_cpu(reg); 64 *value = le32_to_cpu(reg);
64} 65}
65 66
67static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
68 const unsigned int offset, u32 *value)
69{
70 __le32 reg;
71 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
72 USB_VENDOR_REQUEST_IN, offset,
73 &reg, sizeof(u32), REGISTER_TIMEOUT);
74 *value = le32_to_cpu(reg);
75}
76
66static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev, 77static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev,
67 const unsigned int offset, 78 const unsigned int offset,
68 void *value, const u32 length) 79 void *value, const u32 length)
@@ -82,6 +93,15 @@ static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
82 &reg, sizeof(u32), REGISTER_TIMEOUT); 93 &reg, sizeof(u32), REGISTER_TIMEOUT);
83} 94}
84 95
96static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
97 const unsigned int offset, u32 value)
98{
99 __le32 reg = cpu_to_le32(value);
100 rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
101 USB_VENDOR_REQUEST_OUT, offset,
102 &reg, sizeof(u32), REGISTER_TIMEOUT);
103}
104
85static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, 105static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
86 const unsigned int offset, 106 const unsigned int offset,
87 void *value, const u32 length) 107 void *value, const u32 length)
@@ -98,7 +118,7 @@ static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
98 unsigned int i; 118 unsigned int i;
99 119
100 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 120 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
101 rt73usb_register_read(rt2x00dev, PHY_CSR3, &reg); 121 rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, &reg);
102 if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) 122 if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
103 break; 123 break;
104 udelay(REGISTER_BUSY_DELAY); 124 udelay(REGISTER_BUSY_DELAY);
@@ -112,12 +132,15 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
112{ 132{
113 u32 reg; 133 u32 reg;
114 134
135 mutex_lock(&rt2x00dev->usb_cache_mutex);
136
115 /* 137 /*
116 * Wait until the BBP becomes ready. 138 * Wait until the BBP becomes ready.
117 */ 139 */
118 reg = rt73usb_bbp_check(rt2x00dev); 140 reg = rt73usb_bbp_check(rt2x00dev);
119 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 141 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
120 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); 142 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
143 mutex_unlock(&rt2x00dev->usb_cache_mutex);
121 return; 144 return;
122 } 145 }
123 146
@@ -130,7 +153,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
130 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1); 153 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
131 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0); 154 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
132 155
133 rt73usb_register_write(rt2x00dev, PHY_CSR3, reg); 156 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
157 mutex_unlock(&rt2x00dev->usb_cache_mutex);
134} 158}
135 159
136static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, 160static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -138,12 +162,15 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
138{ 162{
139 u32 reg; 163 u32 reg;
140 164
165 mutex_lock(&rt2x00dev->usb_cache_mutex);
166
141 /* 167 /*
142 * Wait until the BBP becomes ready. 168 * Wait until the BBP becomes ready.
143 */ 169 */
144 reg = rt73usb_bbp_check(rt2x00dev); 170 reg = rt73usb_bbp_check(rt2x00dev);
145 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 171 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
146 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 172 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
173 mutex_unlock(&rt2x00dev->usb_cache_mutex);
147 return; 174 return;
148 } 175 }
149 176
@@ -155,7 +182,7 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
155 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1); 182 rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
156 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1); 183 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
157 184
158 rt73usb_register_write(rt2x00dev, PHY_CSR3, reg); 185 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
159 186
160 /* 187 /*
161 * Wait until the BBP becomes ready. 188 * Wait until the BBP becomes ready.
@@ -168,6 +195,7 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
168 } 195 }
169 196
170 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); 197 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
198 mutex_unlock(&rt2x00dev->usb_cache_mutex);
171} 199}
172 200
173static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, 201static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -179,13 +207,16 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
179 if (!word) 207 if (!word)
180 return; 208 return;
181 209
210 mutex_lock(&rt2x00dev->usb_cache_mutex);
211
182 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 212 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
183 rt73usb_register_read(rt2x00dev, PHY_CSR4, &reg); 213 rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
184 if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) 214 if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
185 goto rf_write; 215 goto rf_write;
186 udelay(REGISTER_BUSY_DELAY); 216 udelay(REGISTER_BUSY_DELAY);
187 } 217 }
188 218
219 mutex_unlock(&rt2x00dev->usb_cache_mutex);
189 ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); 220 ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
190 return; 221 return;
191 222
@@ -203,8 +234,9 @@ rf_write:
203 rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0); 234 rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
204 rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1); 235 rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
205 236
206 rt73usb_register_write(rt2x00dev, PHY_CSR4, reg); 237 rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
207 rt2x00_rf_write(rt2x00dev, word, value); 238 rt2x00_rf_write(rt2x00dev, word, value);
239 mutex_unlock(&rt2x00dev->usb_cache_mutex);
208} 240}
209 241
210#ifdef CONFIG_RT2X00_LIB_DEBUGFS 242#ifdef CONFIG_RT2X00_LIB_DEBUGFS