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.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 1b1e669dff9a..59973aecd968 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -57,6 +57,7 @@ struct usb_skel {
57 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 57 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
58 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ 58 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
59 int errors; /* the last request tanked */ 59 int errors; /* the last request tanked */
60 int open_count; /* count the number of openers */
60 spinlock_t err_lock; /* lock for errors */ 61 spinlock_t err_lock; /* lock for errors */
61 struct kref kref; 62 struct kref kref;
62 struct mutex io_mutex; /* synchronize I/O with disconnect */ 63 struct mutex io_mutex; /* synchronize I/O with disconnect */
@@ -101,12 +102,26 @@ static int skel_open(struct inode *inode, struct file *file)
101 /* increment our usage count for the device */ 102 /* increment our usage count for the device */
102 kref_get(&dev->kref); 103 kref_get(&dev->kref);
103 104
104 /* prevent the device from being autosuspended */ 105 /* lock the device to allow correctly handling errors
105 retval = usb_autopm_get_interface(interface); 106 * in resumption */
106 if (retval) { 107 mutex_lock(&dev->io_mutex);
108
109 if (!dev->open_count++) {
110 retval = usb_autopm_get_interface(interface);
111 if (retval) {
112 dev->open_count--;
113 mutex_unlock(&dev->io_mutex);
114 kref_put(&dev->kref, skel_delete);
115 goto exit;
116 }
117 } /* else { //uncomment this block if you want exclusive open
118 retval = -EBUSY;
119 dev->open_count--;
120 mutex_unlock(&dev->io_mutex);
107 kref_put(&dev->kref, skel_delete); 121 kref_put(&dev->kref, skel_delete);
108 goto exit; 122 goto exit;
109 } 123 } */
124 /* prevent the device from being autosuspended */
110 125
111 /* save our object in the file's private structure */ 126 /* save our object in the file's private structure */
112 file->private_data = dev; 127 file->private_data = dev;
@@ -125,7 +140,7 @@ static int skel_release(struct inode *inode, struct file *file)
125 140
126 /* allow the device to be autosuspended */ 141 /* allow the device to be autosuspended */
127 mutex_lock(&dev->io_mutex); 142 mutex_lock(&dev->io_mutex);
128 if (dev->interface) 143 if (!--dev->open_count && dev->interface)
129 usb_autopm_put_interface(dev->interface); 144 usb_autopm_put_interface(dev->interface);
130 mutex_unlock(&dev->io_mutex); 145 mutex_unlock(&dev->io_mutex);
131 146
@@ -437,10 +452,27 @@ static void skel_draw_down(struct usb_skel *dev)
437 usb_kill_anchored_urbs(&dev->submitted); 452 usb_kill_anchored_urbs(&dev->submitted);
438} 453}
439 454
455static int skel_suspend(struct usb_interface *intf, pm_message_t message)
456{
457 struct usb_skel *dev = usb_get_intfdata(intf);
458
459 if (!dev)
460 return 0;
461 skel_draw_down(dev);
462 return 0;
463}
464
465static int skel_resume (struct usb_interface *intf)
466{
467 return 0;
468}
469
440static struct usb_driver skel_driver = { 470static struct usb_driver skel_driver = {
441 .name = "skeleton", 471 .name = "skeleton",
442 .probe = skel_probe, 472 .probe = skel_probe,
443 .disconnect = skel_disconnect, 473 .disconnect = skel_disconnect,
474 .suspend = skel_suspend,
475 .resume = skel_resume,
444 .id_table = skel_table, 476 .id_table = skel_table,
445 .supports_autosuspend = 1, 477 .supports_autosuspend = 1,
446}; 478};