diff options
Diffstat (limited to 'drivers/usb/misc/legousbtower.c')
| -rw-r--r-- | drivers/usb/misc/legousbtower.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 561970b889a5..aab320085ebf 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
| @@ -198,6 +198,7 @@ static struct usb_device_id tower_table [] = { | |||
| 198 | }; | 198 | }; |
| 199 | 199 | ||
| 200 | MODULE_DEVICE_TABLE (usb, tower_table); | 200 | MODULE_DEVICE_TABLE (usb, tower_table); |
| 201 | static DEFINE_MUTEX(open_disc_mutex); | ||
| 201 | 202 | ||
| 202 | #define LEGO_USB_TOWER_MINOR_BASE 160 | 203 | #define LEGO_USB_TOWER_MINOR_BASE 160 |
| 203 | 204 | ||
| @@ -350,25 +351,31 @@ static int tower_open (struct inode *inode, struct file *file) | |||
| 350 | goto exit; | 351 | goto exit; |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 354 | mutex_lock(&open_disc_mutex); | ||
| 353 | dev = usb_get_intfdata(interface); | 355 | dev = usb_get_intfdata(interface); |
| 354 | 356 | ||
| 355 | if (!dev) { | 357 | if (!dev) { |
| 358 | mutex_unlock(&open_disc_mutex); | ||
| 356 | retval = -ENODEV; | 359 | retval = -ENODEV; |
| 357 | goto exit; | 360 | goto exit; |
| 358 | } | 361 | } |
| 359 | 362 | ||
| 360 | /* lock this device */ | 363 | /* lock this device */ |
| 361 | if (down_interruptible (&dev->sem)) { | 364 | if (down_interruptible (&dev->sem)) { |
| 365 | mutex_unlock(&open_disc_mutex); | ||
| 362 | retval = -ERESTARTSYS; | 366 | retval = -ERESTARTSYS; |
| 363 | goto exit; | 367 | goto exit; |
| 364 | } | 368 | } |
| 365 | 369 | ||
| 370 | |||
| 366 | /* allow opening only once */ | 371 | /* allow opening only once */ |
| 367 | if (dev->open_count) { | 372 | if (dev->open_count) { |
| 373 | mutex_unlock(&open_disc_mutex); | ||
| 368 | retval = -EBUSY; | 374 | retval = -EBUSY; |
| 369 | goto unlock_exit; | 375 | goto unlock_exit; |
| 370 | } | 376 | } |
| 371 | dev->open_count = 1; | 377 | dev->open_count = 1; |
| 378 | mutex_unlock(&open_disc_mutex); | ||
| 372 | 379 | ||
| 373 | /* reset the tower */ | 380 | /* reset the tower */ |
| 374 | result = usb_control_msg (dev->udev, | 381 | result = usb_control_msg (dev->udev, |
| @@ -437,9 +444,10 @@ static int tower_release (struct inode *inode, struct file *file) | |||
| 437 | if (dev == NULL) { | 444 | if (dev == NULL) { |
| 438 | dbg(1, "%s: object is NULL", __FUNCTION__); | 445 | dbg(1, "%s: object is NULL", __FUNCTION__); |
| 439 | retval = -ENODEV; | 446 | retval = -ENODEV; |
| 440 | goto exit; | 447 | goto exit_nolock; |
| 441 | } | 448 | } |
| 442 | 449 | ||
| 450 | mutex_lock(&open_disc_mutex); | ||
| 443 | if (down_interruptible (&dev->sem)) { | 451 | if (down_interruptible (&dev->sem)) { |
| 444 | retval = -ERESTARTSYS; | 452 | retval = -ERESTARTSYS; |
| 445 | goto exit; | 453 | goto exit; |
| @@ -468,6 +476,8 @@ unlock_exit: | |||
| 468 | up (&dev->sem); | 476 | up (&dev->sem); |
| 469 | 477 | ||
| 470 | exit: | 478 | exit: |
| 479 | mutex_unlock(&open_disc_mutex); | ||
| 480 | exit_nolock: | ||
| 471 | dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); | 481 | dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); |
| 472 | return retval; | 482 | return retval; |
| 473 | } | 483 | } |
| @@ -989,6 +999,7 @@ static void tower_disconnect (struct usb_interface *interface) | |||
| 989 | dbg(2, "%s: enter", __FUNCTION__); | 999 | dbg(2, "%s: enter", __FUNCTION__); |
| 990 | 1000 | ||
| 991 | dev = usb_get_intfdata (interface); | 1001 | dev = usb_get_intfdata (interface); |
| 1002 | mutex_lock(&open_disc_mutex); | ||
| 992 | usb_set_intfdata (interface, NULL); | 1003 | usb_set_intfdata (interface, NULL); |
| 993 | 1004 | ||
| 994 | minor = dev->minor; | 1005 | minor = dev->minor; |
| @@ -997,6 +1008,7 @@ static void tower_disconnect (struct usb_interface *interface) | |||
| 997 | usb_deregister_dev (interface, &tower_class); | 1008 | usb_deregister_dev (interface, &tower_class); |
| 998 | 1009 | ||
| 999 | down (&dev->sem); | 1010 | down (&dev->sem); |
| 1011 | mutex_unlock(&open_disc_mutex); | ||
| 1000 | 1012 | ||
| 1001 | /* if the device is not opened, then we clean up right now */ | 1013 | /* if the device is not opened, then we clean up right now */ |
| 1002 | if (!dev->open_count) { | 1014 | if (!dev->open_count) { |
