aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-05-22 11:46:41 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 19:29:48 -0400
commitd4ead16f50f9ad30bdc7276ec8fee7a24c72f294 (patch)
treee1905abbc393cc4d73180dd7b9e1cf860378b590
parent55e5fdfa541ec7bf1b1613624ed4dd8cdacaa841 (diff)
USB: prevent char device open/deregister race
This patch (as908) adds central protection in usbcore for the prototypical race between opening and unregistering a char device. The spinlock used to protect the minor-numbers array is replaced with an rwsem, which can remain locked across a call to a driver's open() method. This guarantees that open() and deregister() will be mutually exclusive. The private locks currently used in several individual drivers for this purpose are no longer necessary, and the patch removes them. The following USB drivers are affected: usblcd, idmouse, auerswald, legousbtower, sisusbvga/sisusb, ldusb, adutux, iowarrior, and usb-skeleton. As a side effect of this change, usb_deregister_dev() must not be called while holding a lock that is acquired by open(). Unfortunately a number of drivers do this, but luckily the solution is simple: call usb_deregister_dev() before acquiring the lock. In addition to these changes (and their consequent code simplifications), the patch fixes a use-after-free bug in adutux and a race between open() and release() in iowarrior. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/file.c29
-rw-r--r--drivers/usb/misc/adutux.c31
-rw-r--r--drivers/usb/misc/auerswald.c6
-rw-r--r--drivers/usb/misc/idmouse.c54
-rw-r--r--drivers/usb/misc/iowarrior.c26
-rw-r--r--drivers/usb/misc/ldusb.c33
-rw-r--r--drivers/usb/misc/legousbtower.c24
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c38
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c25
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h2
-rw-r--r--drivers/usb/misc/usblcd.c21
-rw-r--r--drivers/usb/usb-skeleton.c14
12 files changed, 75 insertions, 228 deletions
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 01c857ac27af..5d860bc9b421 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -16,15 +16,15 @@
16 */ 16 */
17 17
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/spinlock.h>
20#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/rwsem.h>
21#include <linux/usb.h> 21#include <linux/usb.h>
22 22
23#include "usb.h" 23#include "usb.h"
24 24
25#define MAX_USB_MINORS 256 25#define MAX_USB_MINORS 256
26static const struct file_operations *usb_minors[MAX_USB_MINORS]; 26static const struct file_operations *usb_minors[MAX_USB_MINORS];
27static DEFINE_SPINLOCK(minor_lock); 27static DECLARE_RWSEM(minor_rwsem);
28 28
29static int usb_open(struct inode * inode, struct file * file) 29static int usb_open(struct inode * inode, struct file * file)
30{ 30{
@@ -33,14 +33,11 @@ static int usb_open(struct inode * inode, struct file * file)
33 int err = -ENODEV; 33 int err = -ENODEV;
34 const struct file_operations *old_fops, *new_fops = NULL; 34 const struct file_operations *old_fops, *new_fops = NULL;
35 35
36 spin_lock (&minor_lock); 36 down_read(&minor_rwsem);
37 c = usb_minors[minor]; 37 c = usb_minors[minor];
38 38
39 if (!c || !(new_fops = fops_get(c))) { 39 if (!c || !(new_fops = fops_get(c)))
40 spin_unlock(&minor_lock); 40 goto done;
41 return err;
42 }
43 spin_unlock(&minor_lock);
44 41
45 old_fops = file->f_op; 42 old_fops = file->f_op;
46 file->f_op = new_fops; 43 file->f_op = new_fops;
@@ -52,6 +49,8 @@ static int usb_open(struct inode * inode, struct file * file)
52 file->f_op = fops_get(old_fops); 49 file->f_op = fops_get(old_fops);
53 } 50 }
54 fops_put(old_fops); 51 fops_put(old_fops);
52 done:
53 up_read(&minor_rwsem);
55 return err; 54 return err;
56} 55}
57 56
@@ -166,7 +165,7 @@ int usb_register_dev(struct usb_interface *intf,
166 if (class_driver->fops == NULL) 165 if (class_driver->fops == NULL)
167 goto exit; 166 goto exit;
168 167
169 spin_lock (&minor_lock); 168 down_write(&minor_rwsem);
170 for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { 169 for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
171 if (usb_minors[minor]) 170 if (usb_minors[minor])
172 continue; 171 continue;
@@ -176,7 +175,7 @@ int usb_register_dev(struct usb_interface *intf,
176 retval = 0; 175 retval = 0;
177 break; 176 break;
178 } 177 }
179 spin_unlock (&minor_lock); 178 up_write(&minor_rwsem);
180 179
181 if (retval) 180 if (retval)
182 goto exit; 181 goto exit;
@@ -197,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
197 intf->usb_dev = device_create(usb_class->class, &intf->dev, 196 intf->usb_dev = device_create(usb_class->class, &intf->dev,
198 MKDEV(USB_MAJOR, minor), "%s", temp); 197 MKDEV(USB_MAJOR, minor), "%s", temp);
199 if (IS_ERR(intf->usb_dev)) { 198 if (IS_ERR(intf->usb_dev)) {
200 spin_lock (&minor_lock); 199 down_write(&minor_rwsem);
201 usb_minors[intf->minor] = NULL; 200 usb_minors[intf->minor] = NULL;
202 spin_unlock (&minor_lock); 201 up_write(&minor_rwsem);
203 retval = PTR_ERR(intf->usb_dev); 202 retval = PTR_ERR(intf->usb_dev);
204 } 203 }
205exit: 204exit:
@@ -236,9 +235,9 @@ void usb_deregister_dev(struct usb_interface *intf,
236 235
237 dbg ("removing %d minor", intf->minor); 236 dbg ("removing %d minor", intf->minor);
238 237
239 spin_lock (&minor_lock); 238 down_write(&minor_rwsem);
240 usb_minors[intf->minor] = NULL; 239 usb_minors[intf->minor] = NULL;
241 spin_unlock (&minor_lock); 240 up_write(&minor_rwsem);
242 241
243 snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); 242 snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
244 device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); 243 device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
@@ -247,5 +246,3 @@ void usb_deregister_dev(struct usb_interface *intf,
247 destroy_usb_class(); 246 destroy_usb_class();
248} 247}
249EXPORT_SYMBOL(usb_deregister_dev); 248EXPORT_SYMBOL(usb_deregister_dev);
250
251
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 77145f9db043..d72c42e5f22d 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -108,8 +108,6 @@ struct adu_device {
108 struct urb* interrupt_out_urb; 108 struct urb* interrupt_out_urb;
109}; 109};
110 110
111/* prevent races between open() and disconnect */
112static DEFINE_MUTEX(disconnect_mutex);
113static struct usb_driver adu_driver; 111static struct usb_driver adu_driver;
114 112
115static void adu_debug_data(int level, const char *function, int size, 113static void adu_debug_data(int level, const char *function, int size,
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file)
256 254
257 subminor = iminor(inode); 255 subminor = iminor(inode);
258 256
259 mutex_lock(&disconnect_mutex);
260
261 interface = usb_find_interface(&adu_driver, subminor); 257 interface = usb_find_interface(&adu_driver, subminor);
262 if (!interface) { 258 if (!interface) {
263 err("%s - error, can't find device for minor %d", 259 err("%s - error, can't find device for minor %d",
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file)
306 up(&dev->sem); 302 up(&dev->sem);
307 303
308exit_no_device: 304exit_no_device:
309 mutex_unlock(&disconnect_mutex);
310 dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); 305 dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
311 306
312 return retval; 307 return retval;
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev)
318 313
319 dbg(2," %s : enter", __FUNCTION__); 314 dbg(2," %s : enter", __FUNCTION__);
320 315
321 if (dev->udev == NULL) {
322 /* the device was unplugged before the file was released */
323 adu_delete(dev);
324 goto exit;
325 }
326
327 /* decrement our usage count for the device */ 316 /* decrement our usage count for the device */
328 --dev->open_count; 317 --dev->open_count;
329 dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); 318 dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev)
332 dev->open_count = 0; 321 dev->open_count = 0;
333 } 322 }
334 323
335exit:
336 dbg(2," %s : leave", __FUNCTION__); 324 dbg(2," %s : leave", __FUNCTION__);
337 return retval; 325 return retval;
338} 326}
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file)
367 goto exit; 355 goto exit;
368 } 356 }
369 357
370 /* do the work */ 358 if (dev->udev == NULL) {
371 retval = adu_release_internal(dev); 359 /* the device was unplugged before the file was released */
360 up(&dev->sem);
361 adu_delete(dev);
362 dev = NULL;
363 } else {
364 /* do the work */
365 retval = adu_release_internal(dev);
366 }
372 367
373exit: 368exit:
374 if (dev) 369 if (dev)
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface)
831 826
832 dbg(2," %s : enter", __FUNCTION__); 827 dbg(2," %s : enter", __FUNCTION__);
833 828
834 mutex_lock(&disconnect_mutex); /* not interruptible */
835
836 dev = usb_get_intfdata(interface); 829 dev = usb_get_intfdata(interface);
837 usb_set_intfdata(interface, NULL); 830 usb_set_intfdata(interface, NULL);
838 831
839 down(&dev->sem); /* not interruptible */
840
841 minor = dev->minor; 832 minor = dev->minor;
842 833
843 /* give back our minor */ 834 /* give back our minor */
844 usb_deregister_dev(interface, &adu_class); 835 usb_deregister_dev(interface, &adu_class);
845 dev->minor = 0; 836 dev->minor = 0;
846 837
838 down(&dev->sem); /* not interruptible */
839
847 /* if the device is not opened, then we clean up right now */ 840 /* if the device is not opened, then we clean up right now */
848 dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); 841 dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
849 if (!dev->open_count) { 842 if (!dev->open_count) {
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface)
854 up(&dev->sem); 847 up(&dev->sem);
855 } 848 }
856 849
857 mutex_unlock(&disconnect_mutex);
858
859 dev_info(&interface->dev, "ADU device adutux%d now disconnected", 850 dev_info(&interface->dev, "ADU device adutux%d now disconnected",
860 (minor - ADU_MINOR_BASE)); 851 (minor - ADU_MINOR_BASE));
861 852
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index cac1500cba62..1fd5fc220cd7 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf)
2034 if (!cp) 2034 if (!cp)
2035 return; 2035 return;
2036 2036
2037 down (&cp->mutex);
2038 info ("device /dev/%s now disconnecting", cp->name);
2039
2040 /* give back our USB minor number */ 2037 /* give back our USB minor number */
2041 usb_deregister_dev(intf, &auerswald_class); 2038 usb_deregister_dev(intf, &auerswald_class);
2042 2039
2040 down (&cp->mutex);
2041 info ("device /dev/%s now disconnecting", cp->name);
2042
2043 /* Stop the interrupt endpoint */ 2043 /* Stop the interrupt endpoint */
2044 auerswald_int_release (cp); 2044 auerswald_int_release (cp);
2045 2045
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8d0e360636e6..e6fd024024f5 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = {
119 .id_table = idmouse_table, 119 .id_table = idmouse_table,
120}; 120};
121 121
122/* prevent races between open() and disconnect() */
123static DEFINE_MUTEX(disconnect_mutex);
124
125static int idmouse_create_image(struct usb_idmouse *dev) 122static int idmouse_create_image(struct usb_idmouse *dev)
126{ 123{
127 int bytes_read; 124 int bytes_read;
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file)
211 struct usb_interface *interface; 208 struct usb_interface *interface;
212 int result; 209 int result;
213 210
214 /* prevent disconnects */
215 mutex_lock(&disconnect_mutex);
216
217 /* get the interface from minor number and driver information */ 211 /* get the interface from minor number and driver information */
218 interface = usb_find_interface (&idmouse_driver, iminor (inode)); 212 interface = usb_find_interface (&idmouse_driver, iminor (inode));
219 if (!interface) { 213 if (!interface)
220 mutex_unlock(&disconnect_mutex);
221 return -ENODEV; 214 return -ENODEV;
222 } 215
223 /* get the device information block from the interface */ 216 /* get the device information block from the interface */
224 dev = usb_get_intfdata(interface); 217 dev = usb_get_intfdata(interface);
225 if (!dev) { 218 if (!dev)
226 mutex_unlock(&disconnect_mutex);
227 return -ENODEV; 219 return -ENODEV;
228 }
229 220
230 /* lock this device */ 221 /* lock this device */
231 down(&dev->sem); 222 down(&dev->sem);
@@ -255,9 +246,6 @@ error:
255 246
256 /* unlock this device */ 247 /* unlock this device */
257 up(&dev->sem); 248 up(&dev->sem);
258
259 /* unlock the disconnect semaphore */
260 mutex_unlock(&disconnect_mutex);
261 return result; 249 return result;
262} 250}
263 251
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file)
265{ 253{
266 struct usb_idmouse *dev; 254 struct usb_idmouse *dev;
267 255
268 /* prevent a race condition with open() */
269 mutex_lock(&disconnect_mutex);
270
271 dev = file->private_data; 256 dev = file->private_data;
272 257
273 if (dev == NULL) { 258 if (dev == NULL)
274 mutex_unlock(&disconnect_mutex);
275 return -ENODEV; 259 return -ENODEV;
276 }
277 260
278 /* lock our device */ 261 /* lock our device */
279 down(&dev->sem); 262 down(&dev->sem);
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file)
281 /* are we really open? */ 264 /* are we really open? */
282 if (dev->open <= 0) { 265 if (dev->open <= 0) {
283 up(&dev->sem); 266 up(&dev->sem);
284 mutex_unlock(&disconnect_mutex);
285 return -ENODEV; 267 return -ENODEV;
286 } 268 }
287 269
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file)
291 /* the device was unplugged before the file was released */ 273 /* the device was unplugged before the file was released */
292 up(&dev->sem); 274 up(&dev->sem);
293 idmouse_delete(dev); 275 idmouse_delete(dev);
294 mutex_unlock(&disconnect_mutex); 276 } else {
295 return 0; 277 up(&dev->sem);
296 } 278 }
297
298 up(&dev->sem);
299 mutex_unlock(&disconnect_mutex);
300 return 0; 279 return 0;
301} 280}
302 281
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface)
391{ 370{
392 struct usb_idmouse *dev; 371 struct usb_idmouse *dev;
393 372
394 /* prevent races with open() */
395 mutex_lock(&disconnect_mutex);
396
397 /* get device structure */ 373 /* get device structure */
398 dev = usb_get_intfdata(interface); 374 dev = usb_get_intfdata(interface);
399 usb_set_intfdata(interface, NULL); 375 usb_set_intfdata(interface, NULL);
400 376
401 /* lock it */
402 down(&dev->sem);
403
404 /* give back our minor */ 377 /* give back our minor */
405 usb_deregister_dev(interface, &idmouse_class); 378 usb_deregister_dev(interface, &idmouse_class);
406 379
380 /* lock it */
381 down(&dev->sem);
382
407 /* prevent device read, write and ioctl */ 383 /* prevent device read, write and ioctl */
408 dev->present = 0; 384 dev->present = 0;
409 385
410 /* unlock */
411 up(&dev->sem);
412
413 /* if the device is opened, idmouse_release will clean this up */ 386 /* if the device is opened, idmouse_release will clean this up */
414 if (!dev->open) 387 if (!dev->open) {
388 up(&dev->sem);
415 idmouse_delete(dev); 389 idmouse_delete(dev);
416 390 } else {
417 mutex_unlock(&disconnect_mutex); 391 /* unlock */
392 up(&dev->sem);
393 }
418 394
419 info("%s disconnected", DRIVER_DESC); 395 info("%s disconnected", DRIVER_DESC);
420} 396}
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 3bb33f7bfa36..28548d186712 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -100,8 +100,6 @@ struct iowarrior {
100/*--------------*/ 100/*--------------*/
101/* globals */ 101/* globals */
102/*--------------*/ 102/*--------------*/
103/* prevent races between open() and disconnect() */
104static DECLARE_MUTEX(disconnect_sem);
105 103
106/* 104/*
107 * USB spec identifies 5 second timeouts. 105 * USB spec identifies 5 second timeouts.
@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file)
600 598
601 subminor = iminor(inode); 599 subminor = iminor(inode);
602 600
603 /* prevent disconnects */
604 down(&disconnect_sem);
605
606 interface = usb_find_interface(&iowarrior_driver, subminor); 601 interface = usb_find_interface(&iowarrior_driver, subminor);
607 if (!interface) { 602 if (!interface) {
608 err("%s - error, can't find device for minor %d", __FUNCTION__, 603 err("%s - error, can't find device for minor %d", __FUNCTION__,
609 subminor); 604 subminor);
610 retval = -ENODEV; 605 return -ENODEV;
611 goto out;
612 } 606 }
613 607
614 dev = usb_get_intfdata(interface); 608 dev = usb_get_intfdata(interface);
615 if (!dev) { 609 if (!dev)
616 retval = -ENODEV; 610 return -ENODEV;
617 goto out; 611
618 } 612 mutex_lock(&dev->mutex);
619 613
620 /* Only one process can open each device, no sharing. */ 614 /* Only one process can open each device, no sharing. */
621 if (dev->opened) { 615 if (dev->opened) {
@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
636 retval = 0; 630 retval = 0;
637 631
638out: 632out:
639 up(&disconnect_sem); 633 mutex_unlock(&dev->mutex);
640 return retval; 634 return retval;
641} 635}
642 636
@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface)
868 struct iowarrior *dev; 862 struct iowarrior *dev;
869 int minor; 863 int minor;
870 864
871 /* prevent races with open() */
872 down(&disconnect_sem);
873
874 dev = usb_get_intfdata(interface); 865 dev = usb_get_intfdata(interface);
875 usb_set_intfdata(interface, NULL); 866 usb_set_intfdata(interface, NULL);
876 867
877 mutex_lock(&dev->mutex);
878
879 minor = dev->minor; 868 minor = dev->minor;
880 869
881 /* give back our minor */ 870 /* give back our minor */
882 usb_deregister_dev(interface, &iowarrior_class); 871 usb_deregister_dev(interface, &iowarrior_class);
883 872
873 mutex_lock(&dev->mutex);
874
884 /* prevent device read, write and ioctl */ 875 /* prevent device read, write and ioctl */
885 dev->present = 0; 876 dev->present = 0;
886 877
@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
898 /* no process is using the device, cleanup now */ 889 /* no process is using the device, cleanup now */
899 iowarrior_delete(dev); 890 iowarrior_delete(dev);
900 } 891 }
901 up(&disconnect_sem);
902 892
903 dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", 893 dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
904 minor - IOWARRIOR_MINOR_BASE); 894 minor - IOWARRIOR_MINOR_BASE);
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7bad49404762..5e950b90c541 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -176,9 +176,6 @@ struct ld_usb {
176 int interrupt_out_busy; 176 int interrupt_out_busy;
177}; 177};
178 178
179/* prevent races between open() and disconnect() */
180static DEFINE_MUTEX(disconnect_mutex);
181
182static struct usb_driver ld_usb_driver; 179static struct usb_driver ld_usb_driver;
183 180
184/** 181/**
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file)
298{ 295{
299 struct ld_usb *dev; 296 struct ld_usb *dev;
300 int subminor; 297 int subminor;
301 int retval = 0; 298 int retval;
302 struct usb_interface *interface; 299 struct usb_interface *interface;
303 300
304 nonseekable_open(inode, file); 301 nonseekable_open(inode, file);
305 subminor = iminor(inode); 302 subminor = iminor(inode);
306 303
307 mutex_lock(&disconnect_mutex);
308
309 interface = usb_find_interface(&ld_usb_driver, subminor); 304 interface = usb_find_interface(&ld_usb_driver, subminor);
310 305
311 if (!interface) { 306 if (!interface) {
312 err("%s - error, can't find device for minor %d\n", 307 err("%s - error, can't find device for minor %d\n",
313 __FUNCTION__, subminor); 308 __FUNCTION__, subminor);
314 retval = -ENODEV; 309 return -ENODEV;
315 goto unlock_disconnect_exit;
316 } 310 }
317 311
318 dev = usb_get_intfdata(interface); 312 dev = usb_get_intfdata(interface);
319 313
320 if (!dev) { 314 if (!dev)
321 retval = -ENODEV; 315 return -ENODEV;
322 goto unlock_disconnect_exit;
323 }
324 316
325 /* lock this device */ 317 /* lock this device */
326 if (down_interruptible(&dev->sem)) { 318 if (down_interruptible(&dev->sem))
327 retval = -ERESTARTSYS; 319 return -ERESTARTSYS;
328 goto unlock_disconnect_exit;
329 }
330 320
331 /* allow opening only once */ 321 /* allow opening only once */
332 if (dev->open_count) { 322 if (dev->open_count) {
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file)
366unlock_exit: 356unlock_exit:
367 up(&dev->sem); 357 up(&dev->sem);
368 358
369unlock_disconnect_exit:
370 mutex_unlock(&disconnect_mutex);
371
372 return retval; 359 return retval;
373} 360}
374 361
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf)
766 struct ld_usb *dev; 753 struct ld_usb *dev;
767 int minor; 754 int minor;
768 755
769 mutex_lock(&disconnect_mutex);
770
771 dev = usb_get_intfdata(intf); 756 dev = usb_get_intfdata(intf);
772 usb_set_intfdata(intf, NULL); 757 usb_set_intfdata(intf, NULL);
773 758
774 down(&dev->sem);
775
776 minor = intf->minor; 759 minor = intf->minor;
777 760
778 /* give back our minor */ 761 /* give back our minor */
779 usb_deregister_dev(intf, &ld_usb_class); 762 usb_deregister_dev(intf, &ld_usb_class);
780 763
764 down(&dev->sem);
765
781 /* if the device is not opened, then we clean up right now */ 766 /* if the device is not opened, then we clean up right now */
782 if (!dev->open_count) { 767 if (!dev->open_count) {
783 up(&dev->sem); 768 up(&dev->sem);
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
787 up(&dev->sem); 772 up(&dev->sem);
788 } 773 }
789 774
790 mutex_unlock(&disconnect_mutex);
791
792 dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", 775 dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
793 (minor - USB_LD_MINOR_BASE)); 776 (minor - USB_LD_MINOR_BASE));
794} 777}
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 1713e19a7899..2ed0daea894c 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -254,9 +254,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_devic
254static void tower_disconnect (struct usb_interface *interface); 254static void tower_disconnect (struct usb_interface *interface);
255 255
256 256
257/* prevent races between open() and disconnect */
258static DEFINE_MUTEX (disconnect_mutex);
259
260/* file operations needed when we register this driver */ 257/* file operations needed when we register this driver */
261static const struct file_operations tower_fops = { 258static const struct file_operations tower_fops = {
262 .owner = THIS_MODULE, 259 .owner = THIS_MODULE,
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file)
344 nonseekable_open(inode, file); 341 nonseekable_open(inode, file);
345 subminor = iminor(inode); 342 subminor = iminor(inode);
346 343
347 mutex_lock (&disconnect_mutex);
348
349 interface = usb_find_interface (&tower_driver, subminor); 344 interface = usb_find_interface (&tower_driver, subminor);
350 345
351 if (!interface) { 346 if (!interface) {
352 err ("%s - error, can't find device for minor %d", 347 err ("%s - error, can't find device for minor %d",
353 __FUNCTION__, subminor); 348 __FUNCTION__, subminor);
354 retval = -ENODEV; 349 retval = -ENODEV;
355 goto unlock_disconnect_exit; 350 goto exit;
356 } 351 }
357 352
358 dev = usb_get_intfdata(interface); 353 dev = usb_get_intfdata(interface);
359 354
360 if (!dev) { 355 if (!dev) {
361 retval = -ENODEV; 356 retval = -ENODEV;
362 goto unlock_disconnect_exit; 357 goto exit;
363 } 358 }
364 359
365 /* lock this device */ 360 /* lock this device */
366 if (down_interruptible (&dev->sem)) { 361 if (down_interruptible (&dev->sem)) {
367 retval = -ERESTARTSYS; 362 retval = -ERESTARTSYS;
368 goto unlock_disconnect_exit; 363 goto exit;
369 } 364 }
370 365
371 /* allow opening only once */ 366 /* allow opening only once */
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file)
421unlock_exit: 416unlock_exit:
422 up (&dev->sem); 417 up (&dev->sem);
423 418
424unlock_disconnect_exit: 419exit:
425 mutex_unlock (&disconnect_mutex);
426
427 dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); 420 dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
428 421
429 return retval; 422 return retval;
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface)
993 986
994 dbg(2, "%s: enter", __FUNCTION__); 987 dbg(2, "%s: enter", __FUNCTION__);
995 988
996 mutex_lock (&disconnect_mutex);
997
998 dev = usb_get_intfdata (interface); 989 dev = usb_get_intfdata (interface);
999 usb_set_intfdata (interface, NULL); 990 usb_set_intfdata (interface, NULL);
1000 991
1001
1002 down (&dev->sem);
1003
1004 minor = dev->minor; 992 minor = dev->minor;
1005 993
1006 /* give back our minor */ 994 /* give back our minor */
1007 usb_deregister_dev (interface, &tower_class); 995 usb_deregister_dev (interface, &tower_class);
1008 996
997 down (&dev->sem);
998
1009 /* if the device is not opened, then we clean up right now */ 999 /* if the device is not opened, then we clean up right now */
1010 if (!dev->open_count) { 1000 if (!dev->open_count) {
1011 up (&dev->sem); 1001 up (&dev->sem);
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface)
1015 up (&dev->sem); 1005 up (&dev->sem);
1016 } 1006 }
1017 1007
1018 mutex_unlock (&disconnect_mutex);
1019
1020 info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); 1008 info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
1021 1009
1022 dbg(2, "%s: leave", __FUNCTION__); 1010 dbg(2, "%s: leave", __FUNCTION__);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 6f8b134a79cb..9f37ba44c132 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES
72 72
73static struct usb_driver sisusb_driver; 73static struct usb_driver sisusb_driver;
74 74
75DEFINE_MUTEX(disconnect_mutex);
76
77static void 75static void
78sisusb_free_buffers(struct sisusb_usb_data *sisusb) 76sisusb_free_buffers(struct sisusb_usb_data *sisusb)
79{ 77{
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file)
2511 struct usb_interface *interface; 2509 struct usb_interface *interface;
2512 int subminor = iminor(inode); 2510 int subminor = iminor(inode);
2513 2511
2514 mutex_lock(&disconnect_mutex);
2515
2516 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { 2512 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2517 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", 2513 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2518 subminor); 2514 subminor);
2519 mutex_unlock(&disconnect_mutex);
2520 return -ENODEV; 2515 return -ENODEV;
2521 } 2516 }
2522 2517
2523 if (!(sisusb = usb_get_intfdata(interface))) { 2518 if (!(sisusb = usb_get_intfdata(interface)))
2524 mutex_unlock(&disconnect_mutex);
2525 return -ENODEV; 2519 return -ENODEV;
2526 }
2527 2520
2528 mutex_lock(&sisusb->lock); 2521 mutex_lock(&sisusb->lock);
2529 2522
2530 if (!sisusb->present || !sisusb->ready) { 2523 if (!sisusb->present || !sisusb->ready) {
2531 mutex_unlock(&sisusb->lock); 2524 mutex_unlock(&sisusb->lock);
2532 mutex_unlock(&disconnect_mutex);
2533 return -ENODEV; 2525 return -ENODEV;
2534 } 2526 }
2535 2527
2536 if (sisusb->isopen) { 2528 if (sisusb->isopen) {
2537 mutex_unlock(&sisusb->lock); 2529 mutex_unlock(&sisusb->lock);
2538 mutex_unlock(&disconnect_mutex);
2539 return -EBUSY; 2530 return -EBUSY;
2540 } 2531 }
2541 2532
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file)
2543 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { 2534 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2544 if (sisusb_init_gfxdevice(sisusb, 0)) { 2535 if (sisusb_init_gfxdevice(sisusb, 0)) {
2545 mutex_unlock(&sisusb->lock); 2536 mutex_unlock(&sisusb->lock);
2546 mutex_unlock(&disconnect_mutex);
2547 printk(KERN_ERR 2537 printk(KERN_ERR
2548 "sisusbvga[%d]: Failed to initialize " 2538 "sisusbvga[%d]: Failed to initialize "
2549 "device\n", 2539 "device\n",
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file)
2552 } 2542 }
2553 } else { 2543 } else {
2554 mutex_unlock(&sisusb->lock); 2544 mutex_unlock(&sisusb->lock);
2555 mutex_unlock(&disconnect_mutex);
2556 printk(KERN_ERR 2545 printk(KERN_ERR
2557 "sisusbvga[%d]: Device not attached to " 2546 "sisusbvga[%d]: Device not attached to "
2558 "USB 2.0 hub\n", 2547 "USB 2.0 hub\n",
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file)
2570 2559
2571 mutex_unlock(&sisusb->lock); 2560 mutex_unlock(&sisusb->lock);
2572 2561
2573 mutex_unlock(&disconnect_mutex);
2574
2575 return 0; 2562 return 0;
2576} 2563}
2577 2564
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file)
2601 struct sisusb_usb_data *sisusb; 2588 struct sisusb_usb_data *sisusb;
2602 int myminor; 2589 int myminor;
2603 2590
2604 mutex_lock(&disconnect_mutex); 2591 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2605
2606 if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
2607 mutex_unlock(&disconnect_mutex);
2608 return -ENODEV; 2592 return -ENODEV;
2609 }
2610 2593
2611 mutex_lock(&sisusb->lock); 2594 mutex_lock(&sisusb->lock);
2612 2595
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file)
2626 /* decrement the usage count on our device */ 2609 /* decrement the usage count on our device */
2627 kref_put(&sisusb->kref, sisusb_delete); 2610 kref_put(&sisusb->kref, sisusb_delete);
2628 2611
2629 mutex_unlock(&disconnect_mutex);
2630
2631 return 0; 2612 return 0;
2632} 2613}
2633 2614
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf)
3383 sisusb_console_exit(sisusb); 3364 sisusb_console_exit(sisusb);
3384#endif 3365#endif
3385 3366
3386 /* The above code doesn't need the disconnect 3367 minor = sisusb->minor;
3387 * semaphore to be down; its meaning is to 3368
3388 * protect all other routines from the disconnect 3369 usb_deregister_dev(intf, &usb_sisusb_class);
3389 * case, not the other way round.
3390 */
3391 mutex_lock(&disconnect_mutex);
3392 3370
3393 mutex_lock(&sisusb->lock); 3371 mutex_lock(&sisusb->lock);
3394 3372
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf)
3396 if (!sisusb_wait_all_out_complete(sisusb)) 3374 if (!sisusb_wait_all_out_complete(sisusb))
3397 sisusb_kill_all_busy(sisusb); 3375 sisusb_kill_all_busy(sisusb);
3398 3376
3399 minor = sisusb->minor;
3400
3401 usb_set_intfdata(intf, NULL); 3377 usb_set_intfdata(intf, NULL);
3402 3378
3403 usb_deregister_dev(intf, &usb_sisusb_class);
3404
3405#ifdef SISUSB_OLD_CONFIG_COMPAT 3379#ifdef SISUSB_OLD_CONFIG_COMPAT
3406 if (sisusb->ioctl32registered) { 3380 if (sisusb->ioctl32registered) {
3407 int ret; 3381 int ret;
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
3426 /* decrement our usage count */ 3400 /* decrement our usage count */
3427 kref_put(&sisusb->kref, sisusb_delete); 3401 kref_put(&sisusb->kref, sisusb_delete);
3428 3402
3429 mutex_unlock(&disconnect_mutex);
3430
3431 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); 3403 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3432} 3404}
3433 3405
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 5947afb0017e..8d0edc867f33 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init)
214 * are set up/restored. 214 * are set up/restored.
215 */ 215 */
216 216
217 mutex_lock(&disconnect_mutex); 217 if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
218
219 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
220 mutex_unlock(&disconnect_mutex);
221 return; 218 return;
222 }
223 219
224 mutex_lock(&sisusb->lock); 220 mutex_lock(&sisusb->lock);
225 221
226 if (!sisusb_sisusb_valid(sisusb)) { 222 if (!sisusb_sisusb_valid(sisusb)) {
227 mutex_unlock(&sisusb->lock); 223 mutex_unlock(&sisusb->lock);
228 mutex_unlock(&disconnect_mutex);
229 return; 224 return;
230 } 225 }
231 226
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init)
264 259
265 mutex_unlock(&sisusb->lock); 260 mutex_unlock(&sisusb->lock);
266 261
267 mutex_unlock(&disconnect_mutex);
268
269 if (init) { 262 if (init) {
270 c->vc_cols = cols; 263 c->vc_cols = cols;
271 c->vc_rows = rows; 264 c->vc_rows = rows;
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c)
284 * and others, ie not under our control. 277 * and others, ie not under our control.
285 */ 278 */
286 279
287 mutex_lock(&disconnect_mutex); 280 if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
288
289 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
290 mutex_unlock(&disconnect_mutex);
291 return; 281 return;
292 }
293 282
294 mutex_lock(&sisusb->lock); 283 mutex_lock(&sisusb->lock);
295 284
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c)
314 303
315 /* decrement the usage count on our sisusb */ 304 /* decrement the usage count on our sisusb */
316 kref_put(&sisusb->kref, sisusb_delete); 305 kref_put(&sisusb->kref, sisusb_delete);
317
318 mutex_unlock(&disconnect_mutex);
319} 306}
320 307
321/* interface routine */ 308/* interface routine */
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1490{ 1477{
1491 int i, ret, minor = sisusb->minor; 1478 int i, ret, minor = sisusb->minor;
1492 1479
1493 mutex_lock(&disconnect_mutex);
1494
1495 mutex_lock(&sisusb->lock); 1480 mutex_lock(&sisusb->lock);
1496 1481
1497 /* Erm.. that should not happen */ 1482 /* Erm.. that should not happen */
1498 if (sisusb->haveconsole || !sisusb->SiS_Pr) { 1483 if (sisusb->haveconsole || !sisusb->SiS_Pr) {
1499 mutex_unlock(&sisusb->lock); 1484 mutex_unlock(&sisusb->lock);
1500 mutex_unlock(&disconnect_mutex);
1501 return 1; 1485 return 1;
1502 } 1486 }
1503 1487
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1508 first > MAX_NR_CONSOLES || 1492 first > MAX_NR_CONSOLES ||
1509 last > MAX_NR_CONSOLES) { 1493 last > MAX_NR_CONSOLES) {
1510 mutex_unlock(&sisusb->lock); 1494 mutex_unlock(&sisusb->lock);
1511 mutex_unlock(&disconnect_mutex);
1512 return 1; 1495 return 1;
1513 } 1496 }
1514 1497
1515 /* If gfxcore not initialized or no consoles given, quit graciously */ 1498 /* If gfxcore not initialized or no consoles given, quit graciously */
1516 if (!sisusb->gfxinit || first < 1 || last < 1) { 1499 if (!sisusb->gfxinit || first < 1 || last < 1) {
1517 mutex_unlock(&sisusb->lock); 1500 mutex_unlock(&sisusb->lock);
1518 mutex_unlock(&disconnect_mutex);
1519 return 0; 1501 return 0;
1520 } 1502 }
1521 1503
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1526 /* Set up text mode (and upload default font) */ 1508 /* Set up text mode (and upload default font) */
1527 if (sisusb_reset_text_mode(sisusb, 1)) { 1509 if (sisusb_reset_text_mode(sisusb, 1)) {
1528 mutex_unlock(&sisusb->lock); 1510 mutex_unlock(&sisusb->lock);
1529 mutex_unlock(&disconnect_mutex);
1530 printk(KERN_ERR 1511 printk(KERN_ERR
1531 "sisusbvga[%d]: Failed to set up text mode\n", 1512 "sisusbvga[%d]: Failed to set up text mode\n",
1532 minor); 1513 minor);
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1550 /* Allocate screen buffer */ 1531 /* Allocate screen buffer */
1551 if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { 1532 if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
1552 mutex_unlock(&sisusb->lock); 1533 mutex_unlock(&sisusb->lock);
1553 mutex_unlock(&disconnect_mutex);
1554 printk(KERN_ERR 1534 printk(KERN_ERR
1555 "sisusbvga[%d]: Failed to allocate screen buffer\n", 1535 "sisusbvga[%d]: Failed to allocate screen buffer\n",
1556 minor); 1536 minor);
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1558 } 1538 }
1559 1539
1560 mutex_unlock(&sisusb->lock); 1540 mutex_unlock(&sisusb->lock);
1561 mutex_unlock(&disconnect_mutex);
1562 1541
1563 /* Now grab the desired console(s) */ 1542 /* Now grab the desired console(s) */
1564 ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); 1543 ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
index f05f83268af4..864bc0e96591 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] =
808 { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ 808 { 0x2b,0xc2, 35} /* 0x71 768@576@60 */
809}; 809};
810 810
811extern struct mutex disconnect_mutex;
812
813int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 811int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
814int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); 812int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
815 813
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 12bad8a205a7..6e093c2aac2c 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -51,7 +51,6 @@ struct usb_lcd {
51#define USB_LCD_CONCURRENT_WRITES 5 51#define USB_LCD_CONCURRENT_WRITES 5
52 52
53static struct usb_driver lcd_driver; 53static struct usb_driver lcd_driver;
54static DEFINE_MUTEX(usb_lcd_open_mutex);
55 54
56 55
57static void lcd_delete(struct kref *kref) 56static void lcd_delete(struct kref *kref)
@@ -69,24 +68,19 @@ static int lcd_open(struct inode *inode, struct file *file)
69 struct usb_lcd *dev; 68 struct usb_lcd *dev;
70 struct usb_interface *interface; 69 struct usb_interface *interface;
71 int subminor; 70 int subminor;
72 int retval = 0;
73 71
74 subminor = iminor(inode); 72 subminor = iminor(inode);
75 73
76 mutex_lock(&usb_lcd_open_mutex);
77 interface = usb_find_interface(&lcd_driver, subminor); 74 interface = usb_find_interface(&lcd_driver, subminor);
78 if (!interface) { 75 if (!interface) {
79 err ("USBLCD: %s - error, can't find device for minor %d", 76 err ("USBLCD: %s - error, can't find device for minor %d",
80 __FUNCTION__, subminor); 77 __FUNCTION__, subminor);
81 retval = -ENODEV; 78 return -ENODEV;
82 goto exit;
83 } 79 }
84 80
85 dev = usb_get_intfdata(interface); 81 dev = usb_get_intfdata(interface);
86 if (!dev) { 82 if (!dev)
87 retval = -ENODEV; 83 return -ENODEV;
88 goto exit;
89 }
90 84
91 /* increment our usage count for the device */ 85 /* increment our usage count for the device */
92 kref_get(&dev->kref); 86 kref_get(&dev->kref);
@@ -94,9 +88,7 @@ static int lcd_open(struct inode *inode, struct file *file)
94 /* save our object in the file's private structure */ 88 /* save our object in the file's private structure */
95 file->private_data = dev; 89 file->private_data = dev;
96 90
97exit: 91 return 0;
98 mutex_unlock(&usb_lcd_open_mutex);
99 return retval;
100} 92}
101 93
102static int lcd_release(struct inode *inode, struct file *file) 94static int lcd_release(struct inode *inode, struct file *file)
@@ -363,17 +355,12 @@ static void lcd_disconnect(struct usb_interface *interface)
363 struct usb_lcd *dev; 355 struct usb_lcd *dev;
364 int minor = interface->minor; 356 int minor = interface->minor;
365 357
366 /* prevent skel_open() from racing skel_disconnect() */
367 mutex_lock(&usb_lcd_open_mutex);
368
369 dev = usb_get_intfdata(interface); 358 dev = usb_get_intfdata(interface);
370 usb_set_intfdata(interface, NULL); 359 usb_set_intfdata(interface, NULL);
371 360
372 /* give back our minor */ 361 /* give back our minor */
373 usb_deregister_dev(interface, &lcd_class); 362 usb_deregister_dev(interface, &lcd_class);
374 363
375 mutex_unlock(&usb_lcd_open_mutex);
376
377 /* decrement our usage count */ 364 /* decrement our usage count */
378 kref_put(&dev->kref, lcd_delete); 365 kref_put(&dev->kref, lcd_delete);
379 366
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 8432bf171d2e..38f8e4df9dd6 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -34,9 +34,6 @@ static struct usb_device_id skel_table [] = {
34}; 34};
35MODULE_DEVICE_TABLE(usb, skel_table); 35MODULE_DEVICE_TABLE(usb, skel_table);
36 36
37/* to prevent a race between open and disconnect */
38static DEFINE_MUTEX(skel_open_lock);
39
40 37
41/* Get a minor range for your devices from the usb maintainer */ 38/* Get a minor range for your devices from the usb maintainer */
42#define USB_SKEL_MINOR_BASE 192 39#define USB_SKEL_MINOR_BASE 192
@@ -83,10 +80,8 @@ static int skel_open(struct inode *inode, struct file *file)
83 80
84 subminor = iminor(inode); 81 subminor = iminor(inode);
85 82
86 mutex_lock(&skel_open_lock);
87 interface = usb_find_interface(&skel_driver, subminor); 83 interface = usb_find_interface(&skel_driver, subminor);
88 if (!interface) { 84 if (!interface) {
89 mutex_unlock(&skel_open_lock);
90 err ("%s - error, can't find device for minor %d", 85 err ("%s - error, can't find device for minor %d",
91 __FUNCTION__, subminor); 86 __FUNCTION__, subminor);
92 retval = -ENODEV; 87 retval = -ENODEV;
@@ -95,15 +90,12 @@ static int skel_open(struct inode *inode, struct file *file)
95 90
96 dev = usb_get_intfdata(interface); 91 dev = usb_get_intfdata(interface);
97 if (!dev) { 92 if (!dev) {
98 mutex_unlock(&skel_open_lock);
99 retval = -ENODEV; 93 retval = -ENODEV;
100 goto exit; 94 goto exit;
101 } 95 }
102 96
103 /* increment our usage count for the device */ 97 /* increment our usage count for the device */
104 kref_get(&dev->kref); 98 kref_get(&dev->kref);
105 /* now we can drop the lock */
106 mutex_unlock(&skel_open_lock);
107 99
108 /* prevent the device from being autosuspended */ 100 /* prevent the device from being autosuspended */
109 retval = usb_autopm_get_interface(interface); 101 retval = usb_autopm_get_interface(interface);
@@ -368,23 +360,17 @@ static void skel_disconnect(struct usb_interface *interface)
368 struct usb_skel *dev; 360 struct usb_skel *dev;
369 int minor = interface->minor; 361 int minor = interface->minor;
370 362
371 /* prevent skel_open() from racing skel_disconnect() */
372 mutex_lock(&skel_open_lock);
373
374 dev = usb_get_intfdata(interface); 363 dev = usb_get_intfdata(interface);
375 usb_set_intfdata(interface, NULL); 364 usb_set_intfdata(interface, NULL);
376 365
377 /* give back our minor */ 366 /* give back our minor */
378 usb_deregister_dev(interface, &skel_class); 367 usb_deregister_dev(interface, &skel_class);
379 mutex_unlock(&skel_open_lock);
380 368
381 /* prevent more I/O from starting */ 369 /* prevent more I/O from starting */
382 mutex_lock(&dev->io_mutex); 370 mutex_lock(&dev->io_mutex);
383 dev->interface = NULL; 371 dev->interface = NULL;
384 mutex_unlock(&dev->io_mutex); 372 mutex_unlock(&dev->io_mutex);
385 373
386
387
388 /* decrement our usage count */ 374 /* decrement our usage count */
389 kref_put(&dev->kref, skel_delete); 375 kref_put(&dev->kref, skel_delete);
390 376