diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 19:46:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 19:46:58 -0400 |
commit | 9374430a52dfae5c013b88f7f030c04a6774d410 (patch) | |
tree | ce1ee8eee4e79fbb9486e810278d1092afc74a44 /drivers/usb/misc | |
parent | 66f49739fe1591197364f2dad1b67b975e8f5e85 (diff) | |
parent | 13f9966b3ba5b45f47f2ea0eb0a90afceedfbb1f (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (149 commits)
USB: ohci-pnx4008: Remove unnecessary cast of return value of kzalloc
USB: additions to the quirk list
usb-storage: implement autosuspend
USB: cdc-acm: add new device id to option driver
USB: goku_udc trivial cleanups
USB: usb gadget stack can now -DDEBUG with Kconfig
usb gadget stack: remove usb_ep_*_buffer(), part 2
usb gadget stack: remove usb_ep_*_buffer(), part 1
USB: pxa2xx_udc -- cleanups, mostly removing dma hooks
USB: pxa2xx_udc: use generic gpio layer
USB: quirk for samsung printer
USB: usb/dma doc updates
USB: drivers/usb/storage/unusual_devs.h whitespace cleanup
USB: remove Makefile reference to obsolete OHCI_AT91
USB: io_*: remove bogus termios no change checks
USB: mos7720: remove bogus no termios change check
USB: visor and whiteheat: remove bogus termios change checks
USB: pl2303: remove bogus checks and fix speed support to use tty_get_baud_rate()
USB: mos7840.c: turn this into a serial driver
USB: make the usb_device numa_node get assigned from controller
...
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/adutux.c | 31 | ||||
-rw-r--r-- | drivers/usb/misc/auerswald.c | 6 | ||||
-rw-r--r-- | drivers/usb/misc/berry_charge.c | 35 | ||||
-rw-r--r-- | drivers/usb/misc/idmouse.c | 54 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 26 | ||||
-rw-r--r-- | drivers/usb/misc/ldusb.c | 33 | ||||
-rw-r--r-- | drivers/usb/misc/legousbtower.c | 24 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb.c | 38 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb_con.c | 25 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb_init.h | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usblcd.c | 67 |
11 files changed, 140 insertions, 201 deletions
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 77145f9db043..d72c42e5f22d 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -108,8 +108,6 @@ struct adu_device { | |||
108 | struct urb* interrupt_out_urb; | 108 | struct urb* interrupt_out_urb; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | /* prevent races between open() and disconnect */ | ||
112 | static DEFINE_MUTEX(disconnect_mutex); | ||
113 | static struct usb_driver adu_driver; | 111 | static struct usb_driver adu_driver; |
114 | 112 | ||
115 | static void adu_debug_data(int level, const char *function, int size, | 113 | static void adu_debug_data(int level, const char *function, int size, |
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file) | |||
256 | 254 | ||
257 | subminor = iminor(inode); | 255 | subminor = iminor(inode); |
258 | 256 | ||
259 | mutex_lock(&disconnect_mutex); | ||
260 | |||
261 | interface = usb_find_interface(&adu_driver, subminor); | 257 | interface = usb_find_interface(&adu_driver, subminor); |
262 | if (!interface) { | 258 | if (!interface) { |
263 | err("%s - error, can't find device for minor %d", | 259 | err("%s - error, can't find device for minor %d", |
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file) | |||
306 | up(&dev->sem); | 302 | up(&dev->sem); |
307 | 303 | ||
308 | exit_no_device: | 304 | exit_no_device: |
309 | mutex_unlock(&disconnect_mutex); | ||
310 | dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); | 305 | dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); |
311 | 306 | ||
312 | return retval; | 307 | return retval; |
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev) | |||
318 | 313 | ||
319 | dbg(2," %s : enter", __FUNCTION__); | 314 | dbg(2," %s : enter", __FUNCTION__); |
320 | 315 | ||
321 | if (dev->udev == NULL) { | ||
322 | /* the device was unplugged before the file was released */ | ||
323 | adu_delete(dev); | ||
324 | goto exit; | ||
325 | } | ||
326 | |||
327 | /* decrement our usage count for the device */ | 316 | /* decrement our usage count for the device */ |
328 | --dev->open_count; | 317 | --dev->open_count; |
329 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | 318 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); |
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev) | |||
332 | dev->open_count = 0; | 321 | dev->open_count = 0; |
333 | } | 322 | } |
334 | 323 | ||
335 | exit: | ||
336 | dbg(2," %s : leave", __FUNCTION__); | 324 | dbg(2," %s : leave", __FUNCTION__); |
337 | return retval; | 325 | return retval; |
338 | } | 326 | } |
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file) | |||
367 | goto exit; | 355 | goto exit; |
368 | } | 356 | } |
369 | 357 | ||
370 | /* do the work */ | 358 | if (dev->udev == NULL) { |
371 | retval = adu_release_internal(dev); | 359 | /* the device was unplugged before the file was released */ |
360 | up(&dev->sem); | ||
361 | adu_delete(dev); | ||
362 | dev = NULL; | ||
363 | } else { | ||
364 | /* do the work */ | ||
365 | retval = adu_release_internal(dev); | ||
366 | } | ||
372 | 367 | ||
373 | exit: | 368 | exit: |
374 | if (dev) | 369 | if (dev) |
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface) | |||
831 | 826 | ||
832 | dbg(2," %s : enter", __FUNCTION__); | 827 | dbg(2," %s : enter", __FUNCTION__); |
833 | 828 | ||
834 | mutex_lock(&disconnect_mutex); /* not interruptible */ | ||
835 | |||
836 | dev = usb_get_intfdata(interface); | 829 | dev = usb_get_intfdata(interface); |
837 | usb_set_intfdata(interface, NULL); | 830 | usb_set_intfdata(interface, NULL); |
838 | 831 | ||
839 | down(&dev->sem); /* not interruptible */ | ||
840 | |||
841 | minor = dev->minor; | 832 | minor = dev->minor; |
842 | 833 | ||
843 | /* give back our minor */ | 834 | /* give back our minor */ |
844 | usb_deregister_dev(interface, &adu_class); | 835 | usb_deregister_dev(interface, &adu_class); |
845 | dev->minor = 0; | 836 | dev->minor = 0; |
846 | 837 | ||
838 | down(&dev->sem); /* not interruptible */ | ||
839 | |||
847 | /* if the device is not opened, then we clean up right now */ | 840 | /* if the device is not opened, then we clean up right now */ |
848 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | 841 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); |
849 | if (!dev->open_count) { | 842 | if (!dev->open_count) { |
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface) | |||
854 | up(&dev->sem); | 847 | up(&dev->sem); |
855 | } | 848 | } |
856 | 849 | ||
857 | mutex_unlock(&disconnect_mutex); | ||
858 | |||
859 | dev_info(&interface->dev, "ADU device adutux%d now disconnected", | 850 | dev_info(&interface->dev, "ADU device adutux%d now disconnected", |
860 | (minor - ADU_MINOR_BASE)); | 851 | (minor - ADU_MINOR_BASE)); |
861 | 852 | ||
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index cac1500cba62..1fd5fc220cd7 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c | |||
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf) | |||
2034 | if (!cp) | 2034 | if (!cp) |
2035 | return; | 2035 | return; |
2036 | 2036 | ||
2037 | down (&cp->mutex); | ||
2038 | info ("device /dev/%s now disconnecting", cp->name); | ||
2039 | |||
2040 | /* give back our USB minor number */ | 2037 | /* give back our USB minor number */ |
2041 | usb_deregister_dev(intf, &auerswald_class); | 2038 | usb_deregister_dev(intf, &auerswald_class); |
2042 | 2039 | ||
2040 | down (&cp->mutex); | ||
2041 | info ("device /dev/%s now disconnecting", cp->name); | ||
2042 | |||
2043 | /* Stop the interrupt endpoint */ | 2043 | /* Stop the interrupt endpoint */ |
2044 | auerswald_int_release (cp); | 2044 | auerswald_int_release (cp); |
2045 | 2045 | ||
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index b15f2fd8dab4..92c1d2768df9 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c | |||
@@ -26,8 +26,11 @@ | |||
26 | 26 | ||
27 | #define RIM_VENDOR 0x0fca | 27 | #define RIM_VENDOR 0x0fca |
28 | #define BLACKBERRY 0x0001 | 28 | #define BLACKBERRY 0x0001 |
29 | #define BLACKBERRY_PEARL_DUAL 0x0004 | ||
30 | #define BLACKBERRY_PEARL 0x0006 | ||
29 | 31 | ||
30 | static int debug; | 32 | static int debug; |
33 | static int pearl_dual_mode = 1; | ||
31 | 34 | ||
32 | #ifdef dbg | 35 | #ifdef dbg |
33 | #undef dbg | 36 | #undef dbg |
@@ -38,6 +41,8 @@ static int debug; | |||
38 | 41 | ||
39 | static struct usb_device_id id_table [] = { | 42 | static struct usb_device_id id_table [] = { |
40 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, | 43 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, |
44 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) }, | ||
45 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) }, | ||
41 | { }, /* Terminating entry */ | 46 | { }, /* Terminating entry */ |
42 | }; | 47 | }; |
43 | MODULE_DEVICE_TABLE(usb, id_table); | 48 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev) | |||
86 | return retval; | 91 | return retval; |
87 | } | 92 | } |
88 | 93 | ||
94 | static int magic_dual_mode(struct usb_device *udev) | ||
95 | { | ||
96 | char *dummy_buffer = kzalloc(2, GFP_KERNEL); | ||
97 | int retval; | ||
98 | |||
99 | if (!dummy_buffer) | ||
100 | return -ENOMEM; | ||
101 | |||
102 | /* send magic command so that the Blackberry Pearl device exposes | ||
103 | * two interfaces: both the USB mass-storage one and one which can | ||
104 | * be used for database access. */ | ||
105 | dbg(&udev->dev, "Sending magic pearl command\n"); | ||
106 | retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
107 | 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100); | ||
108 | dbg(&udev->dev, "Magic pearl command returned %d\n", retval); | ||
109 | |||
110 | dbg(&udev->dev, "Calling set_configuration\n"); | ||
111 | retval = usb_driver_set_configuration(udev, 1); | ||
112 | if (retval) | ||
113 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); | ||
114 | |||
115 | return retval; | ||
116 | } | ||
117 | |||
89 | static int berry_probe(struct usb_interface *intf, | 118 | static int berry_probe(struct usb_interface *intf, |
90 | const struct usb_device_id *id) | 119 | const struct usb_device_id *id) |
91 | { | 120 | { |
@@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf, | |||
105 | /* turn the power on */ | 134 | /* turn the power on */ |
106 | magic_charge(udev); | 135 | magic_charge(udev); |
107 | 136 | ||
137 | if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) && | ||
138 | (pearl_dual_mode)) | ||
139 | magic_dual_mode(udev); | ||
140 | |||
108 | /* we don't really want to bind to the device, userspace programs can | 141 | /* we don't really want to bind to the device, userspace programs can |
109 | * handle the syncing just fine, so get outta here. */ | 142 | * handle the syncing just fine, so get outta here. */ |
110 | return -ENODEV; | 143 | return -ENODEV; |
@@ -138,3 +171,5 @@ MODULE_LICENSE("GPL"); | |||
138 | MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); | 171 | MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); |
139 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 172 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
140 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 173 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
174 | module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR); | ||
175 | MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode"); | ||
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 8d0e360636e6..e6fd024024f5 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = { | |||
119 | .id_table = idmouse_table, | 119 | .id_table = idmouse_table, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | /* prevent races between open() and disconnect() */ | ||
123 | static DEFINE_MUTEX(disconnect_mutex); | ||
124 | |||
125 | static int idmouse_create_image(struct usb_idmouse *dev) | 122 | static int idmouse_create_image(struct usb_idmouse *dev) |
126 | { | 123 | { |
127 | int bytes_read; | 124 | int bytes_read; |
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file) | |||
211 | struct usb_interface *interface; | 208 | struct usb_interface *interface; |
212 | int result; | 209 | int result; |
213 | 210 | ||
214 | /* prevent disconnects */ | ||
215 | mutex_lock(&disconnect_mutex); | ||
216 | |||
217 | /* get the interface from minor number and driver information */ | 211 | /* get the interface from minor number and driver information */ |
218 | interface = usb_find_interface (&idmouse_driver, iminor (inode)); | 212 | interface = usb_find_interface (&idmouse_driver, iminor (inode)); |
219 | if (!interface) { | 213 | if (!interface) |
220 | mutex_unlock(&disconnect_mutex); | ||
221 | return -ENODEV; | 214 | return -ENODEV; |
222 | } | 215 | |
223 | /* get the device information block from the interface */ | 216 | /* get the device information block from the interface */ |
224 | dev = usb_get_intfdata(interface); | 217 | dev = usb_get_intfdata(interface); |
225 | if (!dev) { | 218 | if (!dev) |
226 | mutex_unlock(&disconnect_mutex); | ||
227 | return -ENODEV; | 219 | return -ENODEV; |
228 | } | ||
229 | 220 | ||
230 | /* lock this device */ | 221 | /* lock this device */ |
231 | down(&dev->sem); | 222 | down(&dev->sem); |
@@ -255,9 +246,6 @@ error: | |||
255 | 246 | ||
256 | /* unlock this device */ | 247 | /* unlock this device */ |
257 | up(&dev->sem); | 248 | up(&dev->sem); |
258 | |||
259 | /* unlock the disconnect semaphore */ | ||
260 | mutex_unlock(&disconnect_mutex); | ||
261 | return result; | 249 | return result; |
262 | } | 250 | } |
263 | 251 | ||
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
265 | { | 253 | { |
266 | struct usb_idmouse *dev; | 254 | struct usb_idmouse *dev; |
267 | 255 | ||
268 | /* prevent a race condition with open() */ | ||
269 | mutex_lock(&disconnect_mutex); | ||
270 | |||
271 | dev = file->private_data; | 256 | dev = file->private_data; |
272 | 257 | ||
273 | if (dev == NULL) { | 258 | if (dev == NULL) |
274 | mutex_unlock(&disconnect_mutex); | ||
275 | return -ENODEV; | 259 | return -ENODEV; |
276 | } | ||
277 | 260 | ||
278 | /* lock our device */ | 261 | /* lock our device */ |
279 | down(&dev->sem); | 262 | down(&dev->sem); |
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
281 | /* are we really open? */ | 264 | /* are we really open? */ |
282 | if (dev->open <= 0) { | 265 | if (dev->open <= 0) { |
283 | up(&dev->sem); | 266 | up(&dev->sem); |
284 | mutex_unlock(&disconnect_mutex); | ||
285 | return -ENODEV; | 267 | return -ENODEV; |
286 | } | 268 | } |
287 | 269 | ||
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
291 | /* the device was unplugged before the file was released */ | 273 | /* the device was unplugged before the file was released */ |
292 | up(&dev->sem); | 274 | up(&dev->sem); |
293 | idmouse_delete(dev); | 275 | idmouse_delete(dev); |
294 | mutex_unlock(&disconnect_mutex); | 276 | } else { |
295 | return 0; | 277 | up(&dev->sem); |
296 | } | 278 | } |
297 | |||
298 | up(&dev->sem); | ||
299 | mutex_unlock(&disconnect_mutex); | ||
300 | return 0; | 279 | return 0; |
301 | } | 280 | } |
302 | 281 | ||
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface) | |||
391 | { | 370 | { |
392 | struct usb_idmouse *dev; | 371 | struct usb_idmouse *dev; |
393 | 372 | ||
394 | /* prevent races with open() */ | ||
395 | mutex_lock(&disconnect_mutex); | ||
396 | |||
397 | /* get device structure */ | 373 | /* get device structure */ |
398 | dev = usb_get_intfdata(interface); | 374 | dev = usb_get_intfdata(interface); |
399 | usb_set_intfdata(interface, NULL); | 375 | usb_set_intfdata(interface, NULL); |
400 | 376 | ||
401 | /* lock it */ | ||
402 | down(&dev->sem); | ||
403 | |||
404 | /* give back our minor */ | 377 | /* give back our minor */ |
405 | usb_deregister_dev(interface, &idmouse_class); | 378 | usb_deregister_dev(interface, &idmouse_class); |
406 | 379 | ||
380 | /* lock it */ | ||
381 | down(&dev->sem); | ||
382 | |||
407 | /* prevent device read, write and ioctl */ | 383 | /* prevent device read, write and ioctl */ |
408 | dev->present = 0; | 384 | dev->present = 0; |
409 | 385 | ||
410 | /* unlock */ | ||
411 | up(&dev->sem); | ||
412 | |||
413 | /* if the device is opened, idmouse_release will clean this up */ | 386 | /* if the device is opened, idmouse_release will clean this up */ |
414 | if (!dev->open) | 387 | if (!dev->open) { |
388 | up(&dev->sem); | ||
415 | idmouse_delete(dev); | 389 | idmouse_delete(dev); |
416 | 390 | } else { | |
417 | mutex_unlock(&disconnect_mutex); | 391 | /* unlock */ |
392 | up(&dev->sem); | ||
393 | } | ||
418 | 394 | ||
419 | info("%s disconnected", DRIVER_DESC); | 395 | info("%s disconnected", DRIVER_DESC); |
420 | } | 396 | } |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 3bb33f7bfa36..28548d186712 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -100,8 +100,6 @@ struct iowarrior { | |||
100 | /*--------------*/ | 100 | /*--------------*/ |
101 | /* globals */ | 101 | /* globals */ |
102 | /*--------------*/ | 102 | /*--------------*/ |
103 | /* prevent races between open() and disconnect() */ | ||
104 | static DECLARE_MUTEX(disconnect_sem); | ||
105 | 103 | ||
106 | /* | 104 | /* |
107 | * USB spec identifies 5 second timeouts. | 105 | * USB spec identifies 5 second timeouts. |
@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
600 | 598 | ||
601 | subminor = iminor(inode); | 599 | subminor = iminor(inode); |
602 | 600 | ||
603 | /* prevent disconnects */ | ||
604 | down(&disconnect_sem); | ||
605 | |||
606 | interface = usb_find_interface(&iowarrior_driver, subminor); | 601 | interface = usb_find_interface(&iowarrior_driver, subminor); |
607 | if (!interface) { | 602 | if (!interface) { |
608 | err("%s - error, can't find device for minor %d", __FUNCTION__, | 603 | err("%s - error, can't find device for minor %d", __FUNCTION__, |
609 | subminor); | 604 | subminor); |
610 | retval = -ENODEV; | 605 | return -ENODEV; |
611 | goto out; | ||
612 | } | 606 | } |
613 | 607 | ||
614 | dev = usb_get_intfdata(interface); | 608 | dev = usb_get_intfdata(interface); |
615 | if (!dev) { | 609 | if (!dev) |
616 | retval = -ENODEV; | 610 | return -ENODEV; |
617 | goto out; | 611 | |
618 | } | 612 | mutex_lock(&dev->mutex); |
619 | 613 | ||
620 | /* Only one process can open each device, no sharing. */ | 614 | /* Only one process can open each device, no sharing. */ |
621 | if (dev->opened) { | 615 | if (dev->opened) { |
@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
636 | retval = 0; | 630 | retval = 0; |
637 | 631 | ||
638 | out: | 632 | out: |
639 | up(&disconnect_sem); | 633 | mutex_unlock(&dev->mutex); |
640 | return retval; | 634 | return retval; |
641 | } | 635 | } |
642 | 636 | ||
@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface) | |||
868 | struct iowarrior *dev; | 862 | struct iowarrior *dev; |
869 | int minor; | 863 | int minor; |
870 | 864 | ||
871 | /* prevent races with open() */ | ||
872 | down(&disconnect_sem); | ||
873 | |||
874 | dev = usb_get_intfdata(interface); | 865 | dev = usb_get_intfdata(interface); |
875 | usb_set_intfdata(interface, NULL); | 866 | usb_set_intfdata(interface, NULL); |
876 | 867 | ||
877 | mutex_lock(&dev->mutex); | ||
878 | |||
879 | minor = dev->minor; | 868 | minor = dev->minor; |
880 | 869 | ||
881 | /* give back our minor */ | 870 | /* give back our minor */ |
882 | usb_deregister_dev(interface, &iowarrior_class); | 871 | usb_deregister_dev(interface, &iowarrior_class); |
883 | 872 | ||
873 | mutex_lock(&dev->mutex); | ||
874 | |||
884 | /* prevent device read, write and ioctl */ | 875 | /* prevent device read, write and ioctl */ |
885 | dev->present = 0; | 876 | dev->present = 0; |
886 | 877 | ||
@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface) | |||
898 | /* no process is using the device, cleanup now */ | 889 | /* no process is using the device, cleanup now */ |
899 | iowarrior_delete(dev); | 890 | iowarrior_delete(dev); |
900 | } | 891 | } |
901 | up(&disconnect_sem); | ||
902 | 892 | ||
903 | dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", | 893 | dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", |
904 | minor - IOWARRIOR_MINOR_BASE); | 894 | minor - IOWARRIOR_MINOR_BASE); |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 7bad49404762..5e950b90c541 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
@@ -176,9 +176,6 @@ struct ld_usb { | |||
176 | int interrupt_out_busy; | 176 | int interrupt_out_busy; |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /* prevent races between open() and disconnect() */ | ||
180 | static DEFINE_MUTEX(disconnect_mutex); | ||
181 | |||
182 | static struct usb_driver ld_usb_driver; | 179 | static struct usb_driver ld_usb_driver; |
183 | 180 | ||
184 | /** | 181 | /** |
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file) | |||
298 | { | 295 | { |
299 | struct ld_usb *dev; | 296 | struct ld_usb *dev; |
300 | int subminor; | 297 | int subminor; |
301 | int retval = 0; | 298 | int retval; |
302 | struct usb_interface *interface; | 299 | struct usb_interface *interface; |
303 | 300 | ||
304 | nonseekable_open(inode, file); | 301 | nonseekable_open(inode, file); |
305 | subminor = iminor(inode); | 302 | subminor = iminor(inode); |
306 | 303 | ||
307 | mutex_lock(&disconnect_mutex); | ||
308 | |||
309 | interface = usb_find_interface(&ld_usb_driver, subminor); | 304 | interface = usb_find_interface(&ld_usb_driver, subminor); |
310 | 305 | ||
311 | if (!interface) { | 306 | if (!interface) { |
312 | err("%s - error, can't find device for minor %d\n", | 307 | err("%s - error, can't find device for minor %d\n", |
313 | __FUNCTION__, subminor); | 308 | __FUNCTION__, subminor); |
314 | retval = -ENODEV; | 309 | return -ENODEV; |
315 | goto unlock_disconnect_exit; | ||
316 | } | 310 | } |
317 | 311 | ||
318 | dev = usb_get_intfdata(interface); | 312 | dev = usb_get_intfdata(interface); |
319 | 313 | ||
320 | if (!dev) { | 314 | if (!dev) |
321 | retval = -ENODEV; | 315 | return -ENODEV; |
322 | goto unlock_disconnect_exit; | ||
323 | } | ||
324 | 316 | ||
325 | /* lock this device */ | 317 | /* lock this device */ |
326 | if (down_interruptible(&dev->sem)) { | 318 | if (down_interruptible(&dev->sem)) |
327 | retval = -ERESTARTSYS; | 319 | return -ERESTARTSYS; |
328 | goto unlock_disconnect_exit; | ||
329 | } | ||
330 | 320 | ||
331 | /* allow opening only once */ | 321 | /* allow opening only once */ |
332 | if (dev->open_count) { | 322 | if (dev->open_count) { |
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file) | |||
366 | unlock_exit: | 356 | unlock_exit: |
367 | up(&dev->sem); | 357 | up(&dev->sem); |
368 | 358 | ||
369 | unlock_disconnect_exit: | ||
370 | mutex_unlock(&disconnect_mutex); | ||
371 | |||
372 | return retval; | 359 | return retval; |
373 | } | 360 | } |
374 | 361 | ||
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf) | |||
766 | struct ld_usb *dev; | 753 | struct ld_usb *dev; |
767 | int minor; | 754 | int minor; |
768 | 755 | ||
769 | mutex_lock(&disconnect_mutex); | ||
770 | |||
771 | dev = usb_get_intfdata(intf); | 756 | dev = usb_get_intfdata(intf); |
772 | usb_set_intfdata(intf, NULL); | 757 | usb_set_intfdata(intf, NULL); |
773 | 758 | ||
774 | down(&dev->sem); | ||
775 | |||
776 | minor = intf->minor; | 759 | minor = intf->minor; |
777 | 760 | ||
778 | /* give back our minor */ | 761 | /* give back our minor */ |
779 | usb_deregister_dev(intf, &ld_usb_class); | 762 | usb_deregister_dev(intf, &ld_usb_class); |
780 | 763 | ||
764 | down(&dev->sem); | ||
765 | |||
781 | /* if the device is not opened, then we clean up right now */ | 766 | /* if the device is not opened, then we clean up right now */ |
782 | if (!dev->open_count) { | 767 | if (!dev->open_count) { |
783 | up(&dev->sem); | 768 | up(&dev->sem); |
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf) | |||
787 | up(&dev->sem); | 772 | up(&dev->sem); |
788 | } | 773 | } |
789 | 774 | ||
790 | mutex_unlock(&disconnect_mutex); | ||
791 | |||
792 | dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", | 775 | dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", |
793 | (minor - USB_LD_MINOR_BASE)); | 776 | (minor - USB_LD_MINOR_BASE)); |
794 | } | 777 | } |
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 1713e19a7899..2ed0daea894c 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
@@ -254,9 +254,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_devic | |||
254 | static void tower_disconnect (struct usb_interface *interface); | 254 | static void tower_disconnect (struct usb_interface *interface); |
255 | 255 | ||
256 | 256 | ||
257 | /* prevent races between open() and disconnect */ | ||
258 | static DEFINE_MUTEX (disconnect_mutex); | ||
259 | |||
260 | /* file operations needed when we register this driver */ | 257 | /* file operations needed when we register this driver */ |
261 | static const struct file_operations tower_fops = { | 258 | static const struct file_operations tower_fops = { |
262 | .owner = THIS_MODULE, | 259 | .owner = THIS_MODULE, |
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file) | |||
344 | nonseekable_open(inode, file); | 341 | nonseekable_open(inode, file); |
345 | subminor = iminor(inode); | 342 | subminor = iminor(inode); |
346 | 343 | ||
347 | mutex_lock (&disconnect_mutex); | ||
348 | |||
349 | interface = usb_find_interface (&tower_driver, subminor); | 344 | interface = usb_find_interface (&tower_driver, subminor); |
350 | 345 | ||
351 | if (!interface) { | 346 | if (!interface) { |
352 | err ("%s - error, can't find device for minor %d", | 347 | err ("%s - error, can't find device for minor %d", |
353 | __FUNCTION__, subminor); | 348 | __FUNCTION__, subminor); |
354 | retval = -ENODEV; | 349 | retval = -ENODEV; |
355 | goto unlock_disconnect_exit; | 350 | goto exit; |
356 | } | 351 | } |
357 | 352 | ||
358 | dev = usb_get_intfdata(interface); | 353 | dev = usb_get_intfdata(interface); |
359 | 354 | ||
360 | if (!dev) { | 355 | if (!dev) { |
361 | retval = -ENODEV; | 356 | retval = -ENODEV; |
362 | goto unlock_disconnect_exit; | 357 | goto exit; |
363 | } | 358 | } |
364 | 359 | ||
365 | /* lock this device */ | 360 | /* lock this device */ |
366 | if (down_interruptible (&dev->sem)) { | 361 | if (down_interruptible (&dev->sem)) { |
367 | retval = -ERESTARTSYS; | 362 | retval = -ERESTARTSYS; |
368 | goto unlock_disconnect_exit; | 363 | goto exit; |
369 | } | 364 | } |
370 | 365 | ||
371 | /* allow opening only once */ | 366 | /* allow opening only once */ |
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file) | |||
421 | unlock_exit: | 416 | unlock_exit: |
422 | up (&dev->sem); | 417 | up (&dev->sem); |
423 | 418 | ||
424 | unlock_disconnect_exit: | 419 | exit: |
425 | mutex_unlock (&disconnect_mutex); | ||
426 | |||
427 | dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); | 420 | dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); |
428 | 421 | ||
429 | return retval; | 422 | return retval; |
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface) | |||
993 | 986 | ||
994 | dbg(2, "%s: enter", __FUNCTION__); | 987 | dbg(2, "%s: enter", __FUNCTION__); |
995 | 988 | ||
996 | mutex_lock (&disconnect_mutex); | ||
997 | |||
998 | dev = usb_get_intfdata (interface); | 989 | dev = usb_get_intfdata (interface); |
999 | usb_set_intfdata (interface, NULL); | 990 | usb_set_intfdata (interface, NULL); |
1000 | 991 | ||
1001 | |||
1002 | down (&dev->sem); | ||
1003 | |||
1004 | minor = dev->minor; | 992 | minor = dev->minor; |
1005 | 993 | ||
1006 | /* give back our minor */ | 994 | /* give back our minor */ |
1007 | usb_deregister_dev (interface, &tower_class); | 995 | usb_deregister_dev (interface, &tower_class); |
1008 | 996 | ||
997 | down (&dev->sem); | ||
998 | |||
1009 | /* if the device is not opened, then we clean up right now */ | 999 | /* if the device is not opened, then we clean up right now */ |
1010 | if (!dev->open_count) { | 1000 | if (!dev->open_count) { |
1011 | up (&dev->sem); | 1001 | up (&dev->sem); |
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface) | |||
1015 | up (&dev->sem); | 1005 | up (&dev->sem); |
1016 | } | 1006 | } |
1017 | 1007 | ||
1018 | mutex_unlock (&disconnect_mutex); | ||
1019 | |||
1020 | info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); | 1008 | info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); |
1021 | 1009 | ||
1022 | dbg(2, "%s: leave", __FUNCTION__); | 1010 | dbg(2, "%s: leave", __FUNCTION__); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 6f8b134a79cb..9f37ba44c132 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES | |||
72 | 72 | ||
73 | static struct usb_driver sisusb_driver; | 73 | static struct usb_driver sisusb_driver; |
74 | 74 | ||
75 | DEFINE_MUTEX(disconnect_mutex); | ||
76 | |||
77 | static void | 75 | static void |
78 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) | 76 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) |
79 | { | 77 | { |
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2511 | struct usb_interface *interface; | 2509 | struct usb_interface *interface; |
2512 | int subminor = iminor(inode); | 2510 | int subminor = iminor(inode); |
2513 | 2511 | ||
2514 | mutex_lock(&disconnect_mutex); | ||
2515 | |||
2516 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { | 2512 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { |
2517 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", | 2513 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", |
2518 | subminor); | 2514 | subminor); |
2519 | mutex_unlock(&disconnect_mutex); | ||
2520 | return -ENODEV; | 2515 | return -ENODEV; |
2521 | } | 2516 | } |
2522 | 2517 | ||
2523 | if (!(sisusb = usb_get_intfdata(interface))) { | 2518 | if (!(sisusb = usb_get_intfdata(interface))) |
2524 | mutex_unlock(&disconnect_mutex); | ||
2525 | return -ENODEV; | 2519 | return -ENODEV; |
2526 | } | ||
2527 | 2520 | ||
2528 | mutex_lock(&sisusb->lock); | 2521 | mutex_lock(&sisusb->lock); |
2529 | 2522 | ||
2530 | if (!sisusb->present || !sisusb->ready) { | 2523 | if (!sisusb->present || !sisusb->ready) { |
2531 | mutex_unlock(&sisusb->lock); | 2524 | mutex_unlock(&sisusb->lock); |
2532 | mutex_unlock(&disconnect_mutex); | ||
2533 | return -ENODEV; | 2525 | return -ENODEV; |
2534 | } | 2526 | } |
2535 | 2527 | ||
2536 | if (sisusb->isopen) { | 2528 | if (sisusb->isopen) { |
2537 | mutex_unlock(&sisusb->lock); | 2529 | mutex_unlock(&sisusb->lock); |
2538 | mutex_unlock(&disconnect_mutex); | ||
2539 | return -EBUSY; | 2530 | return -EBUSY; |
2540 | } | 2531 | } |
2541 | 2532 | ||
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2543 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { | 2534 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { |
2544 | if (sisusb_init_gfxdevice(sisusb, 0)) { | 2535 | if (sisusb_init_gfxdevice(sisusb, 0)) { |
2545 | mutex_unlock(&sisusb->lock); | 2536 | mutex_unlock(&sisusb->lock); |
2546 | mutex_unlock(&disconnect_mutex); | ||
2547 | printk(KERN_ERR | 2537 | printk(KERN_ERR |
2548 | "sisusbvga[%d]: Failed to initialize " | 2538 | "sisusbvga[%d]: Failed to initialize " |
2549 | "device\n", | 2539 | "device\n", |
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2552 | } | 2542 | } |
2553 | } else { | 2543 | } else { |
2554 | mutex_unlock(&sisusb->lock); | 2544 | mutex_unlock(&sisusb->lock); |
2555 | mutex_unlock(&disconnect_mutex); | ||
2556 | printk(KERN_ERR | 2545 | printk(KERN_ERR |
2557 | "sisusbvga[%d]: Device not attached to " | 2546 | "sisusbvga[%d]: Device not attached to " |
2558 | "USB 2.0 hub\n", | 2547 | "USB 2.0 hub\n", |
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2570 | 2559 | ||
2571 | mutex_unlock(&sisusb->lock); | 2560 | mutex_unlock(&sisusb->lock); |
2572 | 2561 | ||
2573 | mutex_unlock(&disconnect_mutex); | ||
2574 | |||
2575 | return 0; | 2562 | return 0; |
2576 | } | 2563 | } |
2577 | 2564 | ||
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2601 | struct sisusb_usb_data *sisusb; | 2588 | struct sisusb_usb_data *sisusb; |
2602 | int myminor; | 2589 | int myminor; |
2603 | 2590 | ||
2604 | mutex_lock(&disconnect_mutex); | 2591 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2605 | |||
2606 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { | ||
2607 | mutex_unlock(&disconnect_mutex); | ||
2608 | return -ENODEV; | 2592 | return -ENODEV; |
2609 | } | ||
2610 | 2593 | ||
2611 | mutex_lock(&sisusb->lock); | 2594 | mutex_lock(&sisusb->lock); |
2612 | 2595 | ||
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2626 | /* decrement the usage count on our device */ | 2609 | /* decrement the usage count on our device */ |
2627 | kref_put(&sisusb->kref, sisusb_delete); | 2610 | kref_put(&sisusb->kref, sisusb_delete); |
2628 | 2611 | ||
2629 | mutex_unlock(&disconnect_mutex); | ||
2630 | |||
2631 | return 0; | 2612 | return 0; |
2632 | } | 2613 | } |
2633 | 2614 | ||
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3383 | sisusb_console_exit(sisusb); | 3364 | sisusb_console_exit(sisusb); |
3384 | #endif | 3365 | #endif |
3385 | 3366 | ||
3386 | /* The above code doesn't need the disconnect | 3367 | minor = sisusb->minor; |
3387 | * semaphore to be down; its meaning is to | 3368 | |
3388 | * protect all other routines from the disconnect | 3369 | usb_deregister_dev(intf, &usb_sisusb_class); |
3389 | * case, not the other way round. | ||
3390 | */ | ||
3391 | mutex_lock(&disconnect_mutex); | ||
3392 | 3370 | ||
3393 | mutex_lock(&sisusb->lock); | 3371 | mutex_lock(&sisusb->lock); |
3394 | 3372 | ||
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3396 | if (!sisusb_wait_all_out_complete(sisusb)) | 3374 | if (!sisusb_wait_all_out_complete(sisusb)) |
3397 | sisusb_kill_all_busy(sisusb); | 3375 | sisusb_kill_all_busy(sisusb); |
3398 | 3376 | ||
3399 | minor = sisusb->minor; | ||
3400 | |||
3401 | usb_set_intfdata(intf, NULL); | 3377 | usb_set_intfdata(intf, NULL); |
3402 | 3378 | ||
3403 | usb_deregister_dev(intf, &usb_sisusb_class); | ||
3404 | |||
3405 | #ifdef SISUSB_OLD_CONFIG_COMPAT | 3379 | #ifdef SISUSB_OLD_CONFIG_COMPAT |
3406 | if (sisusb->ioctl32registered) { | 3380 | if (sisusb->ioctl32registered) { |
3407 | int ret; | 3381 | int ret; |
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3426 | /* decrement our usage count */ | 3400 | /* decrement our usage count */ |
3427 | kref_put(&sisusb->kref, sisusb_delete); | 3401 | kref_put(&sisusb->kref, sisusb_delete); |
3428 | 3402 | ||
3429 | mutex_unlock(&disconnect_mutex); | ||
3430 | |||
3431 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); | 3403 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); |
3432 | } | 3404 | } |
3433 | 3405 | ||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 5947afb0017e..8d0edc867f33 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init) | |||
214 | * are set up/restored. | 214 | * are set up/restored. |
215 | */ | 215 | */ |
216 | 216 | ||
217 | mutex_lock(&disconnect_mutex); | 217 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) |
218 | |||
219 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | ||
220 | mutex_unlock(&disconnect_mutex); | ||
221 | return; | 218 | return; |
222 | } | ||
223 | 219 | ||
224 | mutex_lock(&sisusb->lock); | 220 | mutex_lock(&sisusb->lock); |
225 | 221 | ||
226 | if (!sisusb_sisusb_valid(sisusb)) { | 222 | if (!sisusb_sisusb_valid(sisusb)) { |
227 | mutex_unlock(&sisusb->lock); | 223 | mutex_unlock(&sisusb->lock); |
228 | mutex_unlock(&disconnect_mutex); | ||
229 | return; | 224 | return; |
230 | } | 225 | } |
231 | 226 | ||
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init) | |||
264 | 259 | ||
265 | mutex_unlock(&sisusb->lock); | 260 | mutex_unlock(&sisusb->lock); |
266 | 261 | ||
267 | mutex_unlock(&disconnect_mutex); | ||
268 | |||
269 | if (init) { | 262 | if (init) { |
270 | c->vc_cols = cols; | 263 | c->vc_cols = cols; |
271 | c->vc_rows = rows; | 264 | c->vc_rows = rows; |
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c) | |||
284 | * and others, ie not under our control. | 277 | * and others, ie not under our control. |
285 | */ | 278 | */ |
286 | 279 | ||
287 | mutex_lock(&disconnect_mutex); | 280 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) |
288 | |||
289 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | ||
290 | mutex_unlock(&disconnect_mutex); | ||
291 | return; | 281 | return; |
292 | } | ||
293 | 282 | ||
294 | mutex_lock(&sisusb->lock); | 283 | mutex_lock(&sisusb->lock); |
295 | 284 | ||
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c) | |||
314 | 303 | ||
315 | /* decrement the usage count on our sisusb */ | 304 | /* decrement the usage count on our sisusb */ |
316 | kref_put(&sisusb->kref, sisusb_delete); | 305 | kref_put(&sisusb->kref, sisusb_delete); |
317 | |||
318 | mutex_unlock(&disconnect_mutex); | ||
319 | } | 306 | } |
320 | 307 | ||
321 | /* interface routine */ | 308 | /* interface routine */ |
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1490 | { | 1477 | { |
1491 | int i, ret, minor = sisusb->minor; | 1478 | int i, ret, minor = sisusb->minor; |
1492 | 1479 | ||
1493 | mutex_lock(&disconnect_mutex); | ||
1494 | |||
1495 | mutex_lock(&sisusb->lock); | 1480 | mutex_lock(&sisusb->lock); |
1496 | 1481 | ||
1497 | /* Erm.. that should not happen */ | 1482 | /* Erm.. that should not happen */ |
1498 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { | 1483 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { |
1499 | mutex_unlock(&sisusb->lock); | 1484 | mutex_unlock(&sisusb->lock); |
1500 | mutex_unlock(&disconnect_mutex); | ||
1501 | return 1; | 1485 | return 1; |
1502 | } | 1486 | } |
1503 | 1487 | ||
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1508 | first > MAX_NR_CONSOLES || | 1492 | first > MAX_NR_CONSOLES || |
1509 | last > MAX_NR_CONSOLES) { | 1493 | last > MAX_NR_CONSOLES) { |
1510 | mutex_unlock(&sisusb->lock); | 1494 | mutex_unlock(&sisusb->lock); |
1511 | mutex_unlock(&disconnect_mutex); | ||
1512 | return 1; | 1495 | return 1; |
1513 | } | 1496 | } |
1514 | 1497 | ||
1515 | /* If gfxcore not initialized or no consoles given, quit graciously */ | 1498 | /* If gfxcore not initialized or no consoles given, quit graciously */ |
1516 | if (!sisusb->gfxinit || first < 1 || last < 1) { | 1499 | if (!sisusb->gfxinit || first < 1 || last < 1) { |
1517 | mutex_unlock(&sisusb->lock); | 1500 | mutex_unlock(&sisusb->lock); |
1518 | mutex_unlock(&disconnect_mutex); | ||
1519 | return 0; | 1501 | return 0; |
1520 | } | 1502 | } |
1521 | 1503 | ||
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1526 | /* Set up text mode (and upload default font) */ | 1508 | /* Set up text mode (and upload default font) */ |
1527 | if (sisusb_reset_text_mode(sisusb, 1)) { | 1509 | if (sisusb_reset_text_mode(sisusb, 1)) { |
1528 | mutex_unlock(&sisusb->lock); | 1510 | mutex_unlock(&sisusb->lock); |
1529 | mutex_unlock(&disconnect_mutex); | ||
1530 | printk(KERN_ERR | 1511 | printk(KERN_ERR |
1531 | "sisusbvga[%d]: Failed to set up text mode\n", | 1512 | "sisusbvga[%d]: Failed to set up text mode\n", |
1532 | minor); | 1513 | minor); |
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1550 | /* Allocate screen buffer */ | 1531 | /* Allocate screen buffer */ |
1551 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { | 1532 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { |
1552 | mutex_unlock(&sisusb->lock); | 1533 | mutex_unlock(&sisusb->lock); |
1553 | mutex_unlock(&disconnect_mutex); | ||
1554 | printk(KERN_ERR | 1534 | printk(KERN_ERR |
1555 | "sisusbvga[%d]: Failed to allocate screen buffer\n", | 1535 | "sisusbvga[%d]: Failed to allocate screen buffer\n", |
1556 | minor); | 1536 | minor); |
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1558 | } | 1538 | } |
1559 | 1539 | ||
1560 | mutex_unlock(&sisusb->lock); | 1540 | mutex_unlock(&sisusb->lock); |
1561 | mutex_unlock(&disconnect_mutex); | ||
1562 | 1541 | ||
1563 | /* Now grab the desired console(s) */ | 1542 | /* Now grab the desired console(s) */ |
1564 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); | 1543 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index f05f83268af4..864bc0e96591 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h | |||
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] = | |||
808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ | 808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ |
809 | }; | 809 | }; |
810 | 810 | ||
811 | extern struct mutex disconnect_mutex; | ||
812 | |||
813 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | 811 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); |
814 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); | 812 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); |
815 | 813 | ||
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 12bad8a205a7..504f7221b0d0 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -45,13 +45,13 @@ struct usb_lcd { | |||
45 | struct kref kref; | 45 | struct kref kref; |
46 | struct semaphore limit_sem; /* to stop writes at full throttle from | 46 | struct semaphore limit_sem; /* to stop writes at full throttle from |
47 | * using up all RAM */ | 47 | * using up all RAM */ |
48 | struct usb_anchor submitted; /* URBs to wait for before suspend */ | ||
48 | }; | 49 | }; |
49 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) | 50 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) |
50 | 51 | ||
51 | #define USB_LCD_CONCURRENT_WRITES 5 | 52 | #define USB_LCD_CONCURRENT_WRITES 5 |
52 | 53 | ||
53 | static struct usb_driver lcd_driver; | 54 | static struct usb_driver lcd_driver; |
54 | static DEFINE_MUTEX(usb_lcd_open_mutex); | ||
55 | 55 | ||
56 | 56 | ||
57 | static void lcd_delete(struct kref *kref) | 57 | static void lcd_delete(struct kref *kref) |
@@ -68,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
68 | { | 68 | { |
69 | struct usb_lcd *dev; | 69 | struct usb_lcd *dev; |
70 | struct usb_interface *interface; | 70 | struct usb_interface *interface; |
71 | int subminor; | 71 | int subminor, r; |
72 | int retval = 0; | ||
73 | 72 | ||
74 | subminor = iminor(inode); | 73 | subminor = iminor(inode); |
75 | 74 | ||
76 | mutex_lock(&usb_lcd_open_mutex); | ||
77 | interface = usb_find_interface(&lcd_driver, subminor); | 75 | interface = usb_find_interface(&lcd_driver, subminor); |
78 | if (!interface) { | 76 | if (!interface) { |
79 | err ("USBLCD: %s - error, can't find device for minor %d", | 77 | err ("USBLCD: %s - error, can't find device for minor %d", |
80 | __FUNCTION__, subminor); | 78 | __FUNCTION__, subminor); |
81 | retval = -ENODEV; | 79 | return -ENODEV; |
82 | goto exit; | ||
83 | } | 80 | } |
84 | 81 | ||
85 | dev = usb_get_intfdata(interface); | 82 | dev = usb_get_intfdata(interface); |
86 | if (!dev) { | 83 | if (!dev) |
87 | retval = -ENODEV; | 84 | return -ENODEV; |
88 | goto exit; | ||
89 | } | ||
90 | 85 | ||
91 | /* increment our usage count for the device */ | 86 | /* increment our usage count for the device */ |
92 | kref_get(&dev->kref); | 87 | kref_get(&dev->kref); |
93 | 88 | ||
89 | /* grab a power reference */ | ||
90 | r = usb_autopm_get_interface(interface); | ||
91 | if (r < 0) { | ||
92 | kref_put(&dev->kref, lcd_delete); | ||
93 | return r; | ||
94 | } | ||
95 | |||
94 | /* save our object in the file's private structure */ | 96 | /* save our object in the file's private structure */ |
95 | file->private_data = dev; | 97 | file->private_data = dev; |
96 | 98 | ||
97 | exit: | 99 | return 0; |
98 | mutex_unlock(&usb_lcd_open_mutex); | ||
99 | return retval; | ||
100 | } | 100 | } |
101 | 101 | ||
102 | static int lcd_release(struct inode *inode, struct file *file) | 102 | static int lcd_release(struct inode *inode, struct file *file) |
@@ -108,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file) | |||
108 | return -ENODEV; | 108 | return -ENODEV; |
109 | 109 | ||
110 | /* decrement the count on our device */ | 110 | /* decrement the count on our device */ |
111 | usb_autopm_put_interface(dev->interface); | ||
111 | kref_put(&dev->kref, lcd_delete); | 112 | kref_put(&dev->kref, lcd_delete); |
112 | return 0; | 113 | return 0; |
113 | } | 114 | } |
@@ -233,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
233 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), | 234 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), |
234 | buf, count, lcd_write_bulk_callback, dev); | 235 | buf, count, lcd_write_bulk_callback, dev); |
235 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 236 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
237 | |||
238 | usb_anchor_urb(urb, &dev->submitted); | ||
236 | 239 | ||
237 | /* send the data out the bulk port */ | 240 | /* send the data out the bulk port */ |
238 | retval = usb_submit_urb(urb, GFP_KERNEL); | 241 | retval = usb_submit_urb(urb, GFP_KERNEL); |
239 | if (retval) { | 242 | if (retval) { |
240 | err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval); | 243 | err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval); |
241 | goto error; | 244 | goto error_unanchor; |
242 | } | 245 | } |
243 | 246 | ||
244 | /* release our reference to this urb, the USB core will eventually free it entirely */ | 247 | /* release our reference to this urb, the USB core will eventually free it entirely */ |
@@ -246,7 +249,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
246 | 249 | ||
247 | exit: | 250 | exit: |
248 | return count; | 251 | return count; |
249 | 252 | error_unanchor: | |
253 | usb_unanchor_urb(urb); | ||
250 | error: | 254 | error: |
251 | usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); | 255 | usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); |
252 | usb_free_urb(urb); | 256 | usb_free_urb(urb); |
@@ -291,6 +295,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
291 | } | 295 | } |
292 | kref_init(&dev->kref); | 296 | kref_init(&dev->kref); |
293 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); | 297 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); |
298 | init_usb_anchor(&dev->submitted); | ||
294 | 299 | ||
295 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 300 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
296 | dev->interface = interface; | 301 | dev->interface = interface; |
@@ -358,22 +363,41 @@ error: | |||
358 | return retval; | 363 | return retval; |
359 | } | 364 | } |
360 | 365 | ||
366 | static void lcd_draw_down(struct usb_lcd *dev) | ||
367 | { | ||
368 | int time; | ||
369 | |||
370 | time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); | ||
371 | if (!time) | ||
372 | usb_kill_anchored_urbs(&dev->submitted); | ||
373 | } | ||
374 | |||
375 | static int lcd_suspend(struct usb_interface *intf, pm_message_t message) | ||
376 | { | ||
377 | struct usb_lcd *dev = usb_get_intfdata(intf); | ||
378 | |||
379 | if (!dev) | ||
380 | return 0; | ||
381 | lcd_draw_down(dev); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int lcd_resume (struct usb_interface *intf) | ||
386 | { | ||
387 | return 0; | ||
388 | } | ||
389 | |||
361 | static void lcd_disconnect(struct usb_interface *interface) | 390 | static void lcd_disconnect(struct usb_interface *interface) |
362 | { | 391 | { |
363 | struct usb_lcd *dev; | 392 | struct usb_lcd *dev; |
364 | int minor = interface->minor; | 393 | int minor = interface->minor; |
365 | 394 | ||
366 | /* prevent skel_open() from racing skel_disconnect() */ | ||
367 | mutex_lock(&usb_lcd_open_mutex); | ||
368 | |||
369 | dev = usb_get_intfdata(interface); | 395 | dev = usb_get_intfdata(interface); |
370 | usb_set_intfdata(interface, NULL); | 396 | usb_set_intfdata(interface, NULL); |
371 | 397 | ||
372 | /* give back our minor */ | 398 | /* give back our minor */ |
373 | usb_deregister_dev(interface, &lcd_class); | 399 | usb_deregister_dev(interface, &lcd_class); |
374 | 400 | ||
375 | mutex_unlock(&usb_lcd_open_mutex); | ||
376 | |||
377 | /* decrement our usage count */ | 401 | /* decrement our usage count */ |
378 | kref_put(&dev->kref, lcd_delete); | 402 | kref_put(&dev->kref, lcd_delete); |
379 | 403 | ||
@@ -384,7 +408,10 @@ static struct usb_driver lcd_driver = { | |||
384 | .name = "usblcd", | 408 | .name = "usblcd", |
385 | .probe = lcd_probe, | 409 | .probe = lcd_probe, |
386 | .disconnect = lcd_disconnect, | 410 | .disconnect = lcd_disconnect, |
411 | .suspend = lcd_suspend, | ||
412 | .resume = lcd_resume, | ||
387 | .id_table = id_table, | 413 | .id_table = id_table, |
414 | .supports_autosuspend = 1, | ||
388 | }; | 415 | }; |
389 | 416 | ||
390 | static int __init usb_lcd_init(void) | 417 | static int __init usb_lcd_init(void) |