diff options
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/Kconfig | 32 | ||||
-rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/misc/adutux.c | 24 | ||||
-rw-r--r-- | drivers/usb/misc/appledisplay.c | 8 | ||||
-rw-r--r-- | drivers/usb/misc/chaoskey.c | 29 | ||||
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 6 | ||||
-rw-r--r-- | drivers/usb/misc/idmouse.c | 36 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 48 | ||||
-rw-r--r-- | drivers/usb/misc/ldusb.c | 60 | ||||
-rw-r--r-- | drivers/usb/misc/legousbtower.c | 356 | ||||
-rw-r--r-- | drivers/usb/misc/rio500.c | 554 | ||||
-rw-r--r-- | drivers/usb/misc/rio500_usb.h | 20 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usb251xb.c | 66 | ||||
-rw-r--r-- | drivers/usb/misc/usblcd.c | 60 | ||||
-rw-r--r-- | drivers/usb/misc/yurex.c | 18 |
16 files changed, 351 insertions, 969 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index bdae62b2ffe0..834b2494da73 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -47,16 +47,6 @@ config USB_SEVSEG To compile this driver as a module, choose M here: the module will be called usbsevseg. -config USB_RIO500 - tristate "USB Diamond Rio500 support" - help - Say Y here if you want to connect a USB Rio500 mp3 player to your - computer's USB port. Please read <file:Documentation/usb/rio.rst> - for more information. - - To compile this driver as a module, choose M here: the - module will be called rio500. - config USB_LEGOTOWER tristate "USB Lego Infrared Tower support" help @@ -191,8 +181,8 @@ config USB_TEST including sample test device firmware and "how to use it". config USB_EHSET_TEST_FIXTURE - tristate "USB EHSET Test Fixture driver" - help + tristate "USB EHSET Test Fixture driver" + help Say Y here if you want to support the special test fixture device used for the USB-IF Embedded Host High-Speed Electrical Test procedure. @@ -243,17 +233,17 @@ config USB_HUB_USB251XB Say Y or M here if you need to configure such a device via SMBus. config USB_HSIC_USB3503 - tristate "USB3503 HSIC to USB20 Driver" - depends on I2C - select REGMAP_I2C - help - This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver. + tristate "USB3503 HSIC to USB20 Driver" + depends on I2C + select REGMAP_I2C + help + This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver. config USB_HSIC_USB4604 - tristate "USB4604 HSIC to USB20 Driver" - depends on I2C - help - This option enables support for SMSC USB4604 HSIC to USB 2.0 Driver. + tristate "USB4604 HSIC to USB20 Driver" + depends on I2C + help + This option enables support for SMSC USB4604 HSIC to USB 2.0 Driver. config USB_LINK_LAYER_TEST tristate "USB Link Layer Test driver" diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 109f54f5b9aa..0d416eb624bb 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 344d523b0502..6f5edb9fc61e 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -75,6 +75,7 @@ struct adu_device { char serial_number[8]; int open_count; /* number of times this port has been opened */ + unsigned long disconnected:1; char *read_buffer_primary; int read_buffer_length; @@ -116,7 +117,7 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - if (dev->udev == NULL) + if (dev->disconnected) return; /* shutdown transfer */ @@ -148,6 +149,7 @@ static void adu_delete(struct adu_device *dev) kfree(dev->read_buffer_secondary); kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); + usb_put_dev(dev->udev); kfree(dev); } @@ -243,7 +245,7 @@ static int adu_open(struct inode *inode, struct file *file) } dev = usb_get_intfdata(interface); - if (!dev || !dev->udev) { + if (!dev) { retval = -ENODEV; goto exit_no_device; } @@ -326,7 +328,7 @@ static int adu_release(struct inode *inode, struct file *file) } adu_release_internal(dev); - if (dev->udev == NULL) { + if (dev->disconnected) { /* the device was unplugged before the file was released */ if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); @@ -354,7 +356,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, return -ERESTARTSYS; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto exit; @@ -518,7 +520,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit_nolock; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; pr_err("No device or device unplugged %d\n", retval); goto exit; @@ -663,7 +665,7 @@ static int adu_probe(struct usb_interface *interface, mutex_init(&dev->mtx); spin_lock_init(&dev->buflock); - dev->udev = udev; + dev->udev = usb_get_dev(udev); init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait); @@ -762,14 +764,18 @@ static void adu_disconnect(struct usb_interface *interface) dev = usb_get_intfdata(interface); - mutex_lock(&dev->mtx); /* not interruptible */ - dev->udev = NULL; /* poison */ usb_deregister_dev(interface, &adu_class); - mutex_unlock(&dev->mtx); + + usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); mutex_lock(&adutux_mutex); usb_set_intfdata(interface, NULL); + mutex_lock(&dev->mtx); /* not interruptible */ + dev->disconnected = 1; + mutex_unlock(&dev->mtx); + /* if the device is not opened, then we clean up right now */ if (!dev->open_count) adu_delete(dev); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index ac92725458b5..ba1eaabc7796 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -164,7 +164,12 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd) 0, pdata->msgdata, 2, ACD_USB_TIMEOUT); - brightness = pdata->msgdata[1]; + if (retval < 2) { + if (retval >= 0) + retval = -EMSGSIZE; + } else { + brightness = pdata->msgdata[1]; + } mutex_unlock(&pdata->sysfslock); if (retval < 0) @@ -299,6 +304,7 @@ error: if (pdata) { if (pdata->urb) { usb_kill_urb(pdata->urb); + cancel_delayed_work_sync(&pdata->work); if (pdata->urbdata) usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma); diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c index cf5828ce927a..87067c3d6109 100644 --- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -98,6 +98,7 @@ static void chaoskey_free(struct chaoskey *dev) usb_free_urb(dev->urb); kfree(dev->name); kfree(dev->buf); + usb_put_intf(dev->interface); kfree(dev); } } @@ -145,6 +146,8 @@ static int chaoskey_probe(struct usb_interface *interface, if (dev == NULL) goto out; + dev->interface = usb_get_intf(interface); + dev->buf = kmalloc(size, GFP_KERNEL); if (dev->buf == NULL) @@ -174,8 +177,6 @@ static int chaoskey_probe(struct usb_interface *interface, goto out; } - dev->interface = interface; - dev->in_ep = in_ep; if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID) @@ -383,13 +384,17 @@ static int _chaoskey_fill(struct chaoskey *dev) !dev->reading, (started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) ); - if (result < 0) + if (result < 0) { + usb_kill_urb(dev->urb); goto out; + } - if (result == 0) + if (result == 0) { result = -ETIMEDOUT; - else + usb_kill_urb(dev->urb); + } else { result = dev->valid; + } out: /* Let the device go back to sleep eventually */ usb_autopm_put_interface(dev->interface); @@ -525,7 +530,21 @@ static int chaoskey_suspend(struct usb_interface *interface, static int chaoskey_resume(struct usb_interface *interface) { + struct chaoskey *dev; + struct usb_device *udev = interface_to_usbdev(interface); + usb_dbg(interface, "resume"); + dev = usb_get_intfdata(interface); + + /* + * We may have lost power. + * In that case the device that needs a long time + * for the first requests needs an extended timeout + * again + */ + if (le16_to_cpu(udev->descriptor.idVendor) == ALEA_VENDOR_ID) + dev->reads_started = false; + return 0; } #else diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index cdee3af33ad7..8a3d9c0c8d8b 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -333,7 +333,8 @@ static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi) *respond->result = -ESHUTDOWN; *respond->value = 0; complete(&respond->wait_completion); - } mutex_unlock(&ftdi->u132_lock); + } + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi) @@ -763,7 +764,8 @@ static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size) struct u132_command *command = &ftdi->command[COMMAND_MASK & i++]; total_size += 5 + command->follows; - } return total_size; + } + return total_size; } static int ftdi_elan_command_engine(struct usb_ftdi *ftdi) diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 20b0f91a5d9b..4afb5ddfd361 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -56,11 +56,10 @@ static const struct usb_device_id idmouse_table[] = { #define FTIP_SCROLL 0x24 #define ftip_command(dev, command, value, index) \ - usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), command, \ + usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), command, \ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000) MODULE_DEVICE_TABLE(usb, idmouse_table); -static DEFINE_MUTEX(open_disc_mutex); /* structure to hold all of our device specific stuff */ struct usb_idmouse { @@ -158,8 +157,8 @@ static int idmouse_create_image(struct usb_idmouse *dev) /* loop over a blocking bulk read to get data from the device */ while (bytes_read < IMGSIZE) { - result = usb_bulk_msg (dev->udev, - usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), + result = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), dev->bulk_in_buffer + bytes_read, dev->bulk_in_size, &bulk_read, 5000); if (result < 0) { @@ -223,21 +222,17 @@ static int idmouse_open(struct inode *inode, struct file *file) int result; /* get the interface from minor number and driver information */ - interface = usb_find_interface (&idmouse_driver, iminor (inode)); + interface = usb_find_interface(&idmouse_driver, iminor(inode)); if (!interface) return -ENODEV; - mutex_lock(&open_disc_mutex); /* get the device information block from the interface */ dev = usb_get_intfdata(interface); - if (!dev) { - mutex_unlock(&open_disc_mutex); + if (!dev) return -ENODEV; - } /* lock this device */ mutex_lock(&dev->lock); - mutex_unlock(&open_disc_mutex); /* check if already open */ if (dev->open) { @@ -251,7 +246,7 @@ static int idmouse_open(struct inode *inode, struct file *file) result = usb_autopm_get_interface(interface); if (result) goto error; - result = idmouse_create_image (dev); + result = idmouse_create_image(dev); usb_autopm_put_interface(interface); if (result) goto error; @@ -280,27 +275,17 @@ static int idmouse_release(struct inode *inode, struct file *file) if (dev == NULL) return -ENODEV; - mutex_lock(&open_disc_mutex); /* lock our device */ mutex_lock(&dev->lock); - /* are we really open? */ - if (dev->open <= 0) { - mutex_unlock(&dev->lock); - mutex_unlock(&open_disc_mutex); - return -ENODEV; - } - --dev->open; if (!dev->present) { /* the device was unplugged before the file was released */ mutex_unlock(&dev->lock); - mutex_unlock(&open_disc_mutex); idmouse_delete(dev); } else { mutex_unlock(&dev->lock); - mutex_unlock(&open_disc_mutex); } return 0; } @@ -379,7 +364,6 @@ static int idmouse_probe(struct usb_interface *interface, if (result) { /* something prevented us from registering this device */ dev_err(&interface->dev, "Unable to allocate minor number.\n"); - usb_set_intfdata(interface, NULL); idmouse_delete(dev); return result; } @@ -392,19 +376,13 @@ static int idmouse_probe(struct usb_interface *interface, static void idmouse_disconnect(struct usb_interface *interface) { - struct usb_idmouse *dev; - - /* get device structure */ - dev = usb_get_intfdata(interface); + struct usb_idmouse *dev = usb_get_intfdata(interface); /* give back our minor */ usb_deregister_dev(interface, &idmouse_class); - mutex_lock(&open_disc_mutex); - usb_set_intfdata(interface, NULL); /* lock the device */ mutex_lock(&dev->lock); - mutex_unlock(&open_disc_mutex); /* prevent device read, write and ioctl */ dev->present = 0; diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index f5bed9f29e56..dce44fbf031f 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -54,11 +54,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -/* Module parameters */ -static DEFINE_MUTEX(iowarrior_mutex); - static struct usb_driver iowarrior_driver; -static DEFINE_MUTEX(iowarrior_open_disc_lock); /*--------------*/ /* data */ @@ -87,6 +83,7 @@ struct iowarrior { char chip_serial[9]; /* the serial number string of the chip connected */ int report_size; /* number of bytes in a report */ u16 product_id; + struct usb_anchor submitted; }; /*--------------*/ @@ -243,6 +240,7 @@ static inline void iowarrior_delete(struct iowarrior *dev) kfree(dev->int_in_buffer); usb_free_urb(dev->int_in_urb); kfree(dev->read_queue); + usb_put_intf(dev->interface); kfree(dev); } @@ -424,11 +422,13 @@ static ssize_t iowarrior_write(struct file *file, retval = -EFAULT; goto error; } + usb_anchor_urb(int_out_urb, &dev->submitted); retval = usb_submit_urb(int_out_urb, GFP_KERNEL); if (retval) { dev_dbg(&dev->interface->dev, "submit error %d for urb nr.%d\n", retval, atomic_read(&dev->write_busy)); + usb_unanchor_urb(int_out_urb); goto error; } /* submit was ok */ @@ -477,8 +477,6 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, if (!buffer) return -ENOMEM; - /* lock this object */ - mutex_lock(&iowarrior_mutex); mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ @@ -571,7 +569,6 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, error_out: /* unlock the device */ mutex_unlock(&dev->mutex); - mutex_unlock(&iowarrior_mutex); kfree(buffer); return retval; } @@ -586,27 +583,20 @@ static int iowarrior_open(struct inode *inode, struct file *file) int subminor; int retval = 0; - mutex_lock(&iowarrior_mutex); subminor = iminor(inode); interface = usb_find_interface(&iowarrior_driver, subminor); if (!interface) { - mutex_unlock(&iowarrior_mutex); - printk(KERN_ERR "%s - error, can't find device for minor %d\n", + pr_err("%s - error, can't find device for minor %d\n", __func__, subminor); return -ENODEV; } - mutex_lock(&iowarrior_open_disc_lock); dev = usb_get_intfdata(interface); - if (!dev) { - mutex_unlock(&iowarrior_open_disc_lock); - mutex_unlock(&iowarrior_mutex); + if (!dev) return -ENODEV; - } mutex_lock(&dev->mutex); - mutex_unlock(&iowarrior_open_disc_lock); /* Only one process can open each device, no sharing. */ if (dev->opened) { @@ -628,7 +618,6 @@ static int iowarrior_open(struct inode *inode, struct file *file) out: mutex_unlock(&dev->mutex); - mutex_unlock(&iowarrior_mutex); return retval; } @@ -764,11 +753,13 @@ static int iowarrior_probe(struct usb_interface *interface, init_waitqueue_head(&dev->write_wait); dev->udev = udev; - dev->interface = interface; + dev->interface = usb_get_intf(interface); iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct); + init_usb_anchor(&dev->submitted); + res = usb_find_last_int_in_endpoint(iface_desc, &dev->int_in_endpoint); if (res) { dev_err(&interface->dev, "no interrupt-in endpoint found\n"); @@ -836,7 +827,6 @@ static int iowarrior_probe(struct usb_interface *interface, if (retval) { /* something prevented us from registering this driver */ dev_err(&interface->dev, "Not able to get a minor for this device.\n"); - usb_set_intfdata(interface, NULL); goto error; } @@ -860,26 +850,15 @@ error: */ static void iowarrior_disconnect(struct usb_interface *interface) { - struct iowarrior *dev; - int minor; - - dev = usb_get_intfdata(interface); - mutex_lock(&iowarrior_open_disc_lock); - usb_set_intfdata(interface, NULL); - /* prevent device read, write and ioctl */ - dev->present = 0; - - minor = dev->minor; - mutex_unlock(&iowarrior_open_disc_lock); - /* give back our minor - this will call close() locks need to be dropped at this point*/ + struct iowarrior *dev = usb_get_intfdata(interface); + int minor = dev->minor; usb_deregister_dev(interface, &iowarrior_class); mutex_lock(&dev->mutex); /* prevent device read, write and ioctl */ - - mutex_unlock(&dev->mutex); + dev->present = 0; if (dev->opened) { /* There is a process that holds a filedescriptor to the device , @@ -887,10 +866,13 @@ static void iowarrior_disconnect(struct usb_interface *interface) Deleting the device is postponed until close() was called. */ usb_kill_urb(dev->int_in_urb); + usb_kill_anchored_urbs(&dev->submitted); wake_up_interruptible(&dev->read_wait); wake_up_interruptible(&dev->write_wait); + mutex_unlock(&dev->mutex); } else { /* no process is using the device, cleanup now */ + mutex_unlock(&dev->mutex); iowarrior_delete(dev); } diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 6581774bdfa4..8f86b4ebca89 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -153,6 +153,7 @@ MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in struct ld_usb { struct mutex mutex; /* locks this structure */ struct usb_interface *intf; /* save off the usb interface pointer */ + unsigned long disconnected:1; int open_count; /* number of times this port has been opened */ @@ -192,12 +193,10 @@ static void ld_usb_abort_transfers(struct ld_usb *dev) /* shutdown transfer */ if (dev->interrupt_in_running) { dev->interrupt_in_running = 0; - if (dev->intf) - usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_in_urb); } if (dev->interrupt_out_busy) - if (dev->intf) - usb_kill_urb(dev->interrupt_out_urb); + usb_kill_urb(dev->interrupt_out_urb); } /** @@ -205,8 +204,6 @@ static void ld_usb_abort_transfers(struct ld_usb *dev) */ static void ld_usb_delete(struct ld_usb *dev) { - ld_usb_abort_transfers(dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -263,7 +260,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) resubmit: /* resubmit if we're still running */ - if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) { + if (dev->interrupt_in_running && !dev->buffer_overflow) { retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); if (retval) { dev_err(&dev->intf->dev, @@ -383,16 +380,13 @@ static int ld_usb_release(struct inode *inode, struct file *file) goto exit; } - if (mutex_lock_interruptible(&dev->mutex)) { - retval = -ERESTARTSYS; - goto exit; - } + mutex_lock(&dev->mutex); if (dev->open_count != 1) { retval = -ENODEV; goto unlock_exit; } - if (dev->intf == NULL) { + if (dev->disconnected) { /* the device was unplugged before the file was released */ mutex_unlock(&dev->mutex); /* unlock here as ld_usb_delete frees dev */ @@ -423,7 +417,7 @@ static __poll_t ld_usb_poll(struct file *file, poll_table *wait) dev = file->private_data; - if (!dev->intf) + if (dev->disconnected) return EPOLLERR | EPOLLHUP; poll_wait(file, &dev->read_wait, wait); @@ -462,7 +456,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, } /* verify that the device wasn't unplugged */ - if (dev->intf == NULL) { + if (dev->disconnected) { retval = -ENODEV; printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; @@ -470,7 +464,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, /* wait for data */ spin_lock_irq(&dev->rbsl); - if (dev->ring_head == dev->ring_tail) { + while (dev->ring_head == dev->ring_tail) { dev->interrupt_in_done = 0; spin_unlock_irq(&dev->rbsl); if (file->f_flags & O_NONBLOCK) { @@ -480,15 +474,20 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); if (retval < 0) goto unlock_exit; - } else { - spin_unlock_irq(&dev->rbsl); + + spin_lock_irq(&dev->rbsl); } + spin_unlock_irq(&dev->rbsl); /* actual_buffer contains actual_length + interrupt_in_buffer */ actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_endpoint_size)); + if (*actual_buffer > dev->interrupt_in_endpoint_size) { + retval = -EIO; + goto unlock_exit; + } bytes_to_read = min(count, *actual_buffer); if (bytes_to_read < *actual_buffer) - dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n", + dev_warn(&dev->intf->dev, "Read buffer overflow, %zu bytes dropped\n", *actual_buffer-bytes_to_read); /* copy one interrupt_in_buffer from ring_buffer into userspace */ @@ -496,11 +495,11 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = -EFAULT; goto unlock_exit; } - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; - retval = bytes_to_read; spin_lock_irq(&dev->rbsl); + dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; + if (dev->buffer_overflow) { dev->buffer_overflow = 0; spin_unlock_irq(&dev->rbsl); @@ -542,7 +541,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, } /* verify that the device wasn't unplugged */ - if (dev->intf == NULL) { + if (dev->disconnected) { retval = -ENODEV; printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; @@ -563,8 +562,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, /* write the data into interrupt_out_buffer from userspace */ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); if (bytes_to_write < count) - dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n", count-bytes_to_write); - dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + dev_warn(&dev->intf->dev, "Write buffer overflow, %zu bytes dropped\n", + count - bytes_to_write); + dev_dbg(&dev->intf->dev, "%s: count = %zu, bytes_to_write = %zu\n", __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { @@ -581,7 +581,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, 1 << 8, 0, dev->interrupt_out_buffer, bytes_to_write, - USB_CTRL_SET_TIMEOUT * HZ); + USB_CTRL_SET_TIMEOUT); if (retval < 0) dev_err(&dev->intf->dev, "Couldn't submit HID_REQ_SET_REPORT %d\n", @@ -696,10 +696,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); - dev->ring_buffer = - kmalloc_array(ring_buffer_size, - sizeof(size_t) + dev->interrupt_in_endpoint_size, - GFP_KERNEL); + dev->ring_buffer = kcalloc(ring_buffer_size, + sizeof(size_t) + dev->interrupt_in_endpoint_size, + GFP_KERNEL); if (!dev->ring_buffer) goto error; dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); @@ -764,6 +763,9 @@ static void ld_usb_disconnect(struct usb_interface *intf) /* give back our minor */ usb_deregister_dev(intf, &ld_usb_class); + usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); + mutex_lock(&dev->mutex); /* if the device is not opened, then we clean up right now */ @@ -771,7 +773,7 @@ static void ld_usb_disconnect(struct usb_interface *intf) mutex_unlock(&dev->mutex); ld_usb_delete(dev); } else { - dev->intf = NULL; + dev->disconnected = 1; /* wake up pollers */ wake_up_interruptible_all(&dev->read_wait); wake_up_interruptible_all(&dev->write_wait); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 006cf13b2199..ab4b98b04115 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -157,19 +157,19 @@ MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms"); #define LEGO_USB_TOWER_REQUEST_GET_VERSION 0xFD struct tower_reset_reply { - __le16 size; /* little-endian */ + __le16 size; __u8 err_code; __u8 spare; -} __attribute__ ((packed)); +}; struct tower_get_version_reply { - __le16 size; /* little-endian */ + __le16 size; __u8 err_code; __u8 spare; __u8 major; __u8 minor; - __le16 build_no; /* little-endian */ -} __attribute__ ((packed)); + __le16 build_no; +}; /* table of devices that work with this driver */ @@ -178,8 +178,7 @@ static const struct usb_device_id tower_table[] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, tower_table); -static DEFINE_MUTEX(open_disc_mutex); +MODULE_DEVICE_TABLE(usb, tower_table); #define LEGO_USB_TOWER_MINOR_BASE 160 @@ -187,12 +186,13 @@ static DEFINE_MUTEX(open_disc_mutex); /* Structure to hold all of our device specific stuff */ struct lego_usb_tower { struct mutex lock; /* locks this structure */ - struct usb_device* udev; /* save off the usb device pointer */ + struct usb_device *udev; /* save off the usb device pointer */ unsigned char minor; /* the starting minor number for this device */ int open_count; /* number of times this port has been opened */ + unsigned long disconnected:1; - char* read_buffer; + char *read_buffer; size_t read_buffer_length; /* this much came in */ size_t read_packet_length; /* this much will be returned on read */ spinlock_t read_buffer_lock; @@ -202,16 +202,15 @@ struct lego_usb_tower { wait_queue_head_t read_wait; wait_queue_head_t write_wait; - char* interrupt_in_buffer; - struct usb_endpoint_descriptor* interrupt_in_endpoint; - struct urb* interrupt_in_urb; + char *interrupt_in_buffer; + struct usb_endpoint_descriptor *interrupt_in_endpoint; + struct urb *interrupt_in_urb; int interrupt_in_interval; - int interrupt_in_running; int interrupt_in_done; - char* interrupt_out_buffer; - struct usb_endpoint_descriptor* interrupt_out_endpoint; - struct urb* interrupt_out_urb; + char *interrupt_out_buffer; + struct usb_endpoint_descriptor *interrupt_out_endpoint; + struct urb *interrupt_out_urb; int interrupt_out_interval; int interrupt_out_busy; @@ -219,21 +218,20 @@ struct lego_usb_tower { /* local function prototypes */ -static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos); -static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos); -static inline void tower_delete (struct lego_usb_tower *dev); -static int tower_open (struct inode *inode, struct file *file); -static int tower_release (struct inode *inode, struct file *file); -static __poll_t tower_poll (struct file *file, poll_table *wait); -static loff_t tower_llseek (struct file *file, loff_t off, int whence); +static ssize_t tower_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos); +static ssize_t tower_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos); +static inline void tower_delete(struct lego_usb_tower *dev); +static int tower_open(struct inode *inode, struct file *file); +static int tower_release(struct inode *inode, struct file *file); +static __poll_t tower_poll(struct file *file, poll_table *wait); +static loff_t tower_llseek(struct file *file, loff_t off, int whence); -static void tower_abort_transfers (struct lego_usb_tower *dev); -static void tower_check_for_read_packet (struct lego_usb_tower *dev); -static void tower_interrupt_in_callback (struct urb *urb); -static void tower_interrupt_out_callback (struct urb *urb); +static void tower_check_for_read_packet(struct lego_usb_tower *dev); +static void tower_interrupt_in_callback(struct urb *urb); +static void tower_interrupt_out_callback(struct urb *urb); -static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id); -static void tower_disconnect (struct usb_interface *interface); +static int tower_probe(struct usb_interface *interface, const struct usb_device_id *id); +static void tower_disconnect(struct usb_interface *interface); /* file operations needed when we register this driver */ @@ -288,24 +286,23 @@ static inline void lego_usb_tower_debug_data(struct device *dev, /** * tower_delete */ -static inline void tower_delete (struct lego_usb_tower *dev) +static inline void tower_delete(struct lego_usb_tower *dev) { - tower_abort_transfers (dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); - kfree (dev->read_buffer); - kfree (dev->interrupt_in_buffer); - kfree (dev->interrupt_out_buffer); - kfree (dev); + kfree(dev->read_buffer); + kfree(dev->interrupt_in_buffer); + kfree(dev->interrupt_out_buffer); + usb_put_dev(dev->udev); + kfree(dev); } /** * tower_open */ -static int tower_open (struct inode *inode, struct file *file) +static int tower_open(struct inode *inode, struct file *file) { struct lego_usb_tower *dev = NULL; int subminor; @@ -315,7 +312,6 @@ static int tower_open (struct inode *inode, struct file *file) int result; reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL); - if (!reset_reply) { retval = -ENOMEM; goto exit; @@ -324,26 +320,21 @@ static int tower_open (struct inode *inode, struct file *file) nonseekable_open(inode, file); subminor = iminor(inode); - interface = usb_find_interface (&tower_driver, subminor); - + interface = usb_find_interface(&tower_driver, subminor); if (!interface) { pr_err("error, can't find device for minor %d\n", subminor); retval = -ENODEV; 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 (mutex_lock_interruptible(&dev->lock)) { - mutex_unlock(&open_disc_mutex); retval = -ERESTARTSYS; goto exit; } @@ -351,23 +342,20 @@ static int tower_open (struct inode *inode, struct file *file) /* 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, - usb_rcvctrlpipe(dev->udev, 0), - LEGO_USB_TOWER_REQUEST_RESET, - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, - reset_reply, - sizeof(*reset_reply), - 1000); + result = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + LEGO_USB_TOWER_REQUEST_RESET, + USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + 0, + 0, + reset_reply, + sizeof(*reset_reply), + 1000); if (result < 0) { dev_err(&dev->udev->dev, "LEGO USB Tower reset control request failed\n"); @@ -378,31 +366,30 @@ static int tower_open (struct inode *inode, struct file *file) /* initialize in direction */ dev->read_buffer_length = 0; dev->read_packet_length = 0; - usb_fill_int_urb (dev->interrupt_in_urb, - dev->udev, - usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - usb_endpoint_maxp(dev->interrupt_in_endpoint), - tower_interrupt_in_callback, - dev, - dev->interrupt_in_interval); - - dev->interrupt_in_running = 1; + usb_fill_int_urb(dev->interrupt_in_urb, + dev->udev, + usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_buffer, + usb_endpoint_maxp(dev->interrupt_in_endpoint), + tower_interrupt_in_callback, + dev, + dev->interrupt_in_interval); + dev->interrupt_in_done = 0; mb(); - retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL); + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); if (retval) { dev_err(&dev->udev->dev, "Couldn't submit interrupt_in_urb %d\n", retval); - dev->interrupt_in_running = 0; - dev->open_count = 0; goto unlock_exit; } /* save device in the file's private structure */ file->private_data = dev; + dev->open_count = 1; + unlock_exit: mutex_unlock(&dev->lock); @@ -414,77 +401,45 @@ exit: /** * tower_release */ -static int tower_release (struct inode *inode, struct file *file) +static int tower_release(struct inode *inode, struct file *file) { struct lego_usb_tower *dev; int retval = 0; dev = file->private_data; - if (dev == NULL) { retval = -ENODEV; - goto exit_nolock; - } - - mutex_lock(&open_disc_mutex); - if (mutex_lock_interruptible(&dev->lock)) { - retval = -ERESTARTSYS; goto exit; } - if (dev->open_count != 1) { - dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", - __func__); - retval = -ENODEV; - goto unlock_exit; - } - if (dev->udev == NULL) { + mutex_lock(&dev->lock); + + if (dev->disconnected) { /* the device was unplugged before the file was released */ /* unlock here as tower_delete frees dev */ mutex_unlock(&dev->lock); - tower_delete (dev); + tower_delete(dev); goto exit; } /* wait until write transfer is finished */ if (dev->interrupt_out_busy) { - wait_event_interruptible_timeout (dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); + wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, + 2 * HZ); } - tower_abort_transfers (dev); + + /* shutdown transfers */ + usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_out_urb); + dev->open_count = 0; -unlock_exit: mutex_unlock(&dev->lock); - exit: - mutex_unlock(&open_disc_mutex); -exit_nolock: return retval; } - -/** - * tower_abort_transfers - * aborts transfers and frees associated data structures - */ -static void tower_abort_transfers (struct lego_usb_tower *dev) -{ - if (dev == NULL) - return; - - /* shutdown transfer */ - if (dev->interrupt_in_running) { - dev->interrupt_in_running = 0; - mb(); - if (dev->udev) - usb_kill_urb (dev->interrupt_in_urb); - } - if (dev->interrupt_out_busy && dev->udev) - usb_kill_urb(dev->interrupt_out_urb); -} - - /** * tower_check_for_read_packet * @@ -493,42 +448,40 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) * until it has been there unchanged for at least * dev->packet_timeout_jiffies, or until the buffer is full. */ -static void tower_check_for_read_packet (struct lego_usb_tower *dev) +static void tower_check_for_read_packet(struct lego_usb_tower *dev) { - spin_lock_irq (&dev->read_buffer_lock); + spin_lock_irq(&dev->read_buffer_lock); if (!packet_timeout || time_after(jiffies, dev->read_last_arrival + dev->packet_timeout_jiffies) || dev->read_buffer_length == read_buffer_size) { dev->read_packet_length = dev->read_buffer_length; } dev->interrupt_in_done = 0; - spin_unlock_irq (&dev->read_buffer_lock); + spin_unlock_irq(&dev->read_buffer_lock); } /** * tower_poll */ -static __poll_t tower_poll (struct file *file, poll_table *wait) +static __poll_t tower_poll(struct file *file, poll_table *wait) { struct lego_usb_tower *dev; __poll_t mask = 0; dev = file->private_data; - if (!dev->udev) + if (dev->disconnected) return EPOLLERR | EPOLLHUP; poll_wait(file, &dev->read_wait, wait); poll_wait(file, &dev->write_wait, wait); tower_check_for_read_packet(dev); - if (dev->read_packet_length > 0) { + if (dev->read_packet_length > 0) mask |= EPOLLIN | EPOLLRDNORM; - } - if (!dev->interrupt_out_busy) { + if (!dev->interrupt_out_busy) mask |= EPOLLOUT | EPOLLWRNORM; - } return mask; } @@ -537,7 +490,7 @@ static __poll_t tower_poll (struct file *file, poll_table *wait) /** * tower_llseek */ -static loff_t tower_llseek (struct file *file, loff_t off, int whence) +static loff_t tower_llseek(struct file *file, loff_t off, int whence) { return -ESPIPE; /* unseekable */ } @@ -546,7 +499,7 @@ static loff_t tower_llseek (struct file *file, loff_t off, int whence) /** * tower_read */ -static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) +static ssize_t tower_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; size_t bytes_to_read; @@ -563,9 +516,8 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, } /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; - pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -575,21 +527,19 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, goto unlock_exit; } - if (read_timeout) { + if (read_timeout) timeout = jiffies + msecs_to_jiffies(read_timeout); - } /* wait for data */ - tower_check_for_read_packet (dev); + tower_check_for_read_packet(dev); while (dev->read_packet_length == 0) { if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; goto unlock_exit; } retval = wait_event_interruptible_timeout(dev->read_wait, dev->interrupt_in_done, dev->packet_timeout_jiffies); - if (retval < 0) { + if (retval < 0) goto unlock_exit; - } /* reset read timeout during read or write activity */ if (read_timeout @@ -597,28 +547,27 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, timeout = jiffies + msecs_to_jiffies(read_timeout); } /* check for read timeout */ - if (read_timeout && time_after (jiffies, timeout)) { + if (read_timeout && time_after(jiffies, timeout)) { retval = -ETIMEDOUT; goto unlock_exit; } - tower_check_for_read_packet (dev); + tower_check_for_read_packet(dev); } /* copy the data from read_buffer into userspace */ bytes_to_read = min(count, dev->read_packet_length); - if (copy_to_user (buffer, dev->read_buffer, bytes_to_read)) { + if (copy_to_user(buffer, dev->read_buffer, bytes_to_read)) { retval = -EFAULT; goto unlock_exit; } - spin_lock_irq (&dev->read_buffer_lock); + spin_lock_irq(&dev->read_buffer_lock); dev->read_buffer_length -= bytes_to_read; dev->read_packet_length -= bytes_to_read; - for (i=0; i<dev->read_buffer_length; i++) { + for (i = 0; i < dev->read_buffer_length; i++) dev->read_buffer[i] = dev->read_buffer[i+bytes_to_read]; - } - spin_unlock_irq (&dev->read_buffer_lock); + spin_unlock_irq(&dev->read_buffer_lock); retval = bytes_to_read; @@ -634,7 +583,7 @@ exit: /** * tower_write */ -static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +static ssize_t tower_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; size_t bytes_to_write; @@ -649,9 +598,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t } /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (dev->disconnected) { retval = -ENODEV; - pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -667,10 +615,10 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t retval = -EAGAIN; goto unlock_exit; } - retval = wait_event_interruptible (dev->write_wait, !dev->interrupt_out_busy); - if (retval) { + retval = wait_event_interruptible(dev->write_wait, + !dev->interrupt_out_busy); + if (retval) goto unlock_exit; - } } /* write the data into interrupt_out_buffer from userspace */ @@ -678,7 +626,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t dev_dbg(&dev->udev->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); - if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { + if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; goto unlock_exit; } @@ -696,7 +644,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t dev->interrupt_out_busy = 1; wmb(); - retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL); + retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval) { dev->interrupt_out_busy = 0; dev_err(&dev->udev->dev, @@ -717,7 +665,7 @@ exit: /** * tower_interrupt_in_callback */ -static void tower_interrupt_in_callback (struct urb *urb) +static void tower_interrupt_in_callback(struct urb *urb) { struct lego_usb_tower *dev = urb->context; int status = urb->status; @@ -743,9 +691,9 @@ static void tower_interrupt_in_callback (struct urb *urb) if (urb->actual_length > 0) { spin_lock_irqsave(&dev->read_buffer_lock, flags); if (dev->read_buffer_length + urb->actual_length < read_buffer_size) { - memcpy (dev->read_buffer + dev->read_buffer_length, - dev->interrupt_in_buffer, - urb->actual_length); + memcpy(dev->read_buffer + dev->read_buffer_length, + dev->interrupt_in_buffer, + urb->actual_length); dev->read_buffer_length += urb->actual_length; dev->read_last_arrival = jiffies; dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", @@ -758,25 +706,21 @@ static void tower_interrupt_in_callback (struct urb *urb) } resubmit: - /* resubmit if we're still running */ - if (dev->interrupt_in_running && dev->udev) { - retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC); - if (retval) - dev_err(&dev->udev->dev, - "%s: usb_submit_urb failed (%d)\n", - __func__, retval); + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); + if (retval) { + dev_err(&dev->udev->dev, "%s: usb_submit_urb failed (%d)\n", + __func__, retval); } - exit: dev->interrupt_in_done = 1; - wake_up_interruptible (&dev->read_wait); + wake_up_interruptible(&dev->read_wait); } /** * tower_interrupt_out_callback */ -static void tower_interrupt_out_callback (struct urb *urb) +static void tower_interrupt_out_callback(struct urb *urb) { struct lego_usb_tower *dev = urb->context; int status = urb->status; @@ -804,47 +748,27 @@ static void tower_interrupt_out_callback (struct urb *urb) * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */ -static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id) +static int tower_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct device *idev = &interface->dev; struct usb_device *udev = interface_to_usbdev(interface); - struct lego_usb_tower *dev = NULL; + struct lego_usb_tower *dev; struct tower_get_version_reply *get_version_reply = NULL; int retval = -ENOMEM; int result; /* allocate memory for our device state and initialize it */ - - dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); - + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) goto exit; mutex_init(&dev->lock); - - dev->udev = udev; - dev->open_count = 0; - - dev->read_buffer = NULL; - dev->read_buffer_length = 0; - dev->read_packet_length = 0; - spin_lock_init (&dev->read_buffer_lock); + dev->udev = usb_get_dev(udev); + spin_lock_init(&dev->read_buffer_lock); dev->packet_timeout_jiffies = msecs_to_jiffies(packet_timeout); dev->read_last_arrival = jiffies; - - init_waitqueue_head (&dev->read_wait); - init_waitqueue_head (&dev->write_wait); - - dev->interrupt_in_buffer = NULL; - dev->interrupt_in_endpoint = NULL; - dev->interrupt_in_urb = NULL; - dev->interrupt_in_running = 0; - dev->interrupt_in_done = 0; - - dev->interrupt_out_buffer = NULL; - dev->interrupt_out_endpoint = NULL; - dev->interrupt_out_urb = NULL; - dev->interrupt_out_busy = 0; + init_waitqueue_head(&dev->read_wait); + init_waitqueue_head(&dev->write_wait); result = usb_find_common_endpoints_reverse(interface->cur_altsetting, NULL, NULL, @@ -856,16 +780,16 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device goto error; } - dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL); + dev->read_buffer = kmalloc(read_buffer_size, GFP_KERNEL); if (!dev->read_buffer) goto error; - dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL); + dev->interrupt_in_buffer = kmalloc(usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL); if (!dev->interrupt_in_buffer) goto error; dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->interrupt_in_urb) goto error; - dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL); + dev->interrupt_out_buffer = kmalloc(write_buffer_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) goto error; dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -875,24 +799,25 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL); - if (!get_version_reply) { retval = -ENOMEM; goto error; } /* get the firmware version and log it */ - result = usb_control_msg (udev, - usb_rcvctrlpipe(udev, 0), - LEGO_USB_TOWER_REQUEST_GET_VERSION, - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, - get_version_reply, - sizeof(*get_version_reply), - 1000); - if (result < 0) { - dev_err(idev, "LEGO USB Tower get version control request failed\n"); + result = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + LEGO_USB_TOWER_REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + 0, + 0, + get_version_reply, + sizeof(*get_version_reply), + 1000); + if (result != sizeof(*get_version_reply)) { + if (result >= 0) + result = -EIO; + dev_err(idev, "get version request failed: %d\n", result); retval = result; goto error; } @@ -903,14 +828,12 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device le16_to_cpu(get_version_reply->build_no)); /* we can register the device now, as it is ready */ - usb_set_intfdata (interface, dev); - - retval = usb_register_dev (interface, &tower_class); + usb_set_intfdata(interface, dev); + retval = usb_register_dev(interface, &tower_class); if (retval) { /* something prevented us from registering this driver */ dev_err(idev, "Not able to get a minor for this device.\n"); - usb_set_intfdata (interface, NULL); goto error; } dev->minor = interface->minor; @@ -936,29 +859,30 @@ error: * * Called by the usb core when the device is removed from the system. */ -static void tower_disconnect (struct usb_interface *interface) +static void tower_disconnect(struct usb_interface *interface) { struct lego_usb_tower *dev; int minor; - dev = usb_get_intfdata (interface); - mutex_lock(&open_disc_mutex); - usb_set_intfdata (interface, NULL); + dev = usb_get_intfdata(interface); minor = dev->minor; - /* give back our minor */ - usb_deregister_dev (interface, &tower_class); + /* give back our minor and prevent further open() */ + usb_deregister_dev(interface, &tower_class); + + /* stop I/O */ + usb_poison_urb(dev->interrupt_in_urb); + usb_poison_urb(dev->interrupt_out_urb); mutex_lock(&dev->lock); - mutex_unlock(&open_disc_mutex); /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { mutex_unlock(&dev->lock); - tower_delete (dev); + tower_delete(dev); } else { - dev->udev = NULL; + dev->disconnected = 1; /* wake up pollers */ wake_up_interruptible_all(&dev->read_wait); wake_up_interruptible_all(&dev->write_wait); @@ -973,6 +897,4 @@ module_usb_driver(tower_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c deleted file mode 100644 index 30cae5e1954d..000000000000 --- a/drivers/usb/misc/rio500.c +++ /dev/null @@ -1,554 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* -*- linux-c -*- */ - -/* - * Driver for USB Rio 500 - * - * Cesar Miquel (miquel@df.uba.ar) - * - * based on hp_scanner.c by David E. Nelson (dnelson@jump.net) - * - * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). - * - * Changelog: - * 30/05/2003 replaced lock/unlock kernel with up/down - * Daniele Bellucci bellucda@tiscali.it - * */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/sched/signal.h> -#include <linux/mutex.h> -#include <linux/errno.h> -#include <linux/random.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/usb.h> -#include <linux/wait.h> - -#include "rio500_usb.h" - -#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>" -#define DRIVER_DESC "USB Rio 500 driver" - -#define RIO_MINOR 64 - -/* stall/wait timeout for rio */ -#define NAK_TIMEOUT (HZ) - -#define IBUF_SIZE 0x1000 - -/* Size of the rio buffer */ -#define OBUF_SIZE 0x10000 - -struct rio_usb_data { - struct usb_device *rio_dev; /* init: probe_rio */ - unsigned int ifnum; /* Interface number of the USB device */ - int isopen; /* nz if open */ - int present; /* Device is present on the bus */ - char *obuf, *ibuf; /* transfer buffers */ - char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ - wait_queue_head_t wait_q; /* for timeouts */ -}; - -static DEFINE_MUTEX(rio500_mutex); -static struct rio_usb_data rio_instance; - -static int open_rio(struct inode *inode, struct file *file) -{ - struct rio_usb_data *rio = &rio_instance; - - /* against disconnect() */ - mutex_lock(&rio500_mutex); - - if (rio->isopen || !rio->present) { - mutex_unlock(&rio500_mutex); - return -EBUSY; - } - rio->isopen = 1; - - init_waitqueue_head(&rio->wait_q); - - - dev_info(&rio->rio_dev->dev, "Rio opened.\n"); - mutex_unlock(&rio500_mutex); - - return 0; -} - -static int close_rio(struct inode *inode, struct file *file) -{ - struct rio_usb_data *rio = &rio_instance; - - /* against disconnect() */ - mutex_lock(&rio500_mutex); - - rio->isopen = 0; - if (!rio->present) { - /* cleanup has been delayed */ - kfree(rio->ibuf); - kfree(rio->obuf); - rio->ibuf = NULL; - rio->obuf = NULL; - } else { - dev_info(&rio->rio_dev->dev, "Rio closed.\n"); - } - mutex_unlock(&rio500_mutex); - return 0; -} - -static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct RioCommand rio_cmd; - struct rio_usb_data *rio = &rio_instance; - void __user *data; - unsigned char *buffer; - int result, requesttype; - int retries; - int retval=0; - - mutex_lock(&rio500_mutex); - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - retval = -ENODEV; - goto err_out; - } - - switch (cmd) { - case RIO_RECV_COMMAND: - data = (void __user *) arg; - if (data == NULL) - break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { - retval = -EFAULT; - goto err_out; - } - if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { - retval = -EINVAL; - goto err_out; - } - buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) { - retval = -ENOMEM; - goto err_out; - } - if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { - retval = -EFAULT; - free_page((unsigned long) buffer); - goto err_out; - } - - requesttype = rio_cmd.requesttype | USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dev_dbg(&rio->rio_dev->dev, - "sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); - /* Send rio control message */ - retries = 3; - while (retries) { - result = usb_control_msg(rio->rio_dev, - usb_rcvctrlpipe(rio-> rio_dev, 0), - rio_cmd.request, - requesttype, - rio_cmd.value, - rio_cmd.index, buffer, - rio_cmd.length, - jiffies_to_msecs(rio_cmd.timeout)); - if (result == -ETIMEDOUT) - retries--; - else if (result < 0) { - dev_err(&rio->rio_dev->dev, - "Error executing ioctrl. code = %d\n", - result); - retries = 0; - } else { - dev_dbg(&rio->rio_dev->dev, - "Executed ioctl. Result = %d (data=%02x)\n", - result, buffer[0]); - if (copy_to_user(rio_cmd.buffer, buffer, - rio_cmd.length)) { - free_page((unsigned long) buffer); - retval = -EFAULT; - goto err_out; - } - retries = 0; - } - - /* rio_cmd.buffer contains a raw stream of single byte - data which has been returned from rio. Data is - interpreted at application level. For data that - will be cast to data types longer than 1 byte, data - will be little_endian and will potentially need to - be swapped at the app level */ - - } - free_page((unsigned long) buffer); - break; - - case RIO_SEND_COMMAND: - data = (void __user *) arg; - if (data == NULL) - break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { - retval = -EFAULT; - goto err_out; - } - if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { - retval = -EINVAL; - goto err_out; - } - buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) { - retval = -ENOMEM; - goto err_out; - } - if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { - free_page((unsigned long)buffer); - retval = -EFAULT; - goto err_out; - } - - requesttype = rio_cmd.requesttype | USB_DIR_OUT | - USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dev_dbg(&rio->rio_dev->dev, - "sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); - /* Send rio control message */ - retries = 3; - while (retries) { - result = usb_control_msg(rio->rio_dev, - usb_sndctrlpipe(rio-> rio_dev, 0), - rio_cmd.request, - requesttype, - rio_cmd.value, - rio_cmd.index, buffer, - rio_cmd.length, - jiffies_to_msecs(rio_cmd.timeout)); - if (result == -ETIMEDOUT) - retries--; - else if (result < 0) { - dev_err(&rio->rio_dev->dev, - "Error executing ioctrl. code = %d\n", - result); - retries = 0; - } else { - dev_dbg(&rio->rio_dev->dev, - "Executed ioctl. Result = %d\n", result); - retries = 0; - - } - - } - free_page((unsigned long) buffer); - break; - - default: - retval = -ENOTTY; - break; - } - - -err_out: - mutex_unlock(&rio500_mutex); - return retval; -} - -static ssize_t -write_rio(struct file *file, const char __user *buffer, - size_t count, loff_t * ppos) -{ - DEFINE_WAIT(wait); - struct rio_usb_data *rio = &rio_instance; - - unsigned long copy_size; - unsigned long bytes_written = 0; - unsigned int partial; - - int result = 0; - int maxretry; - int errn = 0; - int intr; - - intr = mutex_lock_interruptible(&rio500_mutex); - if (intr) - return -EINTR; - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - mutex_unlock(&rio500_mutex); - return -ENODEV; - } - - - - do { - unsigned long thistime; - char *obuf = rio->obuf; - - thistime = copy_size = - (count >= OBUF_SIZE) ? OBUF_SIZE : count; - if (copy_from_user(rio->obuf, buffer, copy_size)) { - errn = -EFAULT; - goto error; - } - maxretry = 5; - while (thistime) { - if (!rio->rio_dev) { - errn = -ENODEV; - goto error; - } - if (signal_pending(current)) { - mutex_unlock(&rio500_mutex); - return bytes_written ? bytes_written : -EINTR; - } - - result = usb_bulk_msg(rio->rio_dev, - usb_sndbulkpipe(rio->rio_dev, 2), - obuf, thistime, &partial, 5000); - - dev_dbg(&rio->rio_dev->dev, - "write stats: result:%d thistime:%lu partial:%u\n", - result, thistime, partial); - - if (result == -ETIMEDOUT) { /* NAK - so hold for a while */ - if (!maxretry--) { - errn = -ETIME; - goto error; - } - prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(NAK_TIMEOUT); - finish_wait(&rio->wait_q, &wait); - continue; - } else if (!result && partial) { - obuf += partial; - thistime -= partial; - } else - break; - } - if (result) { - dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n", - result); - errn = -EIO; - goto error; - } - bytes_written += copy_size; - count -= copy_size; - buffer += copy_size; - } while (count > 0); - - mutex_unlock(&rio500_mutex); - - return bytes_written ? bytes_written : -EIO; - -error: - mutex_unlock(&rio500_mutex); - return errn; -} - -static ssize_t -read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) -{ - DEFINE_WAIT(wait); - struct rio_usb_data *rio = &rio_instance; - ssize_t read_count; - unsigned int partial; - int this_read; - int result; - int maxretry = 10; - char *ibuf; - int intr; - - intr = mutex_lock_interruptible(&rio500_mutex); - if (intr) - return -EINTR; - /* Sanity check to make sure rio is connected, powered, etc */ - if (rio->present == 0 || rio->rio_dev == NULL) { - mutex_unlock(&rio500_mutex); - return -ENODEV; - } - - ibuf = rio->ibuf; - - read_count = 0; - - - while (count > 0) { - if (signal_pending(current)) { - mutex_unlock(&rio500_mutex); - return read_count ? read_count : -EINTR; - } - if (!rio->rio_dev) { - mutex_unlock(&rio500_mutex); - return -ENODEV; - } - this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; - - result = usb_bulk_msg(rio->rio_dev, - usb_rcvbulkpipe(rio->rio_dev, 1), - ibuf, this_read, &partial, - 8000); - - dev_dbg(&rio->rio_dev->dev, - "read stats: result:%d this_read:%u partial:%u\n", - result, this_read, partial); - - if (partial) { - count = this_read = partial; - } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ - if (!maxretry--) { - mutex_unlock(&rio500_mutex); - dev_err(&rio->rio_dev->dev, - "read_rio: maxretry timeout\n"); - return -ETIME; - } - prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(NAK_TIMEOUT); - finish_wait(&rio->wait_q, &wait); - continue; - } else if (result != -EREMOTEIO) { - mutex_unlock(&rio500_mutex); - dev_err(&rio->rio_dev->dev, - "Read Whoops - result:%d partial:%u this_read:%u\n", - result, partial, this_read); - return -EIO; - } else { - mutex_unlock(&rio500_mutex); - return (0); - } - - if (this_read) { - if (copy_to_user(buffer, ibuf, this_read)) { - mutex_unlock(&rio500_mutex); - return -EFAULT; - } - count -= this_read; - read_count += this_read; - buffer += this_read; - } - } - mutex_unlock(&rio500_mutex); - return read_count; -} - -static const struct file_operations usb_rio_fops = { - .owner = THIS_MODULE, - .read = read_rio, - .write = write_rio, - .unlocked_ioctl = ioctl_rio, - .open = open_rio, - .release = close_rio, - .llseek = noop_llseek, -}; - -static struct usb_class_driver usb_rio_class = { - .name = "rio500%d", - .fops = &usb_rio_fops, - .minor_base = RIO_MINOR, -}; - -static int probe_rio(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct rio_usb_data *rio = &rio_instance; - int retval = -ENOMEM; - char *ibuf, *obuf; - - if (rio->present) { - dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); - return -EBUSY; - } - dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); - - obuf = kmalloc(OBUF_SIZE, GFP_KERNEL); - if (!obuf) { - dev_err(&dev->dev, - "probe_rio: Not enough memory for the output buffer\n"); - goto err_obuf; - } - dev_dbg(&intf->dev, "obuf address: %p\n", obuf); - - ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL); - if (!ibuf) { - dev_err(&dev->dev, - "probe_rio: Not enough memory for the input buffer\n"); - goto err_ibuf; - } - dev_dbg(&intf->dev, "ibuf address: %p\n", ibuf); - - mutex_lock(&rio500_mutex); - rio->rio_dev = dev; - rio->ibuf = ibuf; - rio->obuf = obuf; - rio->present = 1; - mutex_unlock(&rio500_mutex); - - retval = usb_register_dev(intf, &usb_rio_class); - if (retval) { - dev_err(&dev->dev, - "Not able to get a minor for this device.\n"); - goto err_register; - } - - usb_set_intfdata(intf, rio); - return retval; - - err_register: - mutex_lock(&rio500_mutex); - rio->present = 0; - mutex_unlock(&rio500_mutex); - err_ibuf: - kfree(obuf); - err_obuf: - return retval; -} - -static void disconnect_rio(struct usb_interface *intf) -{ - struct rio_usb_data *rio = usb_get_intfdata (intf); - - usb_set_intfdata (intf, NULL); - if (rio) { - usb_deregister_dev(intf, &usb_rio_class); - - mutex_lock(&rio500_mutex); - if (rio->isopen) { - rio->isopen = 0; - /* better let it finish - the release will do whats needed */ - rio->rio_dev = NULL; - mutex_unlock(&rio500_mutex); - return; - } - kfree(rio->ibuf); - kfree(rio->obuf); - - dev_info(&intf->dev, "USB Rio disconnected.\n"); - - rio->present = 0; - mutex_unlock(&rio500_mutex); - } -} - -static const struct usb_device_id rio_table[] = { - { USB_DEVICE(0x0841, 1) }, /* Rio 500 */ - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, rio_table); - -static struct usb_driver rio_driver = { - .name = "rio500", - .probe = probe_rio, - .disconnect = disconnect_rio, - .id_table = rio_table, -}; - -module_usb_driver(rio_driver); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/misc/rio500_usb.h b/drivers/usb/misc/rio500_usb.h deleted file mode 100644 index 6db7a5863496..000000000000 --- a/drivers/usb/misc/rio500_usb.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* ---------------------------------------------------------------------- - Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar) - ---------------------------------------------------------------------- */ - -#define RIO_SEND_COMMAND 0x1 -#define RIO_RECV_COMMAND 0x2 - -#define RIO_DIR_OUT 0x0 -#define RIO_DIR_IN 0x1 - -struct RioCommand { - short length; - int request; - int requesttype; - int value; - int index; - void __user *buffer; - int timeout; -}; diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 9b632ab24f03..c16121276a21 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -4,7 +4,7 @@ config USB_SISUSBVGA tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)" depends on (USB_MUSB_HDRC || USB_EHCI_HCD) select FONT_SUPPORT if USB_SISUSBVGA_CON - ---help--- + ---help--- Say Y here if you intend to attach a USB2VGA dongle based on a Net2280 and a SiS315 chip. diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c index 6ca9111d150a..10c9e7f6273e 100644 --- a/drivers/usb/misc/usb251xb.c +++ b/drivers/usb/misc/usb251xb.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/nls.h> #include <linux/of_device.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> /* Internal Register Set Addresses & Default Values acc. to DS00001692C */ @@ -26,10 +27,6 @@ #define USB251XB_ADDR_PRODUCT_ID_LSB 0x02 #define USB251XB_ADDR_PRODUCT_ID_MSB 0x03 -#define USB251XB_DEF_PRODUCT_ID_12 0x2512 /* USB2512B/12Bi */ -#define USB251XB_DEF_PRODUCT_ID_13 0x2513 /* USB2513B/13Bi */ -#define USB251XB_DEF_PRODUCT_ID_14 0x2514 /* USB2514B/14Bi */ -#define USB251XB_DEF_PRODUCT_ID_17 0x2517 /* USB2517/17i */ #define USB251XB_ADDR_DEVICE_ID_LSB 0x04 #define USB251XB_ADDR_DEVICE_ID_MSB 0x05 @@ -74,7 +71,6 @@ #define USB251XB_ADDR_PRODUCT_STRING_LEN 0x14 #define USB251XB_ADDR_PRODUCT_STRING 0x54 -#define USB251XB_DEF_PRODUCT_STRING "USB251xB/xBi/7i" #define USB251XB_ADDR_SERIAL_STRING_LEN 0x15 #define USB251XB_ADDR_SERIAL_STRING 0x92 @@ -116,6 +112,7 @@ struct usb251xb { struct device *dev; struct i2c_client *i2c; + struct regulator *vdd; u8 skip_config; struct gpio_desc *gpio_reset; u16 vendor_id; @@ -159,6 +156,14 @@ struct usb251xb_data { char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */ }; +static const struct usb251xb_data usb2422_data = { + .product_id = 0x2422, + .port_cnt = 2, + .led_support = false, + .bat_support = true, + .product_str = "USB2422", +}; + static const struct usb251xb_data usb2512b_data = { .product_id = 0x2512, .port_cnt = 2, @@ -261,20 +266,19 @@ static int usb251x_check_gpio_chip(struct usb251xb *hub) } #endif -static void usb251xb_reset(struct usb251xb *hub, int state) +static void usb251xb_reset(struct usb251xb *hub) { if (!hub->gpio_reset) return; i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); - gpiod_set_value_cansleep(hub->gpio_reset, state); + gpiod_set_value_cansleep(hub->gpio_reset, 1); + usleep_range(1, 10); /* >=1us RESET_N asserted */ + gpiod_set_value_cansleep(hub->gpio_reset, 0); /* wait for hub recovery/stabilization */ - if (!state) - usleep_range(500, 750); /* >=500us at power on */ - else - usleep_range(1, 10); /* >=1us at power down */ + usleep_range(500, 750); /* >=500us after RESET_N deasserted */ i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); } @@ -292,7 +296,7 @@ static int usb251xb_connect(struct usb251xb *hub) i2c_wb[0] = 0x01; i2c_wb[1] = USB251XB_STATUS_COMMAND_ATTACH; - usb251xb_reset(hub, 0); + usb251xb_reset(hub); err = i2c_smbus_write_i2c_block_data(hub->i2c, USB251XB_ADDR_STATUS_COMMAND, 2, i2c_wb); @@ -342,7 +346,7 @@ static int usb251xb_connect(struct usb251xb *hub) i2c_wb[USB251XB_ADDR_PORT_MAP_7] = hub->port_map7; i2c_wb[USB251XB_ADDR_STATUS_COMMAND] = USB251XB_STATUS_COMMAND_ATTACH; - usb251xb_reset(hub, 0); + usb251xb_reset(hub); /* write registers */ for (i = 0; i < (USB251XB_I2C_REG_SZ / USB251XB_I2C_WRITE_SZ); i++) { @@ -420,6 +424,10 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, return err; } + hub->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(hub->vdd)) + return PTR_ERR(hub->vdd); + if (of_property_read_u16_array(np, "vendor-id", &hub->vendor_id, 1)) hub->vendor_id = USB251XB_DEF_VENDOR_ID; @@ -593,6 +601,9 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, static const struct of_device_id usb251xb_of_match[] = { { + .compatible = "microchip,usb2422", + .data = &usb2422_data, + }, { .compatible = "microchip,usb2512b", .data = &usb2512b_data, }, { @@ -665,6 +676,10 @@ static int usb251xb_probe(struct usb251xb *hub) if (err) return err; + err = regulator_enable(hub->vdd); + if (err) + return err; + err = usb251xb_connect(hub); if (err) { dev_err(dev, "Failed to connect hub (%d)\n", err); @@ -692,7 +707,31 @@ static int usb251xb_i2c_probe(struct i2c_client *i2c, return usb251xb_probe(hub); } +static int __maybe_unused usb251xb_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct usb251xb *hub = i2c_get_clientdata(client); + + return regulator_disable(hub->vdd); +} + +static int __maybe_unused usb251xb_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct usb251xb *hub = i2c_get_clientdata(client); + int err; + + err = regulator_enable(hub->vdd); + if (err) + return err; + + return usb251xb_connect(hub); +} + +static SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume); + static const struct i2c_device_id usb251xb_id[] = { + { "usb2422", 0 }, { "usb2512b", 0 }, { "usb2512bi", 0 }, { "usb2513b", 0 }, @@ -709,6 +748,7 @@ static struct i2c_driver usb251xb_i2c_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(usb251xb_of_match), + .pm = &usb251xb_pm_ops, }, .probe = usb251xb_i2c_probe, .id_table = usb251xb_id, diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 9ba4a4e68d91..61e9e987fe4a 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/mutex.h> +#include <linux/rwsem.h> #include <linux/uaccess.h> #include <linux/usb.h> @@ -29,16 +30,12 @@ #define IOCTL_GET_DRV_VERSION 2 -static DEFINE_MUTEX(lcd_mutex); static const struct usb_device_id id_table[] = { { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); -static DEFINE_MUTEX(open_disc_mutex); - - struct usb_lcd { struct usb_device *udev; /* init: probe_lcd */ struct usb_interface *interface; /* the interface for @@ -57,6 +54,8 @@ struct usb_lcd { using up all RAM */ struct usb_anchor submitted; /* URBs to wait for before suspend */ + struct rw_semaphore io_rwsem; + unsigned long disconnected:1; }; #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) @@ -81,40 +80,29 @@ static int lcd_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor, r; - mutex_lock(&lcd_mutex); subminor = iminor(inode); interface = usb_find_interface(&lcd_driver, subminor); if (!interface) { - mutex_unlock(&lcd_mutex); - printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n", + pr_err("USBLCD: %s - error, can't find device for minor %d\n", __func__, subminor); return -ENODEV; } - mutex_lock(&open_disc_mutex); dev = usb_get_intfdata(interface); - if (!dev) { - mutex_unlock(&open_disc_mutex); - mutex_unlock(&lcd_mutex); - return -ENODEV; - } /* increment our usage count for the device */ kref_get(&dev->kref); - mutex_unlock(&open_disc_mutex); /* grab a power reference */ r = usb_autopm_get_interface(interface); if (r < 0) { kref_put(&dev->kref, lcd_delete); - mutex_unlock(&lcd_mutex); return r; } /* save our object in the file's private structure */ file->private_data = dev; - mutex_unlock(&lcd_mutex); return 0; } @@ -142,6 +130,13 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, dev = file->private_data; + down_read(&dev->io_rwsem); + + if (dev->disconnected) { + retval = -ENODEV; + goto out_up_io; + } + /* do a blocking bulk read to get data from the device */ retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, @@ -158,6 +153,9 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, retval = bytes_read; } +out_up_io: + up_read(&dev->io_rwsem); + return retval; } @@ -173,14 +171,12 @@ static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case IOCTL_GET_HARD_VERSION: - mutex_lock(&lcd_mutex); bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); sprintf(buf, "%1d%1d.%1d%1d", (bcdDevice & 0xF000)>>12, (bcdDevice & 0xF00)>>8, (bcdDevice & 0xF0)>>4, (bcdDevice & 0xF)); - mutex_unlock(&lcd_mutex); if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0) return -EFAULT; break; @@ -237,11 +233,18 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, if (r < 0) return -EINTR; + down_read(&dev->io_rwsem); + + if (dev->disconnected) { + retval = -ENODEV; + goto err_up_io; + } + /* create a urb, and a buffer for it, and copy the data to the urb */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; - goto err_no_buf; + goto err_up_io; } buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, @@ -278,6 +281,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, the USB core will eventually free it entirely */ usb_free_urb(urb); + up_read(&dev->io_rwsem); exit: return count; error_unanchor: @@ -285,7 +289,8 @@ error_unanchor: error: usb_free_coherent(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); -err_no_buf: +err_up_io: + up_read(&dev->io_rwsem); up(&dev->limit_sem); return retval; } @@ -325,6 +330,7 @@ static int lcd_probe(struct usb_interface *interface, kref_init(&dev->kref); sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); + init_rwsem(&dev->io_rwsem); init_usb_anchor(&dev->submitted); dev->udev = usb_get_dev(interface_to_usbdev(interface)); @@ -365,7 +371,6 @@ static int lcd_probe(struct usb_interface *interface, /* something prevented us from registering this driver */ dev_err(&interface->dev, "Not able to get a minor for this device.\n"); - usb_set_intfdata(interface, NULL); goto error; } @@ -411,17 +416,18 @@ static int lcd_resume(struct usb_interface *intf) static void lcd_disconnect(struct usb_interface *interface) { - struct usb_lcd *dev; + struct usb_lcd *dev = usb_get_intfdata(interface); int minor = interface->minor; - mutex_lock(&open_disc_mutex); - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - mutex_unlock(&open_disc_mutex); - /* give back our minor */ usb_deregister_dev(interface, &lcd_class); + down_write(&dev->io_rwsem); + dev->disconnected = 1; + up_write(&dev->io_rwsem); + + usb_kill_anchored_urbs(&dev->submitted); + /* decrement our usage count */ kref_put(&dev->kref, lcd_delete); diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 6715a128e6c8..be0505b8b5d4 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -60,6 +60,7 @@ struct usb_yurex { struct kref kref; struct mutex io_mutex; + unsigned long disconnected:1; struct fasync_struct *async_queue; wait_queue_head_t waitq; @@ -107,6 +108,7 @@ static void yurex_delete(struct kref *kref) dev->int_buffer, dev->urb->transfer_dma); usb_free_urb(dev->urb); } + usb_put_intf(dev->interface); usb_put_dev(dev->udev); kfree(dev); } @@ -132,6 +134,7 @@ static void yurex_interrupt(struct urb *urb) switch (status) { case 0: /*success*/ break; + /* The device is terminated or messed up, give up */ case -EOVERFLOW: dev_err(&dev->interface->dev, "%s - overflow with length %d, actual length is %d\n", @@ -140,12 +143,13 @@ static void yurex_interrupt(struct urb *urb) case -ENOENT: case -ESHUTDOWN: case -EILSEQ: - /* The device is terminated, clean up */ + case -EPROTO: + case -ETIME: return; default: dev_err(&dev->interface->dev, "%s - unknown status received: %d\n", __func__, status); - goto exit; + return; } /* handle received message */ @@ -177,7 +181,6 @@ static void yurex_interrupt(struct urb *urb) break; } -exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); if (retval) { dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n", @@ -204,7 +207,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ init_waitqueue_head(&dev->waitq); dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; + dev->interface = usb_get_intf(interface); /* set up the endpoint information */ iface_desc = interface->cur_altsetting; @@ -315,8 +318,9 @@ static void yurex_disconnect(struct usb_interface *interface) /* prevent more I/O from starting */ usb_poison_urb(dev->urb); + usb_poison_urb(dev->cntl_urb); mutex_lock(&dev->io_mutex); - dev->interface = NULL; + dev->disconnected = 1; mutex_unlock(&dev->io_mutex); /* wakeup waiters */ @@ -404,7 +408,7 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count, dev = file->private_data; mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* already disconnected */ + if (dev->disconnected) { /* already disconnected */ mutex_unlock(&dev->io_mutex); return -ENODEV; } @@ -439,7 +443,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, goto error; mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* already disconnected */ + if (dev->disconnected) { /* already disconnected */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto error; |