aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-06-20 16:11:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-25 10:56:16 -0400
commit99ade2597e3f7f0ad463c489aaccd6cc605e242c (patch)
treea644c9c689cded6ebdb46953180af82d7d3fcdd4 /drivers/net/wireless
parent2f9ec47d0954f9d2e5a00209c2689cbc477a8c89 (diff)
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: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c36
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c36
2 files changed, 42 insertions, 30 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index fdbd0ef2be4b..61e59c17a60a 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
138 * Wait until the BBP becomes ready. 138 * Wait until the BBP becomes ready.
139 */ 139 */
140 reg = rt2500usb_bbp_check(rt2x00dev); 140 reg = rt2500usb_bbp_check(rt2x00dev);
141 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 141 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
142 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); 142 goto exit_fail;
143 mutex_unlock(&rt2x00dev->usb_cache_mutex);
144 return;
145 }
146 143
147 /* 144 /*
148 * Write the data into the BBP. 145 * Write the data into the BBP.
@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
155 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); 152 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
156 153
157 mutex_unlock(&rt2x00dev->usb_cache_mutex); 154 mutex_unlock(&rt2x00dev->usb_cache_mutex);
155
156 return;
157
158exit_fail:
159 mutex_unlock(&rt2x00dev->usb_cache_mutex);
160
161 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
158} 162}
159 163
160static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, 164static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
168 * Wait until the BBP becomes ready. 172 * Wait until the BBP becomes ready.
169 */ 173 */
170 reg = rt2500usb_bbp_check(rt2x00dev); 174 reg = rt2500usb_bbp_check(rt2x00dev);
171 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 175 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
172 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); 176 goto exit_fail;
173 return;
174 }
175 177
176 /* 178 /*
177 * Write the request into the BBP. 179 * Write the request into the BBP.
@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
186 * Wait until the BBP becomes ready. 188 * Wait until the BBP becomes ready.
187 */ 189 */
188 reg = rt2500usb_bbp_check(rt2x00dev); 190 reg = rt2500usb_bbp_check(rt2x00dev);
189 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 191 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
190 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); 192 goto exit_fail;
191 *value = 0xff;
192 mutex_unlock(&rt2x00dev->usb_cache_mutex);
193 return;
194 }
195 193
196 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg); 194 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
197 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); 195 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
198 196
199 mutex_unlock(&rt2x00dev->usb_cache_mutex); 197 mutex_unlock(&rt2x00dev->usb_cache_mutex);
198
199 return;
200
201exit_fail:
202 mutex_unlock(&rt2x00dev->usb_cache_mutex);
203
204 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
205 *value = 0xff;
200} 206}
201 207
202static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, 208static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index fff8386e816b..83cc0147f698 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
134 * Wait until the BBP becomes ready. 134 * Wait until the BBP becomes ready.
135 */ 135 */
136 reg = rt73usb_bbp_check(rt2x00dev); 136 reg = rt73usb_bbp_check(rt2x00dev);
137 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 137 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
138 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); 138 goto exit_fail;
139 mutex_unlock(&rt2x00dev->usb_cache_mutex);
140 return;
141 }
142 139
143 /* 140 /*
144 * Write the data into the BBP. 141 * Write the data into the BBP.
@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
151 148
152 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); 149 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
153 mutex_unlock(&rt2x00dev->usb_cache_mutex); 150 mutex_unlock(&rt2x00dev->usb_cache_mutex);
151
152 return;
153
154exit_fail:
155 mutex_unlock(&rt2x00dev->usb_cache_mutex);
156
157 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
154} 158}
155 159
156static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, 160static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
164 * Wait until the BBP becomes ready. 168 * Wait until the BBP becomes ready.
165 */ 169 */
166 reg = rt73usb_bbp_check(rt2x00dev); 170 reg = rt73usb_bbp_check(rt2x00dev);
167 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 171 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
168 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 172 goto exit_fail;
169 mutex_unlock(&rt2x00dev->usb_cache_mutex);
170 return;
171 }
172 173
173 /* 174 /*
174 * Write the request into the BBP. 175 * Write the request into the BBP.
@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
184 * Wait until the BBP becomes ready. 185 * Wait until the BBP becomes ready.
185 */ 186 */
186 reg = rt73usb_bbp_check(rt2x00dev); 187 reg = rt73usb_bbp_check(rt2x00dev);
187 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 188 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
188 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 189 goto exit_fail;
189 *value = 0xff;
190 return;
191 }
192 190
193 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); 191 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
194 mutex_unlock(&rt2x00dev->usb_cache_mutex); 192 mutex_unlock(&rt2x00dev->usb_cache_mutex);
193
194 return;
195
196exit_fail:
197 mutex_unlock(&rt2x00dev->usb_cache_mutex);
198
199 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
200 *value = 0xff;
195} 201}
196 202
197static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, 203static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,