diff options
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/adutux.c | 86 | ||||
-rw-r--r-- | drivers/usb/misc/appledisplay.c | 9 | ||||
-rw-r--r-- | drivers/usb/misc/auerswald.c | 35 | ||||
-rw-r--r-- | drivers/usb/misc/berry_charge.c | 35 | ||||
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 21 | ||||
-rw-r--r-- | drivers/usb/misc/idmouse.c | 54 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 54 | ||||
-rw-r--r-- | drivers/usb/misc/ldusb.c | 53 | ||||
-rw-r--r-- | drivers/usb/misc/legousbtower.c | 52 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetkit.c | 13 | ||||
-rw-r--r-- | drivers/usb/misc/phidgetmotorcontrol.c | 13 | ||||
-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 | 100 | ||||
-rw-r--r-- | drivers/usb/misc/usbtest.c | 4 | ||||
-rw-r--r-- | drivers/usb/misc/uss720.c | 7 |
17 files changed, 289 insertions, 312 deletions
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 77145f9db04..e9fdbc8997b 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/usb.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #ifdef CONFIG_USB_DEBUG @@ -80,7 +81,7 @@ MODULE_DEVICE_TABLE(usb, device_table); /* Structure to hold all of our device specific stuff */ struct adu_device { - struct semaphore sem; /* locks this structure */ + struct mutex mtx; /* locks this structure */ struct usb_device* udev; /* save off the usb device pointer */ struct usb_interface* interface; unsigned char minor; /* the starting minor number for this device */ @@ -108,8 +109,6 @@ struct adu_device { struct urb* interrupt_out_urb; }; -/* prevent races between open() and disconnect */ -static DEFINE_MUTEX(disconnect_mutex); static struct usb_driver adu_driver; static void adu_debug_data(int level, const char *function, int size, @@ -180,17 +179,18 @@ static void adu_delete(struct adu_device *dev) static void adu_interrupt_in_callback(struct urb *urb) { struct adu_device *dev = urb->context; + int status = urb->status; - dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); + dbg(4," %s : enter, status %d", __FUNCTION__, status); adu_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); spin_lock(&dev->buflock); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { + if (status != 0) { + if ((status != -ENOENT) && (status != -ECONNRESET)) { dbg(1," %s : nonzero status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } goto exit; } @@ -218,21 +218,22 @@ exit: wake_up_interruptible(&dev->read_wait); adu_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); } static void adu_interrupt_out_callback(struct urb *urb) { struct adu_device *dev = urb->context; + int status = urb->status; - dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); + dbg(4," %s : enter, status %d", __FUNCTION__, status); adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && - (urb->status != -ECONNRESET)) { + if (status != 0) { + if ((status != -ENOENT) && + (status != -ECONNRESET)) { dbg(1, " %s :nonzero status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } goto exit; } @@ -242,7 +243,7 @@ exit: adu_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); } static int adu_open(struct inode *inode, struct file *file) @@ -256,8 +257,6 @@ static int adu_open(struct inode *inode, struct file *file) subminor = iminor(inode); - mutex_lock(&disconnect_mutex); - interface = usb_find_interface(&adu_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d", @@ -273,8 +272,8 @@ static int adu_open(struct inode *inode, struct file *file) } /* lock this device */ - if ((retval = down_interruptible(&dev->sem))) { - dbg(2, "%s : sem down failed", __FUNCTION__); + if ((retval = mutex_lock_interruptible(&dev->mtx))) { + dbg(2, "%s : mutex lock failed", __FUNCTION__); goto exit_no_device; } @@ -303,10 +302,9 @@ static int adu_open(struct inode *inode, struct file *file) if (retval) --dev->open_count; } - up(&dev->sem); + mutex_unlock(&dev->mtx); exit_no_device: - mutex_unlock(&disconnect_mutex); dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); return retval; @@ -318,12 +316,6 @@ static int adu_release_internal(struct adu_device *dev) dbg(2," %s : enter", __FUNCTION__); - if (dev->udev == NULL) { - /* the device was unplugged before the file was released */ - adu_delete(dev); - goto exit; - } - /* decrement our usage count for the device */ --dev->open_count; dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); @@ -332,7 +324,6 @@ static int adu_release_internal(struct adu_device *dev) dev->open_count = 0; } -exit: dbg(2," %s : leave", __FUNCTION__); return retval; } @@ -359,7 +350,7 @@ static int adu_release(struct inode *inode, struct file *file) } /* lock our device */ - down(&dev->sem); /* not interruptible */ + mutex_lock(&dev->mtx); /* not interruptible */ if (dev->open_count <= 0) { dbg(1," %s : device not opened", __FUNCTION__); @@ -367,12 +358,19 @@ static int adu_release(struct inode *inode, struct file *file) goto exit; } - /* do the work */ - retval = adu_release_internal(dev); + if (dev->udev == NULL) { + /* the device was unplugged before the file was released */ + mutex_unlock(&dev->mtx); + adu_delete(dev); + dev = NULL; + } else { + /* do the work */ + retval = adu_release_internal(dev); + } exit: if (dev) - up(&dev->sem); + mutex_unlock(&dev->mtx); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } @@ -395,7 +393,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, dev = file->private_data; dbg(2," %s : dev=%p", __FUNCTION__, dev); /* lock this object */ - if (down_interruptible(&dev->sem)) + if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ @@ -527,7 +525,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, exit: /* unlock the device */ - up(&dev->sem); + mutex_unlock(&dev->mtx); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; @@ -548,7 +546,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, dev = file->private_data; /* lock this object */ - retval = down_interruptible(&dev->sem); + retval = mutex_lock_interruptible(&dev->mtx); if (retval) goto exit_nolock; @@ -576,9 +574,9 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, retval = -EINTR; goto exit; } - up(&dev->sem); + mutex_unlock(&dev->mtx); timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); - retval = down_interruptible(&dev->sem); + retval = mutex_lock_interruptible(&dev->mtx); if (retval) { retval = bytes_written ? bytes_written : retval; goto exit_nolock; @@ -643,7 +641,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: /* unlock the device */ - up(&dev->sem); + mutex_unlock(&dev->mtx); exit_nolock: dbg(2," %s : leave, return value %d", __FUNCTION__, retval); @@ -703,7 +701,7 @@ static int adu_probe(struct usb_interface *interface, goto exit; } - init_MUTEX(&dev->sem); + mutex_init(&dev->mtx); spin_lock_init(&dev->buflock); dev->udev = udev; init_waitqueue_head(&dev->read_wait); @@ -831,31 +829,27 @@ static void adu_disconnect(struct usb_interface *interface) dbg(2," %s : enter", __FUNCTION__); - mutex_lock(&disconnect_mutex); /* not interruptible */ - dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); - down(&dev->sem); /* not interruptible */ - minor = dev->minor; /* give back our minor */ usb_deregister_dev(interface, &adu_class); dev->minor = 0; + mutex_lock(&dev->mtx); /* not interruptible */ + /* if the device is not opened, then we clean up right now */ dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); if (!dev->open_count) { - up(&dev->sem); + mutex_unlock(&dev->mtx); adu_delete(dev); } else { dev->udev = NULL; - up(&dev->sem); + mutex_unlock(&dev->mtx); } - mutex_unlock(&disconnect_mutex); - dev_info(&interface->dev, "ADU device adutux%d now disconnected", (minor - ADU_MINOR_BASE)); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index cf70c16f0e3..b09c83568c1 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -88,9 +88,10 @@ static void appledisplay_complete(struct urb *urb) { struct appledisplay *pdata = urb->context; unsigned long flags; + int status = urb->status; int retval; - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -102,12 +103,12 @@ static void appledisplay_complete(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + dbg("%s - urb shuttingdown with status: %d", + __FUNCTION__, status); return; default: dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); goto exit; } diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index cac1500cba6..df7e1ecc810 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -630,7 +630,7 @@ static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int time } else status = urb->status; - if (actual_length) + if (status >= 0) *actual_length = urb->actual_length; return status; @@ -664,7 +664,7 @@ static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsi int ret; struct usb_ctrlrequest *dr; struct urb *urb; - int length; + int uninitialized_var(length); dbg ("auerchain_control_msg"); dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); @@ -862,14 +862,16 @@ static void auerswald_ctrlread_wretcomplete (struct urb * urb) pauerbuf_t bp = (pauerbuf_t) urb->context; pauerswald_t cp; int ret; + int status = urb->status; + dbg ("auerswald_ctrlread_wretcomplete called"); - dbg ("complete with status: %d", urb->status); + dbg ("complete with status: %d", status); cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); /* check if it is possible to advance */ - if (!auerswald_status_retry (urb->status) || !cp->usbdev) { + if (!auerswald_status_retry(status) || !cp->usbdev) { /* reuse the buffer */ - err ("control dummy: transmission error %d, can not retry", urb->status); + err ("control dummy: transmission error %d, can not retry", status); auerbuf_releasebuf (bp); /* Wake up all processes waiting for a buffer */ wake_up (&cp->bufferwait); @@ -902,21 +904,23 @@ static void auerswald_ctrlread_complete (struct urb * urb) pauerswald_t cp; pauerscon_t scp; pauerbuf_t bp = (pauerbuf_t) urb->context; + int status = urb->status; int ret; + dbg ("auerswald_ctrlread_complete called"); cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); /* check if there is valid data in this urb */ - if (urb->status) { - dbg ("complete with non-zero status: %d", urb->status); + if (status) { + dbg ("complete with non-zero status: %d", status); /* should we do a retry? */ - if (!auerswald_status_retry (urb->status) + if (!auerswald_status_retry(status) || !cp->usbdev || (cp->version < AUV_RETRY) || (bp->retries >= AU_RETRIES)) { /* reuse the buffer */ - err ("control read: transmission error %d, can not retry", urb->status); + err ("control read: transmission error %d, can not retry", status); auerbuf_releasebuf (bp); /* Wake up all processes waiting for a buffer */ wake_up (&cp->bufferwait); @@ -974,12 +978,13 @@ static void auerswald_int_complete (struct urb * urb) unsigned int channelid; unsigned int bytecount; int ret; + int status = urb->status; pauerbuf_t bp = NULL; pauerswald_t cp = (pauerswald_t) urb->context; dbg ("%s called", __FUNCTION__); - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -987,10 +992,10 @@ static void auerswald_int_complete (struct urb * urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); return; default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, status); goto exit; } @@ -2034,12 +2039,12 @@ static void auerswald_disconnect (struct usb_interface *intf) if (!cp) return; - down (&cp->mutex); - info ("device /dev/%s now disconnecting", cp->name); - /* give back our USB minor number */ usb_deregister_dev(intf, &auerswald_class); + down (&cp->mutex); + info ("device /dev/%s now disconnecting", cp->name); + /* Stop the interrupt endpoint */ auerswald_int_release (cp); diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index b15f2fd8dab..92c1d2768df 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c @@ -26,8 +26,11 @@ #define RIM_VENDOR 0x0fca #define BLACKBERRY 0x0001 +#define BLACKBERRY_PEARL_DUAL 0x0004 +#define BLACKBERRY_PEARL 0x0006 static int debug; +static int pearl_dual_mode = 1; #ifdef dbg #undef dbg @@ -38,6 +41,8 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, + { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) }, + { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) }, { }, /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev) return retval; } +static int magic_dual_mode(struct usb_device *udev) +{ + char *dummy_buffer = kzalloc(2, GFP_KERNEL); + int retval; + + if (!dummy_buffer) + return -ENOMEM; + + /* send magic command so that the Blackberry Pearl device exposes + * two interfaces: both the USB mass-storage one and one which can + * be used for database access. */ + dbg(&udev->dev, "Sending magic pearl command\n"); + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100); + dbg(&udev->dev, "Magic pearl command returned %d\n", retval); + + dbg(&udev->dev, "Calling set_configuration\n"); + retval = usb_driver_set_configuration(udev, 1); + if (retval) + dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); + + return retval; +} + static int berry_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf, /* turn the power on */ magic_charge(udev); + if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) && + (pearl_dual_mode)) + magic_dual_mode(udev); + /* we don't really want to bind to the device, userspace programs can * handle the syncing just fine, so get outta here. */ return -ENODEV; @@ -138,3 +171,5 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); +module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode"); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index e0f122e131d..538b535e955 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -44,6 +44,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/kref.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/usb.h> #include <linux/workqueue.h> @@ -64,7 +65,7 @@ static struct workqueue_struct *respond_queue; * ftdi_module_lock exists to protect access to global variables * */ -static struct semaphore ftdi_module_lock; +static struct mutex ftdi_module_lock; static int ftdi_instances = 0; static struct list_head ftdi_static_list; /* @@ -199,10 +200,10 @@ static void ftdi_elan_delete(struct kref *kref) dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi); usb_put_dev(ftdi->udev); ftdi->disconnected += 1; - down(&ftdi_module_lock); + mutex_lock(&ftdi_module_lock); list_del_init(&ftdi->ftdi_list); ftdi_instances -= 1; - up(&ftdi_module_lock); + mutex_unlock(&ftdi_module_lock); kfree(ftdi->bulk_in_buffer); ftdi->bulk_in_buffer = NULL; } @@ -746,10 +747,12 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, static void ftdi_elan_write_bulk_callback(struct urb *urb) { struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context; - if (urb->status && !(urb->status == -ENOENT || urb->status == - -ECONNRESET || urb->status == -ESHUTDOWN)) { + int status = urb->status; + + if (status && !(status == -ENOENT || status == -ECONNRESET || + status == -ESHUTDOWN)) { dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %" - "d\n", urb, urb->status); + "d\n", urb, status); } usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); @@ -2780,10 +2783,10 @@ static int ftdi_elan_probe(struct usb_interface *interface, return -ENOMEM; } memset(ftdi, 0x00, sizeof(struct usb_ftdi)); - down(&ftdi_module_lock); + mutex_lock(&ftdi_module_lock); list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); ftdi->sequence_num = ++ftdi_instances; - up(&ftdi_module_lock); + mutex_unlock(&ftdi_module_lock); ftdi_elan_init_kref(ftdi); init_MUTEX(&ftdi->sw_lock); ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); @@ -2909,7 +2912,7 @@ static int __init ftdi_elan_init(void) int result; printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, __TIME__, __DATE__); - init_MUTEX(&ftdi_module_lock); + mutex_init(&ftdi_module_lock); INIT_LIST_HEAD(&ftdi_static_list); status_queue = create_singlethread_workqueue("ftdi-status-control"); if (!status_queue) diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 8d0e360636e..e6fd024024f 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = { .id_table = idmouse_table, }; -/* prevent races between open() and disconnect() */ -static DEFINE_MUTEX(disconnect_mutex); - static int idmouse_create_image(struct usb_idmouse *dev) { int bytes_read; @@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file) struct usb_interface *interface; int result; - /* prevent disconnects */ - mutex_lock(&disconnect_mutex); - /* get the interface from minor number and driver information */ interface = usb_find_interface (&idmouse_driver, iminor (inode)); - if (!interface) { - mutex_unlock(&disconnect_mutex); + if (!interface) return -ENODEV; - } + /* get the device information block from the interface */ dev = usb_get_intfdata(interface); - if (!dev) { - mutex_unlock(&disconnect_mutex); + if (!dev) return -ENODEV; - } /* lock this device */ down(&dev->sem); @@ -255,9 +246,6 @@ error: /* unlock this device */ up(&dev->sem); - - /* unlock the disconnect semaphore */ - mutex_unlock(&disconnect_mutex); return result; } @@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file) { struct usb_idmouse *dev; - /* prevent a race condition with open() */ - mutex_lock(&disconnect_mutex); - dev = file->private_data; - if (dev == NULL) { - mutex_unlock(&disconnect_mutex); + if (dev == NULL) return -ENODEV; - } /* lock our device */ down(&dev->sem); @@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file) /* are we really open? */ if (dev->open <= 0) { up(&dev->sem); - mutex_unlock(&disconnect_mutex); return -ENODEV; } @@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file) /* the device was unplugged before the file was released */ up(&dev->sem); idmouse_delete(dev); - mutex_unlock(&disconnect_mutex); - return 0; + } else { + up(&dev->sem); } - - up(&dev->sem); - mutex_unlock(&disconnect_mutex); return 0; } @@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface) { struct usb_idmouse *dev; - /* prevent races with open() */ - mutex_lock(&disconnect_mutex); - /* get device structure */ dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); - /* lock it */ - down(&dev->sem); - /* give back our minor */ usb_deregister_dev(interface, &idmouse_class); + /* lock it */ + down(&dev->sem); + /* prevent device read, write and ioctl */ dev->present = 0; - /* unlock */ - up(&dev->sem); - /* if the device is opened, idmouse_release will clean this up */ - if (!dev->open) + if (!dev->open) { + up(&dev->sem); idmouse_delete(dev); - - mutex_unlock(&disconnect_mutex); + } else { + /* unlock */ + up(&dev->sem); + } info("%s disconnected", DRIVER_DESC); } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index fc51207b71b..46d9f27ec17 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -100,8 +100,6 @@ struct iowarrior { /*--------------*/ /* globals */ /*--------------*/ -/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX(disconnect_sem); /* * USB spec identifies 5 second timeouts. @@ -160,9 +158,10 @@ static void iowarrior_callback(struct urb *urb) int read_idx; int aux_idx; int offset; - int status; + int status = urb->status; + int retval; - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -215,10 +214,10 @@ static void iowarrior_callback(struct urb *urb) wake_up_interruptible(&dev->read_wait); exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); + __FUNCTION__, retval); } @@ -228,13 +227,15 @@ exit: static void iowarrior_write_callback(struct urb *urb) { struct iowarrior *dev; + int status = urb->status; + dev = (struct iowarrior *)urb->context; /* 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("%s - nonzero write bulk status received: %d", - __func__, urb->status); + __func__, status); } /* free up our allocated buffer */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, @@ -495,8 +496,8 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file, /* verify that the device wasn't unplugged */ if (!dev->present) { - mutex_unlock(&dev->mutex); - return -ENODEV; + retval = -ENODEV; + goto error_out; } dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd, @@ -579,9 +580,10 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file, retval = -ENOTTY; break; } - +error_out: /* unlock the device */ mutex_unlock(&dev->mutex); + kfree(buffer); return retval; } @@ -599,22 +601,18 @@ static int iowarrior_open(struct inode *inode, struct file *file) subminor = iminor(inode); - /* prevent disconnects */ - down(&disconnect_sem); - interface = usb_find_interface(&iowarrior_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d", __FUNCTION__, subminor); - retval = -ENODEV; - goto out; + return -ENODEV; } dev = usb_get_intfdata(interface); - if (!dev) { - retval = -ENODEV; - goto out; - } + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); /* Only one process can open each device, no sharing. */ if (dev->opened) { @@ -635,7 +633,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) retval = 0; out: - up(&disconnect_sem); + mutex_unlock(&dev->mutex); return retval; } @@ -867,19 +865,16 @@ static void iowarrior_disconnect(struct usb_interface *interface) struct iowarrior *dev; int minor; - /* prevent races with open() */ - down(&disconnect_sem); - dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); - mutex_lock(&dev->mutex); - minor = dev->minor; /* give back our minor */ usb_deregister_dev(interface, &iowarrior_class); + mutex_lock(&dev->mutex); + /* prevent device read, write and ioctl */ dev->present = 0; @@ -897,7 +892,6 @@ static void iowarrior_disconnect(struct usb_interface *interface) /* no process is using the device, cleanup now */ iowarrior_delete(dev); } - up(&disconnect_sem); dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", minor - IOWARRIOR_MINOR_BASE); diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 7bad4940476..8208496dfc6 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -176,9 +176,6 @@ struct ld_usb { int interrupt_out_busy; }; -/* prevent races between open() and disconnect() */ -static DEFINE_MUTEX(disconnect_mutex); - static struct usb_driver ld_usb_driver; /** @@ -222,16 +219,17 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) struct ld_usb *dev = urb->context; size_t *actual_buffer; unsigned int next_ring_head; + int status = urb->status; int retval; - 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_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __FUNCTION__, urb->status); + __FUNCTION__, status); spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } @@ -278,14 +276,15 @@ exit: static void ld_usb_interrupt_out_callback(struct urb *urb) { struct ld_usb *dev = urb->context; + int status = urb->status; /* 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_info(&dev->intf->dev, "%s - nonzero write interrupt status received: %d\n", - __FUNCTION__, urb->status); + __FUNCTION__, status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); @@ -298,35 +297,28 @@ static int ld_usb_open(struct inode *inode, struct file *file) { struct ld_usb *dev; int subminor; - int retval = 0; + int retval; struct usb_interface *interface; nonseekable_open(inode, file); subminor = iminor(inode); - mutex_lock(&disconnect_mutex); - interface = usb_find_interface(&ld_usb_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d\n", __FUNCTION__, subminor); - retval = -ENODEV; - goto unlock_disconnect_exit; + return -ENODEV; } dev = usb_get_intfdata(interface); - if (!dev) { - retval = -ENODEV; - goto unlock_disconnect_exit; - } + if (!dev) + return -ENODEV; /* lock this device */ - if (down_interruptible(&dev->sem)) { - retval = -ERESTARTSYS; - goto unlock_disconnect_exit; - } + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; /* allow opening only once */ if (dev->open_count) { @@ -366,9 +358,6 @@ static int ld_usb_open(struct inode *inode, struct file *file) unlock_exit: up(&dev->sem); -unlock_disconnect_exit: - mutex_unlock(&disconnect_mutex); - return retval; } @@ -766,18 +755,16 @@ static void ld_usb_disconnect(struct usb_interface *intf) struct ld_usb *dev; int minor; - mutex_lock(&disconnect_mutex); - dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); - down(&dev->sem); - minor = intf->minor; /* give back our minor */ usb_deregister_dev(intf, &ld_usb_class); + down(&dev->sem); + /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { up(&dev->sem); @@ -787,8 +774,6 @@ static void ld_usb_disconnect(struct usb_interface *intf) up(&dev->sem); } - mutex_unlock(&disconnect_mutex); - dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", (minor - USB_LD_MINOR_BASE)); } diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 1713e19a789..561970b889a 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 static void tower_disconnect (struct usb_interface *interface); -/* prevent races between open() and disconnect */ -static DEFINE_MUTEX (disconnect_mutex); - /* file operations needed when we register this driver */ static const struct file_operations tower_fops = { .owner = THIS_MODULE, @@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file) nonseekable_open(inode, file); subminor = iminor(inode); - mutex_lock (&disconnect_mutex); - interface = usb_find_interface (&tower_driver, subminor); if (!interface) { err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); retval = -ENODEV; - goto unlock_disconnect_exit; + goto exit; } dev = usb_get_intfdata(interface); if (!dev) { retval = -ENODEV; - goto unlock_disconnect_exit; + goto exit; } /* lock this device */ if (down_interruptible (&dev->sem)) { retval = -ERESTARTSYS; - goto unlock_disconnect_exit; + goto exit; } /* allow opening only once */ @@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file) unlock_exit: up (&dev->sem); -unlock_disconnect_exit: - mutex_unlock (&disconnect_mutex); - +exit: dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); return retval; @@ -749,19 +742,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 */ } } @@ -795,7 +789,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); } @@ -805,23 +799,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); } @@ -993,19 +988,16 @@ static void tower_disconnect (struct usb_interface *interface) dbg(2, "%s: enter", __FUNCTION__); - mutex_lock (&disconnect_mutex); - dev = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); - - down (&dev->sem); - minor = dev->minor; /* give back our minor */ usb_deregister_dev (interface, &tower_class); + down (&dev->sem); + /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { up (&dev->sem); @@ -1015,8 +1007,6 @@ static void tower_disconnect (struct usb_interface *interface) up (&dev->sem); } - mutex_unlock (&disconnect_mutex); - info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); dbg(2, "%s: leave", __FUNCTION__); diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 371bf2b1197..aa9bcceabe7 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -305,9 +305,10 @@ static void interfacekit_irq(struct urb *urb) struct interfacekit *kit = urb->context; unsigned char *buffer = kit->data; int i, level, sensor; - int status; + int retval; + int status = urb->status; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ @@ -377,11 +378,11 @@ static void interfacekit_irq(struct urb *urb) schedule_delayed_work(&kit->do_notify, 0); resubmit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("can't resubmit intr, %s-%s/interfacekit0, status %d", + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + err("can't resubmit intr, %s-%s/interfacekit0, retval %d", kit->udev->bus->bus_name, - kit->udev->devpath, status); + kit->udev->devpath, retval); } static void do_notify(struct work_struct *work) diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 5727e1ea2f9..df0ebcdb9d6 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -95,9 +95,10 @@ static void motorcontrol_irq(struct urb *urb) struct motorcontrol *mc = urb->context; unsigned char *buffer = mc->data; int i, level; - int status; + int retval; + int status = urb->status;; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ @@ -151,12 +152,12 @@ static void motorcontrol_irq(struct urb *urb) schedule_delayed_work(&mc->do_notify, 0); resubmit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) dev_err(&mc->intf->dev, - "can't resubmit intr, %s-%s/motorcontrol0, status %d", + "can't resubmit intr, %s-%s/motorcontrol0, retval %d", mc->udev->bus->bus_name, - mc->udev->devpath, status); + mc->udev->devpath, retval); } static void do_notify(struct work_struct *work) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 6f8b134a79c..9f37ba44c13 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 static struct usb_driver sisusb_driver; -DEFINE_MUTEX(disconnect_mutex); - static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) { @@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor = iminor(inode); - mutex_lock(&disconnect_mutex); - if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", subminor); - mutex_unlock(&disconnect_mutex); return -ENODEV; } - if (!(sisusb = usb_get_intfdata(interface))) { - mutex_unlock(&disconnect_mutex); + if (!(sisusb = usb_get_intfdata(interface))) return -ENODEV; - } mutex_lock(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return -ENODEV; } if (sisusb->isopen) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return -EBUSY; } @@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file) if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to initialize " "device\n", @@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file) } } else { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Device not attached to " "USB 2.0 hub\n", @@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file) mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); - return 0; } @@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file) struct sisusb_usb_data *sisusb; int myminor; - mutex_lock(&disconnect_mutex); - - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { - mutex_unlock(&disconnect_mutex); + if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - } mutex_lock(&sisusb->lock); @@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file) /* decrement the usage count on our device */ kref_put(&sisusb->kref, sisusb_delete); - mutex_unlock(&disconnect_mutex); - return 0; } @@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf) sisusb_console_exit(sisusb); #endif - /* The above code doesn't need the disconnect - * semaphore to be down; its meaning is to - * protect all other routines from the disconnect - * case, not the other way round. - */ - mutex_lock(&disconnect_mutex); + minor = sisusb->minor; + + usb_deregister_dev(intf, &usb_sisusb_class); mutex_lock(&sisusb->lock); @@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf) if (!sisusb_wait_all_out_complete(sisusb)) sisusb_kill_all_busy(sisusb); - minor = sisusb->minor; - usb_set_intfdata(intf, NULL); - usb_deregister_dev(intf, &usb_sisusb_class); - #ifdef SISUSB_OLD_CONFIG_COMPAT if (sisusb->ioctl32registered) { int ret; @@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf) /* decrement our usage count */ kref_put(&sisusb->kref, sisusb_delete); - mutex_unlock(&disconnect_mutex); - printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); } diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 5947afb0017..8d0edc867f3 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) * are set up/restored. */ - mutex_lock(&disconnect_mutex); - - if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - mutex_unlock(&disconnect_mutex); + if (!(sisusb = sisusb_get_sisusb(c->vc_num))) return; - } mutex_lock(&sisusb->lock); if (!sisusb_sisusb_valid(sisusb)) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return; } @@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init) mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); - if (init) { c->vc_cols = cols; c->vc_rows = rows; @@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c) * and others, ie not under our control. */ - mutex_lock(&disconnect_mutex); - - if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - mutex_unlock(&disconnect_mutex); + if (!(sisusb = sisusb_get_sisusb(c->vc_num))) return; - } mutex_lock(&sisusb->lock); @@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c) /* decrement the usage count on our sisusb */ kref_put(&sisusb->kref, sisusb_delete); - - mutex_unlock(&disconnect_mutex); } /* interface routine */ @@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) { int i, ret, minor = sisusb->minor; - mutex_lock(&disconnect_mutex); - mutex_lock(&sisusb->lock); /* Erm.. that should not happen */ if (sisusb->haveconsole || !sisusb->SiS_Pr) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return 1; } @@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) first > MAX_NR_CONSOLES || last > MAX_NR_CONSOLES) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return 1; } /* If gfxcore not initialized or no consoles given, quit graciously */ if (!sisusb->gfxinit || first < 1 || last < 1) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); return 0; } @@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) /* Set up text mode (and upload default font) */ if (sisusb_reset_text_mode(sisusb, 1)) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to set up text mode\n", minor); @@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) /* Allocate screen buffer */ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to allocate screen buffer\n", minor); @@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) } mutex_unlock(&sisusb->lock); - mutex_unlock(&disconnect_mutex); /* Now grab the desired console(s) */ 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 f05f83268af..864bc0e9659 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[] = { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ }; -extern struct mutex disconnect_mutex; - int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 887ef953f3d..71984203271 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -42,12 +42,16 @@ struct usb_lcd { size_t bulk_in_size; /* the size of the receive buffer */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ - struct kref kref; + struct kref kref; + struct semaphore limit_sem; /* to stop writes at full throttle from + * using up all RAM */ + struct usb_anchor submitted; /* URBs to wait for before suspend */ }; #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) +#define USB_LCD_CONCURRENT_WRITES 5 + static struct usb_driver lcd_driver; -static DEFINE_MUTEX(usb_lcd_open_mutex); static void lcd_delete(struct kref *kref) @@ -64,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file) { struct usb_lcd *dev; struct usb_interface *interface; - int subminor; - int retval = 0; + int subminor, r; subminor = iminor(inode); - mutex_lock(&usb_lcd_open_mutex); interface = usb_find_interface(&lcd_driver, subminor); if (!interface) { err ("USBLCD: %s - error, can't find device for minor %d", __FUNCTION__, subminor); - retval = -ENODEV; - goto exit; + return -ENODEV; } dev = usb_get_intfdata(interface); - if (!dev) { - retval = -ENODEV; - goto exit; - } + if (!dev) + return -ENODEV; /* increment our usage count for the device */ kref_get(&dev->kref); + /* grab a power reference */ + r = usb_autopm_get_interface(interface); + if (r < 0) { + kref_put(&dev->kref, lcd_delete); + return r; + } + /* save our object in the file's private structure */ file->private_data = dev; -exit: - mutex_unlock(&usb_lcd_open_mutex); - return retval; + return 0; } static int lcd_release(struct inode *inode, struct file *file) @@ -104,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file) return -ENODEV; /* decrement the count on our device */ + usb_autopm_put_interface(dev->interface); kref_put(&dev->kref, lcd_delete); return 0; } @@ -171,27 +176,29 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u static void lcd_write_bulk_callback(struct urb *urb) { struct usb_lcd *dev; + int status = urb->status; dev = (struct usb_lcd *)urb->context; /* 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("USBLCD: %s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } /* free up our allocated buffer */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); + up(&dev->limit_sem); } static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos) { struct usb_lcd *dev; - int retval = 0; + int retval = 0, r; struct urb *urb = NULL; char *buf = NULL; @@ -201,10 +208,16 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz if (count == 0) goto exit; + r = down_interruptible(&dev->limit_sem); + if (r < 0) + return -EINTR; + /* create a urb, and a buffer for it, and copy the data to the urb */ urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; + if (!urb) { + retval = -ENOMEM; + goto err_no_buf; + } buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { @@ -222,12 +235,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, count, lcd_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_anchor_urb(urb, &dev->submitted); /* send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval); - goto error; + goto error_unanchor; } /* release our reference to this urb, the USB core will eventually free it entirely */ @@ -235,10 +250,13 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz exit: return count; - +error_unanchor: + usb_unanchor_urb(urb); error: usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); +err_no_buf: + up(&dev->limit_sem); return retval; } @@ -277,6 +295,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id goto error; } kref_init(&dev->kref); + sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); + init_usb_anchor(&dev->submitted); dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; @@ -344,22 +364,41 @@ error: return retval; } +static void lcd_draw_down(struct usb_lcd *dev) +{ + int time; + + time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); + if (!time) + usb_kill_anchored_urbs(&dev->submitted); +} + +static int lcd_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_lcd *dev = usb_get_intfdata(intf); + + if (!dev) + return 0; + lcd_draw_down(dev); + return 0; +} + +static int lcd_resume (struct usb_interface *intf) +{ + return 0; +} + static void lcd_disconnect(struct usb_interface *interface) { struct usb_lcd *dev; int minor = interface->minor; - /* prevent skel_open() from racing skel_disconnect() */ - mutex_lock(&usb_lcd_open_mutex); - dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &lcd_class); - mutex_unlock(&usb_lcd_open_mutex); - /* decrement our usage count */ kref_put(&dev->kref, lcd_delete); @@ -370,7 +409,10 @@ static struct usb_driver lcd_driver = { .name = "usblcd", .probe = lcd_probe, .disconnect = lcd_disconnect, + .suspend = lcd_suspend, + .resume = lcd_resume, .id_table = id_table, + .supports_autosuspend = 1, }; static int __init usb_lcd_init(void) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index fb321864a92..e901d31e051 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -768,8 +768,8 @@ static void ctrl_complete (struct urb *urb) /* some faults are allowed, not required */ if (subcase->expected > 0 && ( - ((urb->status == -subcase->expected /* happened */ - || urb->status == 0)))) /* didn't */ + ((status == -subcase->expected /* happened */ + || status == 0)))) /* didn't */ status = 0; /* sometimes more than one fault is allowed */ else if (subcase->number == 12 && status == -EPIPE) diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 70250252ae2..2734fe2b9c4 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -111,12 +111,13 @@ static void async_complete(struct urb *urb) struct uss720_async_request *rq; struct parport *pp; struct parport_uss720_private *priv; + int status = urb->status; rq = urb->context; priv = rq->priv; pp = priv->pp; - if (urb->status) { - err("async_complete: urb error %d", urb->status); + if (status) { + err("async_complete: urb error %d", status); } else if (rq->dr.bRequest == 3) { memcpy(priv->reg, rq->reg, sizeof(priv->reg)); #if 0 @@ -336,7 +337,7 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id) memcpy(priv->reg, buffer, 4); /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ if (priv->reg[2] & priv->reg[1] & 0x10) - parport_generic_irq(0, pp, NULL); + parport_generic_irq(0, pp); return 1; } #endif |