aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/usb-skeleton.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r--drivers/usb/usb-skeleton.c12
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};
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
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);