diff options
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r-- | drivers/usb/usb-skeleton.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 962b28cd3a79..8432bf171d2e 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -34,6 +34,9 @@ static struct usb_device_id skel_table [] = { | |||
34 | }; | 34 | }; |
35 | MODULE_DEVICE_TABLE(usb, skel_table); | 35 | MODULE_DEVICE_TABLE(usb, skel_table); |
36 | 36 | ||
37 | /* to prevent a race between open and disconnect */ | ||
38 | static DEFINE_MUTEX(skel_open_lock); | ||
39 | |||
37 | 40 | ||
38 | /* Get a minor range for your devices from the usb maintainer */ | 41 | /* Get a minor range for your devices from the usb maintainer */ |
39 | #define USB_SKEL_MINOR_BASE 192 | 42 | #define USB_SKEL_MINOR_BASE 192 |
@@ -80,8 +83,10 @@ static int skel_open(struct inode *inode, struct file *file) | |||
80 | 83 | ||
81 | subminor = iminor(inode); | 84 | subminor = iminor(inode); |
82 | 85 | ||
86 | mutex_lock(&skel_open_lock); | ||
83 | interface = usb_find_interface(&skel_driver, subminor); | 87 | interface = usb_find_interface(&skel_driver, subminor); |
84 | if (!interface) { | 88 | if (!interface) { |
89 | mutex_unlock(&skel_open_lock); | ||
85 | err ("%s - error, can't find device for minor %d", | 90 | err ("%s - error, can't find device for minor %d", |
86 | __FUNCTION__, subminor); | 91 | __FUNCTION__, subminor); |
87 | retval = -ENODEV; | 92 | retval = -ENODEV; |
@@ -90,12 +95,15 @@ static int skel_open(struct inode *inode, struct file *file) | |||
90 | 95 | ||
91 | dev = usb_get_intfdata(interface); | 96 | dev = usb_get_intfdata(interface); |
92 | if (!dev) { | 97 | if (!dev) { |
98 | mutex_unlock(&skel_open_lock); | ||
93 | retval = -ENODEV; | 99 | retval = -ENODEV; |
94 | goto exit; | 100 | goto exit; |
95 | } | 101 | } |
96 | 102 | ||
97 | /* increment our usage count for the device */ | 103 | /* increment our usage count for the device */ |
98 | kref_get(&dev->kref); | 104 | kref_get(&dev->kref); |
105 | /* now we can drop the lock */ | ||
106 | mutex_unlock(&skel_open_lock); | ||
99 | 107 | ||
100 | /* prevent the device from being autosuspended */ | 108 | /* prevent the device from being autosuspended */ |
101 | retval = usb_autopm_get_interface(interface); | 109 | retval = usb_autopm_get_interface(interface); |
@@ -361,14 +369,14 @@ static void skel_disconnect(struct usb_interface *interface) | |||
361 | int minor = interface->minor; | 369 | int minor = interface->minor; |
362 | 370 | ||
363 | /* prevent skel_open() from racing skel_disconnect() */ | 371 | /* prevent skel_open() from racing skel_disconnect() */ |
364 | lock_kernel(); | 372 | mutex_lock(&skel_open_lock); |
365 | 373 | ||
366 | dev = usb_get_intfdata(interface); | 374 | dev = usb_get_intfdata(interface); |
367 | usb_set_intfdata(interface, NULL); | 375 | usb_set_intfdata(interface, NULL); |
368 | 376 | ||
369 | /* give back our minor */ | 377 | /* give back our minor */ |
370 | usb_deregister_dev(interface, &skel_class); | 378 | usb_deregister_dev(interface, &skel_class); |
371 | unlock_kernel(); | 379 | mutex_unlock(&skel_open_lock); |
372 | 380 | ||
373 | /* prevent more I/O from starting */ | 381 | /* prevent more I/O from starting */ |
374 | mutex_lock(&dev->io_mutex); | 382 | mutex_lock(&dev->io_mutex); |