diff options
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r-- | drivers/usb/usb-skeleton.c | 42 |
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 | ||
455 | static 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 | |||
465 | static int skel_resume (struct usb_interface *intf) | ||
466 | { | ||
467 | return 0; | ||
468 | } | ||
469 | |||
440 | static struct usb_driver skel_driver = { | 470 | static 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 | }; |