diff options
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r-- | drivers/usb/usb-skeleton.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 5c6c1bdbd455..8efeae24764f 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -27,6 +27,8 @@ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 +static DEFINE_MUTEX(skel_mutex); + /* table of devices that work with this driver */ static const struct usb_device_id skel_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, @@ -60,7 +62,6 @@ struct usb_skel { __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ int errors; /* the last request tanked */ - int open_count; /* count the number of openers */ bool ongoing_read; /* a read is going on */ bool processed_urb; /* indicates we haven't processed the urb */ spinlock_t err_lock; /* lock for errors */ @@ -100,39 +101,37 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } + mutex_lock(&skel_mutex); dev = usb_get_intfdata(interface); if (!dev) { + mutex_unlock(&skel_mutex); retval = -ENODEV; goto exit; } /* increment our usage count for the device */ kref_get(&dev->kref); + mutex_unlock(&skel_mutex); /* lock the device to allow correctly handling errors * in resumption */ mutex_lock(&dev->io_mutex); + if (!dev->interface) { + retval = -ENODEV; + goto out_err; + } - if (!dev->open_count++) { - retval = usb_autopm_get_interface(interface); - if (retval) { - dev->open_count--; - mutex_unlock(&dev->io_mutex); - kref_put(&dev->kref, skel_delete); - goto exit; - } - } /* else { //uncomment this block if you want exclusive open - retval = -EBUSY; - dev->open_count--; - mutex_unlock(&dev->io_mutex); - kref_put(&dev->kref, skel_delete); - goto exit; - } */ - /* prevent the device from being autosuspended */ + retval = usb_autopm_get_interface(interface); + if (retval) + goto out_err; /* save our object in the file's private structure */ file->private_data = dev; + +out_err: mutex_unlock(&dev->io_mutex); + if (retval) + kref_put(&dev->kref, skel_delete); exit: return retval; @@ -148,7 +147,7 @@ static int skel_release(struct inode *inode, struct file *file) /* allow the device to be autosuspended */ mutex_lock(&dev->io_mutex); - if (!--dev->open_count && dev->interface) + if (dev->interface) usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); @@ -612,7 +611,6 @@ static void skel_disconnect(struct usb_interface *interface) int minor = interface->minor; dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &skel_class); @@ -624,8 +622,12 @@ static void skel_disconnect(struct usb_interface *interface) usb_kill_anchored_urbs(&dev->submitted); + mutex_lock(&skel_mutex); + usb_set_intfdata(interface, NULL); + /* decrement our usage count */ kref_put(&dev->kref, skel_delete); + mutex_unlock(&skel_mutex); dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } |