X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fusb%2Fmisc%2Flegousbtower.c;h=aab320085ebf007af652cfa797d93c5ac09de1ce;hb=982286d1b8e438f595cdc9304cc4c185c7b90a39;hp=2ed0daea894c8c93e5c7313d8dd6558634171095;hpb=e030dbf91a87da7e8be3be3ca781558695bea683;p=linux-2.6-omap-h63xx.git diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 2ed0daea894..aab320085eb 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -198,6 +198,7 @@ static struct usb_device_id tower_table [] = { }; MODULE_DEVICE_TABLE (usb, tower_table); +static DEFINE_MUTEX(open_disc_mutex); #define LEGO_USB_TOWER_MINOR_BASE 160 @@ -350,25 +351,31 @@ static int tower_open (struct inode *inode, struct file *file) goto exit; } + mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); if (!dev) { + mutex_unlock(&open_disc_mutex); retval = -ENODEV; goto exit; } /* lock this device */ if (down_interruptible (&dev->sem)) { + mutex_unlock(&open_disc_mutex); retval = -ERESTARTSYS; goto exit; } + /* allow opening only once */ if (dev->open_count) { + mutex_unlock(&open_disc_mutex); retval = -EBUSY; goto unlock_exit; } dev->open_count = 1; + mutex_unlock(&open_disc_mutex); /* reset the tower */ result = usb_control_msg (dev->udev, @@ -437,9 +444,10 @@ static int tower_release (struct inode *inode, struct file *file) if (dev == NULL) { dbg(1, "%s: object is NULL", __FUNCTION__); retval = -ENODEV; - goto exit; + goto exit_nolock; } + mutex_lock(&open_disc_mutex); if (down_interruptible (&dev->sem)) { retval = -ERESTARTSYS; goto exit; @@ -468,6 +476,8 @@ unlock_exit: up (&dev->sem); exit: + mutex_unlock(&open_disc_mutex); +exit_nolock: dbg(2, "%s: leave, return value %d", __FUNCTION__, retval); return retval; } @@ -742,19 +752,20 @@ exit: static void tower_interrupt_in_callback (struct urb *urb) { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; + int status = urb->status; int retval; - dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: enter, status %d", __FUNCTION__, status); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status) { - if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { + if (status) { + if (status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN) { goto exit; } else { - dbg(1, "%s: nonzero status received: %d", __FUNCTION__, urb->status); + dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status); goto resubmit; /* maybe we can recover */ } } @@ -788,7 +799,7 @@ exit: wake_up_interruptible (&dev->read_wait); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: leave, status %d", __FUNCTION__, status); } @@ -798,23 +809,24 @@ exit: static void tower_interrupt_out_callback (struct urb *urb) { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; + int status = urb->status; - dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: enter, status %d", __FUNCTION__, status); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ - if (urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) { + if (status && !(status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN)) { dbg(1, "%s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: leave, status %d", __FUNCTION__, status); } @@ -987,6 +999,7 @@ static void tower_disconnect (struct usb_interface *interface) dbg(2, "%s: enter", __FUNCTION__); dev = usb_get_intfdata (interface); + mutex_lock(&open_disc_mutex); usb_set_intfdata (interface, NULL); minor = dev->minor; @@ -995,6 +1008,7 @@ static void tower_disconnect (struct usb_interface *interface) usb_deregister_dev (interface, &tower_class); down (&dev->sem); + mutex_unlock(&open_disc_mutex); /* if the device is not opened, then we clean up right now */ if (!dev->open_count) {