diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-11-09 17:40:46 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-21 11:08:16 -0500 |
commit | 8ff48a8bbe4a1ba29dea2836dfce74660f97c1be (patch) | |
tree | 611c0e996813c59c229694b52d329c24829b80e8 /drivers/net/wireless/rt2x00/rt2500usb.c | |
parent | bad13639a30e1557fbe9d440adc1906673c9de4e (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/rt2500usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c40c9e706e98..e6bae4ae4c47 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * between each attampt. When the busy bit is still set at that time, | 47 | * between each attampt. When the busy bit is still set at that time, |
48 | * the access attempt is considered to have failed, | 48 | * the access attempt is considered to have failed, |
49 | * and we will print an error. | 49 | * and we will print an error. |
50 | * If the usb_cache_mutex is already held then the _lock variants must | 50 | * If the csr_mutex is already held then the _lock variants must |
51 | * be used instead. | 51 | * be used instead. |
52 | */ | 52 | */ |
53 | static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, | 53 | static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -132,7 +132,7 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
132 | { | 132 | { |
133 | u16 reg; | 133 | u16 reg; |
134 | 134 | ||
135 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 135 | mutex_lock(&rt2x00dev->csr_mutex); |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * Wait until the BBP becomes ready. | 138 | * Wait until the BBP becomes ready. |
@@ -151,12 +151,12 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
151 | 151 | ||
152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | 152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
153 | 153 | ||
154 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 154 | mutex_unlock(&rt2x00dev->csr_mutex); |
155 | 155 | ||
156 | return; | 156 | return; |
157 | 157 | ||
158 | exit_fail: | 158 | exit_fail: |
159 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 159 | mutex_unlock(&rt2x00dev->csr_mutex); |
160 | 160 | ||
161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); | 161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); |
162 | } | 162 | } |
@@ -166,7 +166,7 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
166 | { | 166 | { |
167 | u16 reg; | 167 | u16 reg; |
168 | 168 | ||
169 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 169 | mutex_lock(&rt2x00dev->csr_mutex); |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * Wait until the BBP becomes ready. | 172 | * Wait until the BBP becomes ready. |
@@ -194,12 +194,12 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); | 194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); |
195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); | 195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); |
196 | 196 | ||
197 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 197 | mutex_unlock(&rt2x00dev->csr_mutex); |
198 | 198 | ||
199 | return; | 199 | return; |
200 | 200 | ||
201 | exit_fail: | 201 | exit_fail: |
202 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 202 | mutex_unlock(&rt2x00dev->csr_mutex); |
203 | 203 | ||
204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); | 204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); |
205 | *value = 0xff; | 205 | *value = 0xff; |
@@ -214,7 +214,7 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
214 | if (!word) | 214 | if (!word) |
215 | return; | 215 | return; |
216 | 216 | ||
217 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 217 | mutex_lock(&rt2x00dev->csr_mutex); |
218 | 218 | ||
219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); | 220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); |
@@ -223,7 +223,7 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
223 | udelay(REGISTER_BUSY_DELAY); | 223 | udelay(REGISTER_BUSY_DELAY); |
224 | } | 224 | } |
225 | 225 | ||
226 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 226 | mutex_unlock(&rt2x00dev->csr_mutex); |
227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); | 227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); |
228 | return; | 228 | return; |
229 | 229 | ||
@@ -241,7 +241,7 @@ rf_write: | |||
241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); | 241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); |
242 | rt2x00_rf_write(rt2x00dev, word, value); | 242 | rt2x00_rf_write(rt2x00dev, word, value); |
243 | 243 | ||
244 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 244 | mutex_unlock(&rt2x00dev->csr_mutex); |
245 | } | 245 | } |
246 | 246 | ||
247 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 247 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |