aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt73usb.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-11-09 17:40:46 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:08:16 -0500
commit8ff48a8bbe4a1ba29dea2836dfce74660f97c1be (patch)
tree611c0e996813c59c229694b52d329c24829b80e8 /drivers/net/wireless/rt2x00/rt73usb.c
parentbad13639a30e1557fbe9d440adc1906673c9de4e (diff)
rt2x00: Fix race condition when using inderect registers
Indirect registers require multiple calls to the CSR register in order to access the indirect registers. This must be protected under a lock to prevent race conditions which could cause invalid data to be returned when reading from the indirect register or silent failures when writing data to the indirect register. USB drivers where already protected under a mutex, so rename the mutex and make PCI drivers use the mutex as well. This now means that BBP and RF registers are no longer accessible in interrupt context. That is not a bad situation since the slow behavior of accessing those registers means we don't _want_ to access them in interrupt context either. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index f2c8d9733c1d..d1a63e0017da 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
55 * between each attampt. When the busy bit is still set at that time, 55 * between each attampt. When the busy bit is still set at that time,
56 * the access attempt is considered to have failed, 56 * the access attempt is considered to have failed,
57 * and we will print an error. 57 * and we will print an error.
58 * The _lock versions must be used if you already hold the usb_cache_mutex 58 * The _lock versions must be used if you already hold the csr_mutex
59 */ 59 */
60static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, 60static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
61 const unsigned int offset, u32 *value) 61 const unsigned int offset, u32 *value)
@@ -135,7 +135,7 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
135{ 135{
136 u32 reg; 136 u32 reg;
137 137
138 mutex_lock(&rt2x00dev->usb_cache_mutex); 138 mutex_lock(&rt2x00dev->csr_mutex);
139 139
140 /* 140 /*
141 * Wait until the BBP becomes ready. 141 * Wait until the BBP becomes ready.
@@ -154,12 +154,12 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
154 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0); 154 rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
155 155
156 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); 156 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
157 mutex_unlock(&rt2x00dev->usb_cache_mutex); 157 mutex_unlock(&rt2x00dev->csr_mutex);
158 158
159 return; 159 return;
160 160
161exit_fail: 161exit_fail:
162 mutex_unlock(&rt2x00dev->usb_cache_mutex); 162 mutex_unlock(&rt2x00dev->csr_mutex);
163 163
164 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); 164 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
165} 165}
@@ -169,7 +169,7 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
169{ 169{
170 u32 reg; 170 u32 reg;
171 171
172 mutex_lock(&rt2x00dev->usb_cache_mutex); 172 mutex_lock(&rt2x00dev->csr_mutex);
173 173
174 /* 174 /*
175 * Wait until the BBP becomes ready. 175 * Wait until the BBP becomes ready.
@@ -196,12 +196,12 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
196 goto exit_fail; 196 goto exit_fail;
197 197
198 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); 198 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
199 mutex_unlock(&rt2x00dev->usb_cache_mutex); 199 mutex_unlock(&rt2x00dev->csr_mutex);
200 200
201 return; 201 return;
202 202
203exit_fail: 203exit_fail:
204 mutex_unlock(&rt2x00dev->usb_cache_mutex); 204 mutex_unlock(&rt2x00dev->csr_mutex);
205 205
206 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 206 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
207 *value = 0xff; 207 *value = 0xff;
@@ -216,7 +216,7 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
216 if (!word) 216 if (!word)
217 return; 217 return;
218 218
219 mutex_lock(&rt2x00dev->usb_cache_mutex); 219 mutex_lock(&rt2x00dev->csr_mutex);
220 220
221 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 221 for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
222 rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg); 222 rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
@@ -225,7 +225,7 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
225 udelay(REGISTER_BUSY_DELAY); 225 udelay(REGISTER_BUSY_DELAY);
226 } 226 }
227 227
228 mutex_unlock(&rt2x00dev->usb_cache_mutex); 228 mutex_unlock(&rt2x00dev->csr_mutex);
229 ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); 229 ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
230 return; 230 return;
231 231
@@ -245,7 +245,8 @@ rf_write:
245 245
246 rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); 246 rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
247 rt2x00_rf_write(rt2x00dev, word, value); 247 rt2x00_rf_write(rt2x00dev, word, value);
248 mutex_unlock(&rt2x00dev->usb_cache_mutex); 248
249 mutex_unlock(&rt2x00dev->csr_mutex);
249} 250}
250 251
251#ifdef CONFIG_RT2X00_LIB_DEBUGFS 252#ifdef CONFIG_RT2X00_LIB_DEBUGFS