diff options
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/adutux.c | 48 | ||||
-rw-r--r-- | drivers/usb/misc/cypress_cy7c63.c | 4 | ||||
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 19 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 20 | ||||
-rw-r--r-- | drivers/usb/misc/ldusb.c | 3 | ||||
-rw-r--r-- | drivers/usb/misc/usblcd.c | 7 |
6 files changed, 60 insertions, 41 deletions
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 75bfab95ab3c..77145f9db043 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -285,23 +285,24 @@ static int adu_open(struct inode *inode, struct file *file) /* save device in the file's private structure */ file->private_data = dev; - /* initialize in direction */ - dev->read_buffer_length = 0; - - /* fixup first read by having urb waiting for it */ - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, - usb_rcvintpipe(dev->udev, - dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), - adu_interrupt_in_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ - dev->read_urb_finished = 0; - usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); - /* we ignore failure */ - /* end of fixup for first read */ + if (dev->open_count == 1) { + /* initialize in direction */ + dev->read_buffer_length = 0; + /* fixup first read by having urb waiting for it */ + usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, + usb_rcvintpipe(dev->udev, + dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, dev, + dev->interrupt_in_endpoint->bInterval); + /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ + dev->read_urb_finished = 0; + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (retval) + --dev->open_count; + } up(&dev->sem); exit_no_device: @@ -469,7 +470,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); - retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); if (!retval) { spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submitted OK", __FUNCTION__); @@ -539,7 +540,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, size_t bytes_written = 0; size_t bytes_to_write; size_t buffer_size; - int retval = 0; + int retval; int timeout = 0; dbg(2," %s : enter, count = %Zd", __FUNCTION__, count); @@ -547,7 +548,9 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, dev = file->private_data; /* lock this object */ - down_interruptible(&dev->sem); + retval = down_interruptible(&dev->sem); + if (retval) + goto exit_nolock; /* verify that the device wasn't unplugged */ if (dev->udev == NULL || dev->minor == 0) { @@ -575,7 +578,11 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, } up(&dev->sem); timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); - down_interruptible(&dev->sem); + retval = down_interruptible(&dev->sem); + if (retval) { + retval = bytes_written ? bytes_written : retval; + goto exit_nolock; + } if (timeout > 0) { break; } @@ -637,6 +644,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: /* unlock the device */ up(&dev->sem); +exit_nolock: dbg(2," %s : leave, return value %d", __FUNCTION__, retval); diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index b63b5f34b2aa..d721380b242d 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -246,11 +246,13 @@ static void cypress_disconnect(struct usb_interface *interface) struct cypress *dev; dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); /* remove device attribute files */ device_remove_file(&interface->dev, &dev_attr_port0); device_remove_file(&interface->dev, &dev_attr_port1); + /* the intfdata can be set to NULL only after the + * device files have been removed */ + usb_set_intfdata(interface, NULL); usb_put_dev(dev->udev); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index bc3327e3dd78..e2172e5cf152 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2304,7 +2304,6 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi) #define OHCI_QUIRK_SUPERIO 0x02 #define OHCI_QUIRK_INITRESET 0x04 #define OHCI_BIG_ENDIAN 0x08 -#define OHCI_QUIRK_ZFMICRO 0x10 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ OHCI_INTR_WDH) @@ -2910,24 +2909,28 @@ static int __init ftdi_elan_init(void) INIT_LIST_HEAD(&ftdi_static_list); status_queue = create_singlethread_workqueue("ftdi-status-control"); if (!status_queue) - goto err1; + goto err_status_queue; command_queue = create_singlethread_workqueue("ftdi-command-engine"); if (!command_queue) - goto err2; + goto err_command_queue; respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); if (!respond_queue) - goto err3; + goto err_respond_queue; result = usb_register(&ftdi_elan_driver); - if (result) + if (result) { + destroy_workqueue(status_queue); + destroy_workqueue(command_queue); + destroy_workqueue(respond_queue); printk(KERN_ERR "usb_register failed. Error number %d\n", result); + } return result; - err3: + err_respond_queue: destroy_workqueue(command_queue); - err2: + err_command_queue: destroy_workqueue(status_queue); - err1: + err_status_queue: printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name); return -ENOMEM; } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index d69665c8de02..fc51207b71b8 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -118,7 +118,7 @@ static int usb_get_report(struct usb_device *dev, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, inter->desc.bInterfaceNumber, buf, size, - GET_TIMEOUT); + GET_TIMEOUT*HZ); } //#endif @@ -133,7 +133,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, intf->cur_altsetting->desc.bInterfaceNumber, buf, - size, 1); + size, HZ); } /*---------------------*/ @@ -417,14 +417,14 @@ static ssize_t iowarrior_write(struct file *file, if (!int_out_urb) { retval = -ENOMEM; dbg("%s Unable to allocate urb ", __func__); - goto error; + goto error_no_urb; } buf = usb_buffer_alloc(dev->udev, dev->report_size, GFP_KERNEL, &int_out_urb->transfer_dma); if (!buf) { retval = -ENOMEM; dbg("%s Unable to allocate buffer ", __func__); - goto error; + goto error_no_buffer; } usb_fill_int_urb(int_out_urb, dev->udev, usb_sndintpipe(dev->udev, @@ -459,7 +459,9 @@ static ssize_t iowarrior_write(struct file *file, error: usb_buffer_free(dev->udev, dev->report_size, buf, int_out_urb->transfer_dma); +error_no_buffer: usb_free_urb(int_out_urb); +error_no_urb: atomic_dec(&dev->write_busy); wake_up_interruptible(&dev->write_wait); exit: @@ -748,7 +750,6 @@ static int iowarrior_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *endpoint; int i; int retval = -ENOMEM; - int idele = 0; /* allocate memory for our device state and intialize it */ dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); @@ -824,11 +825,10 @@ static int iowarrior_probe(struct usb_interface *interface, /* Set the idle timeout to 0, if this is interface 0 */ if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) { - idele = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x0A, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("idele = %d", idele); + usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x0A, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + 0, NULL, 0, USB_CTRL_SET_TIMEOUT); } /* allow device read and ioctl */ dev->present = 1; diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 788a11e6772f..11555bde655b 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -62,6 +62,8 @@ #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 +#define USB_VENDOR_ID_MICROCHIP 0x04d8 +#define USB_DEVICE_ID_PICDEM 0x000c #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_LD_MINOR_BASE 0 @@ -89,6 +91,7 @@ static struct usb_device_id ld_usb_table [] = { { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, + { USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index ada2ebc464ae..887ef953f3d8 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -47,6 +47,7 @@ struct usb_lcd { #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) static struct usb_driver lcd_driver; +static DEFINE_MUTEX(usb_lcd_open_mutex); static void lcd_delete(struct kref *kref) @@ -68,6 +69,7 @@ static int lcd_open(struct inode *inode, struct file *file) 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", @@ -89,6 +91,7 @@ static int lcd_open(struct inode *inode, struct file *file) file->private_data = dev; exit: + mutex_unlock(&usb_lcd_open_mutex); return retval; } @@ -347,7 +350,7 @@ static void lcd_disconnect(struct usb_interface *interface) int minor = interface->minor; /* prevent skel_open() from racing skel_disconnect() */ - lock_kernel(); + mutex_lock(&usb_lcd_open_mutex); dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); @@ -355,7 +358,7 @@ static void lcd_disconnect(struct usb_interface *interface) /* give back our minor */ usb_deregister_dev(interface, &lcd_class); - unlock_kernel(); + mutex_unlock(&usb_lcd_open_mutex); /* decrement our usage count */ kref_put(&dev->kref, lcd_delete); |