From 1011b326b1e7ab86a480c99b4718d16e6d9f1d11 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 27 Oct 2007 03:06:47 +0200 Subject: USB: fix USB_OHCI_HCD_SSB dependencies This patch fixes a bug introduced by commit b22817b3c81cdb18ffe3d2debfee968731a8b5f4. Signed-off-by: Adrian Bunk Cc: Ingo Molnar Cc: Michael Buesch Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 177e78ed241..49a91c5ee51 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI config USB_OHCI_HCD_SSB bool "OHCI support for Broadcom SSB OHCI core" - depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL default n ---help--- Support for the Sonics Silicon Backplane (SSB) attached -- cgit v1.2.3 From 9cfbba73118e45d935577389976f0d6af1a8e58b Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 26 Oct 2007 13:42:18 -0700 Subject: USB: omap_udc build fix This fixes some build errors ... unclear how this got past earlier tests. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/omap_udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 87c4f50dfb6..d377154658b 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1241,14 +1241,14 @@ static void pullup_enable(struct omap_udc *udc) udc->gadget.dev.parent->power.power_state = PMSG_ON; udc->gadget.dev.power.power_state = PMSG_ON; UDC_SYSCON1_REG |= UDC_PULLUP_EN; - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG |= OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; } static void pullup_disable(struct omap_udc *udc) { - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG &= ~OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; @@ -1386,7 +1386,7 @@ static void update_otg(struct omap_udc *udc) { u16 devstat; - if (!gadget_is_otg(udc->gadget)) + if (!gadget_is_otg(&udc->gadget)) return; if (OTG_CTRL_REG & OTG_ID) -- cgit v1.2.3 From 9e3285dba5cac12d656da66fd7d420ff1bc0ecc0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Nov 2007 16:45:46 +0900 Subject: USB: pl2303: add support for Corega CG-USBRS232R pl2303: add support for Corega CG-USBRS232R This patch adds support for Corega CG-USBRS232R Serial Adapters. Signed-off-by: Magnus Damm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2cd3f1d4b68..cf8add91de0 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -86,6 +86,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, + { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index ed603e3decd..d31f5d29998 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -104,3 +104,6 @@ #define WS002IN_VENDOR_ID 0x11f6 #define WS002IN_PRODUCT_ID 0x2001 +/* Corega CG-USBRS232R Serial Adapter */ +#define COREGA_VENDOR_ID 0x07aa +#define COREGA_PRODUCT_ID 0x002a -- cgit v1.2.3 From f09e495df27d80ae77005ddb2e93df18ec24d04a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Oct 2007 16:29:02 -0400 Subject: usb-storage: always set the allow_restart flag This patch (as1000) sets the SCSI allow_restart flag for USB disk devices. In theory this should never hurt, and there definitely are devices out there (such as the Seagate 250-GB external drive) which need the flag to be set. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 1ba19eaa197..836a34ae6ec 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -177,6 +177,10 @@ static int slave_configure(struct scsi_device *sdev) * is an occasional series of retries that will all fail. */ sdev->retry_hwerror = 1; + /* USB disks should allow restart. Some drives spin down + * automatically, requiring a START-STOP UNIT command. */ + sdev->allow_restart = 1; + } else { /* Non-disk-type devices don't need to blacklist any pages -- cgit v1.2.3 From 2e2c5eea95cfe4f36d708e6f124d9ac050b19fa1 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Fri, 26 Oct 2007 23:54:35 +0200 Subject: USB: Fix priority mistakes in drivers/usb/core/hub.c Fixes priority mistakes similar to '!x & y' Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 036c3dea855..13b326a1337 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -335,7 +335,7 @@ static void kick_khubd(struct usb_hub *hub) to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; spin_lock_irqsave(&hub_event_lock, flags); - if (!hub->disconnected & list_empty(&hub->event_list)) { + if (!hub->disconnected && list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); wake_up(&khubd_wait); } -- cgit v1.2.3 From 7ced46c3ad1dfaaabf9ec6c98cbb0a48e080fb11 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Sat, 27 Oct 2007 03:36:37 +0200 Subject: USB: free memory when writing fails in usb/serial/mos7840.c Free buffer when writing ZLP_REG5 failed Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index a5ced7e08cb..c29c9127113 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2711,7 +2711,7 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); if (status < 0) { dbg("Writing ZLP_REG5 failed status-0x%x\n", status); - return -1; + goto error; } else dbg("ZLP_REG5 Writing success status%d\n", status); -- cgit v1.2.3 From ed206ec9ab398e1c3756ff0eb9507db1d009e65f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 28 Oct 2007 08:21:59 +0100 Subject: USB: fix usbled disconnect read race #2 usbled has a race where show methods for attributes in sysfs can follow a NULL pointer during disconnect. The correct ordering fixes it. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbled.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 49c5c5c4c43..06cb71942dc 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -144,12 +144,14 @@ static void led_disconnect(struct usb_interface *interface) struct usb_led *dev; dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); device_remove_file(&interface->dev, &dev_attr_blue); device_remove_file(&interface->dev, &dev_attr_red); device_remove_file(&interface->dev, &dev_attr_green); + /* first remove the files, then set the pointer to NULL */ + usb_set_intfdata (interface, NULL); + usb_put_dev(dev->udev); kfree(dev); -- cgit v1.2.3 From bfaeafcfc2242277e31cc1cfae687afaac0cd9ec Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 28 Oct 2007 13:24:16 +0100 Subject: usbserial: fix inconsistent lock state In commit acd2a847e7fee7df11817f67dba75a2802793e5d usb_serial_generic_write() disables interrupts when taking &port->lock which is also taken in usb_serial_generic_read_bulk_callback() resulting in an inconsistent lock state due to the latter not disabling interrupts on the local cpu. Fix that by disabling interrupts in the latter call site also. Signed-off-by: Borislav Petkov Acked-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 9eb4a65ee4d..d41531139c5 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -327,6 +327,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) struct usb_serial_port *port = (struct usb_serial_port *)urb->context; unsigned char *data = urb->transfer_buffer; int status = urb->status; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -339,11 +340,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); /* Throttle the device if requested by tty */ - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); if (!(port->throttled = port->throttle_req)) /* Handle data and continue reading from device */ flush_and_resubmit_read_urb(port); - spin_unlock(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); -- cgit v1.2.3 From bc59462b80c694670fbb5d0bb1a8450ffc353080 Mon Sep 17 00:00:00 2001 From: Phil Endecott Date: Mon, 29 Oct 2007 20:40:30 +0000 Subject: USB: Fix signr comment in usbdevice_fs.h This trivial documentation patch corrects a comment in usbdevice_fs.h; it previously suggested that the signal would only be sent on error, but I am told that it is sent on both successful and unsuccessful completion, and that zero indicates that no signal should be sent. Signed-off-by: Phil Endecott Signed-off-by: Greg Kroah-Hartman --- include/linux/usbdevice_fs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 342dd5a7e8b..8ca5a7fbc9e 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -102,7 +102,8 @@ struct usbdevfs_urb { int start_frame; int number_of_packets; int error_count; - unsigned int signr; /* signal to be sent on error, -1 if none should be sent */ + unsigned int signr; /* signal to be sent on completion, + or 0 if none should be sent. */ void *usercontext; struct usbdevfs_iso_packet_desc iso_frame_desc[0]; }; -- cgit v1.2.3 From 3c886c50486cfbef2a2382b99bf4083a465c970a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 16 Nov 2007 11:58:15 -0500 Subject: USB: power-management documenation update This patch (as1014) was partly written by Tilman Schmidt. It clarifies the USB power-management documentation by explaining that when a disconnect occurs, a suspend method call might not be followed by either a resume or a reset_resume call. Signed-off-by: Alan Stern Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/power-management.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index 97842deec47..b2fc4d4a991 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -278,6 +278,14 @@ optional. The methods' jobs are quite simple: (although the interfaces will be in the same altsettings as before the suspend). +If the device is disconnected or powered down while it is suspended, +the disconnect method will be called instead of the resume or +reset_resume method. This is also quite likely to happen when +waking up from hibernation, as many systems do not maintain suspend +current to the USB host controllers during hibernation. (It's +possible to work around the hibernation-forces-disconnect problem by +using the USB Persist facility.) + The reset_resume method is used by the USB Persist facility (see Documentation/usb/persist.txt) and it can also be used under certain circumstances when CONFIG_USB_PERSIST is not enabled. Currently, if a -- cgit v1.2.3 From f08812d5eb8f8cd1a5bd5f5c26a96eb93d97ab69 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Wed, 31 Oct 2007 15:59:30 -0700 Subject: USB: FIx locks and urb->status in adutux (updated) Two main issues fixed here are: - An improper use of in-struct lock to protect an open count - Use of urb status for -EINPROGRESS Also, along the way: - Change usb_unlink_urb to usb_kill_urb. Apparently there's no need to use usb_unlink_urb whatsoever in this driver, and the old use of usb_kill_urb was outright racy (it unlinked and immediately freed). - Fix indentation in adu_write. Looks like it was damaged by a script. - Vitaly wants -EBUSY on multiply opens. - bInterval was taken from a wrong endpoint. Signed-off-by: Pete Zaitcev Signed-off-by: Vitaliy Ivanov Tested-by: Vitaliy Ivanov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 262 ++++++++++++++++++++++++---------------------- 1 file changed, 139 insertions(+), 123 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index c567aa7a41e..5a2c44e4c1f 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -79,12 +79,22 @@ MODULE_DEVICE_TABLE(usb, device_table); #define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */ +/* + * The locking scheme is a vanilla 3-lock: + * adu_device.buflock: A spinlock, covers what IRQs touch. + * adutux_mutex: A Static lock to cover open_count. It would also cover + * any globals, but we don't have them in 2.6. + * adu_device.mtx: A mutex to hold across sleepers like copy_from_user. + * It covers all of adu_device, except the open_count + * and what .buflock covers. + */ + /* Structure to hold all of our device specific stuff */ struct adu_device { - struct mutex mtx; /* locks this structure */ + struct mutex mtx; struct usb_device* udev; /* save off the usb device pointer */ struct usb_interface* interface; - unsigned char minor; /* the starting minor number for this device */ + unsigned int minor; /* the starting minor number for this device */ char serial_number[8]; int open_count; /* number of times this port has been opened */ @@ -107,8 +117,11 @@ struct adu_device { char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; struct urb* interrupt_out_urb; + int out_urb_finished; }; +static DEFINE_MUTEX(adutux_mutex); + static struct usb_driver adu_driver; static void adu_debug_data(int level, const char *function, int size, @@ -132,27 +145,31 @@ static void adu_debug_data(int level, const char *function, int size, */ static void adu_abort_transfers(struct adu_device *dev) { - dbg(2," %s : enter", __FUNCTION__); + unsigned long flags; - if (dev == NULL) { - dbg(1," %s : dev is null", __FUNCTION__); - goto exit; - } + dbg(2," %s : enter", __FUNCTION__); if (dev->udev == NULL) { dbg(1," %s : udev is null", __FUNCTION__); goto exit; } - dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state); - if (dev->udev->state == USB_STATE_NOTATTACHED) { - dbg(1," %s : udev is not attached", __FUNCTION__); - goto exit; - } - /* shutdown transfer */ - usb_unlink_urb(dev->interrupt_in_urb); - usb_unlink_urb(dev->interrupt_out_urb); + + /* XXX Anchor these instead */ + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_in_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); + + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_out_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); exit: dbg(2," %s : leave", __FUNCTION__); @@ -162,8 +179,6 @@ static void adu_delete(struct adu_device *dev) { dbg(2, "%s enter", __FUNCTION__); - adu_abort_transfers(dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -239,7 +254,10 @@ static void adu_interrupt_out_callback(struct urb *urb) goto exit; } - wake_up_interruptible(&dev->write_wait); + spin_lock(&dev->buflock); + dev->out_urb_finished = 1; + wake_up(&dev->write_wait); + spin_unlock(&dev->buflock); exit: adu_debug_data(5, __FUNCTION__, urb->actual_length, @@ -252,12 +270,17 @@ static int adu_open(struct inode *inode, struct file *file) struct adu_device *dev = NULL; struct usb_interface *interface; int subminor; - int retval = 0; + int retval; dbg(2,"%s : enter", __FUNCTION__); subminor = iminor(inode); + if ((retval = mutex_lock_interruptible(&adutux_mutex))) { + dbg(2, "%s : mutex lock failed", __FUNCTION__); + goto exit_no_lock; + } + interface = usb_find_interface(&adu_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d", @@ -267,54 +290,54 @@ static int adu_open(struct inode *inode, struct file *file) } dev = usb_get_intfdata(interface); - if (!dev) { + if (!dev || !dev->udev) { retval = -ENODEV; goto exit_no_device; } - /* lock this device */ - if ((retval = mutex_lock_interruptible(&dev->mtx))) { - dbg(2, "%s : mutex lock failed", __FUNCTION__); + /* check that nobody else is using the device */ + if (dev->open_count) { + retval = -EBUSY; goto exit_no_device; } - /* increment our usage count for the device */ ++dev->open_count; dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count); /* save device in the file's private structure */ file->private_data = dev; - if (dev->open_count == 1) { - /* initialize in direction */ - dev->read_buffer_length = 0; + /* 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; - } - mutex_unlock(&dev->mtx); + /* 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->read_urb_finished = 0; + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) + dev->read_urb_finished = 1; + /* we ignore failure */ + /* end of fixup for first read */ + + /* initialize out direction */ + dev->out_urb_finished = 1; + + retval = 0; exit_no_device: + mutex_unlock(&adutux_mutex); +exit_no_lock: dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); - return retval; } -static int adu_release_internal(struct adu_device *dev) +static void adu_release_internal(struct adu_device *dev) { - int retval = 0; - dbg(2," %s : enter", __FUNCTION__); /* decrement our usage count for the device */ @@ -326,12 +349,11 @@ static int adu_release_internal(struct adu_device *dev) } dbg(2," %s : leave", __FUNCTION__); - return retval; } static int adu_release(struct inode *inode, struct file *file) { - struct adu_device *dev = NULL; + struct adu_device *dev; int retval = 0; dbg(2," %s : enter", __FUNCTION__); @@ -343,15 +365,13 @@ static int adu_release(struct inode *inode, struct file *file) } dev = file->private_data; - if (dev == NULL) { dbg(1," %s : object is NULL", __FUNCTION__); retval = -ENODEV; goto exit; } - /* lock our device */ - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { dbg(1," %s : device not opened", __FUNCTION__); @@ -359,19 +379,15 @@ static int adu_release(struct inode *inode, struct file *file) goto exit; } + 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); + if (!dev->open_count) /* ... and we're the last user */ + adu_delete(dev); } exit: - if (dev) - mutex_unlock(&dev->mtx); + mutex_unlock(&adutux_mutex); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } @@ -393,12 +409,12 @@ 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 (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -452,7 +468,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, should_submit = 1; } else { /* even the primary was empty - we may need to do IO */ - if (dev->interrupt_in_urb->status == -EINPROGRESS) { + if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submitted already", __FUNCTION__); @@ -460,6 +476,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we must initiate input */ dbg(2," %s : initiate input", __FUNCTION__); dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, usb_rcvintpipe(dev->udev, @@ -469,15 +486,12 @@ 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_ATOMIC); - if (!retval) { - spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2," %s : submitted OK", __FUNCTION__); - } else { + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (retval) { + dev->read_urb_finished = 1; if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submit failed", __FUNCTION__); goto exit; } @@ -486,10 +500,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we wait for I/O to complete */ set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&dev->read_wait, &wait); - if (!dev->read_urb_finished) + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); timeout = schedule_timeout(COMMAND_TIMEOUT); - else + } else { + spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); + } remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { @@ -509,19 +527,23 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, retval = bytes_read; /* if the primary buffer is empty then use it */ - if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) { + spin_lock_irqsave(&dev->buflock, flags); + if (should_submit && dev->read_urb_finished) { + dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); 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); + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, + dev, + dev->interrupt_in_endpoint->bInterval); + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0) + dev->read_urb_finished = 1; /* we ignore failure */ + } else { + spin_unlock_irqrestore(&dev->buflock, flags); } exit: @@ -535,24 +557,24 @@ exit: static ssize_t adu_write(struct file *file, const __user char *buffer, size_t count, loff_t *ppos) { + DECLARE_WAITQUEUE(waita, current); struct adu_device *dev; size_t bytes_written = 0; size_t bytes_to_write; size_t buffer_size; + unsigned long flags; int retval; - int timeout = 0; dbg(2," %s : enter, count = %Zd", __FUNCTION__, count); dev = file->private_data; - /* lock this object */ retval = mutex_lock_interruptible(&dev->mtx); if (retval) goto exit_nolock; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -564,42 +586,37 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit; } - while (count > 0) { - if (dev->interrupt_out_urb->status == -EINPROGRESS) { - timeout = COMMAND_TIMEOUT; + add_wait_queue(&dev->write_wait, &waita); + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); - while (timeout > 0) { - if (signal_pending(current)) { + mutex_unlock(&dev->mtx); + if (signal_pending(current)) { dbg(1," %s : interrupted", __FUNCTION__); + set_current_state(TASK_RUNNING); retval = -EINTR; - goto exit; + goto exit_onqueue; } - mutex_unlock(&dev->mtx); - timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); + if (schedule_timeout(COMMAND_TIMEOUT) == 0) { + dbg(1, "%s - command timed out.", __FUNCTION__); + retval = -ETIMEDOUT; + goto exit_onqueue; + } + remove_wait_queue(&dev->write_wait, &waita); retval = mutex_lock_interruptible(&dev->mtx); if (retval) { retval = bytes_written ? bytes_written : retval; goto exit_nolock; } - if (timeout > 0) { - break; - } - dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout); - } - - - dbg(1," %s : final timeout: %d", __FUNCTION__, timeout); - - if (timeout == 0) { - dbg(1, "%s - command timed out.", __FUNCTION__); - retval = -ETIMEDOUT; - goto exit; - } - - dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); + dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); } else { + spin_unlock_irqrestore(&dev->buflock, flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->write_wait, &waita); dbg(4," %s : sending, count = %Zd", __FUNCTION__, count); /* write the data into interrupt_out_buffer from userspace */ @@ -622,11 +639,12 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_to_write, adu_interrupt_out_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ + dev->interrupt_out_endpoint->bInterval); dev->interrupt_out_urb->actual_length = bytes_to_write; + dev->out_urb_finished = 0; retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval < 0) { + dev->out_urb_finished = 1; err("Couldn't submit interrupt_out_urb %d", retval); goto exit; } @@ -637,16 +655,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_written += bytes_to_write; } } - - retval = bytes_written; + mutex_unlock(&dev->mtx); + return bytes_written; exit: - /* unlock the device */ mutex_unlock(&dev->mtx); exit_nolock: - dbg(2," %s : leave, return value %d", __FUNCTION__, retval); + return retval; +exit_onqueue: + remove_wait_queue(&dev->write_wait, &waita); return retval; } @@ -831,25 +850,22 @@ static void adu_disconnect(struct usb_interface *interface) dbg(2," %s : enter", __FUNCTION__); dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + mutex_lock(&dev->mtx); /* not interruptible */ + dev->udev = NULL; /* poison */ minor = dev->minor; - - /* give back our minor */ usb_deregister_dev(interface, &adu_class); - dev->minor = 0; + mutex_unlock(&dev->mtx); - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); + usb_set_intfdata(interface, NULL); /* 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) { - mutex_unlock(&dev->mtx); + if (!dev->open_count) adu_delete(dev); - } else { - dev->udev = NULL; - mutex_unlock(&dev->mtx); - } + + mutex_unlock(&adutux_mutex); dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); -- cgit v1.2.3 From 034fec2e75e97a5429512a6daf2c605a4829853d Mon Sep 17 00:00:00 2001 From: Mike Pagano Date: Thu, 1 Nov 2007 10:53:43 -0700 Subject: USB: add support for an older firmware revision for the Nikon D200 This is a resubmission of the patch to upgrade the unusual_devs.h file to support an older firmware revision of the Nikon D200. This patch includes the requested /proc/bus/usb/devices information. T: Bus=01 Lev=01 Prnt=01 Port=09 Cnt=02 Dev#= 6 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=04b0 ProdID=040f Rev= 1.00 S: Manufacturer=NIKON S: Product=NIKON DSC D200 S: SerialNumber=0000000 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 2mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Mike Pagano Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 22ab2380367..7398229c525 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -342,11 +342,11 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_FL_FIX_CAPACITY), /* Reported by Graber and Mike Pagano */ -UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200, - "NIKON", - "NIKON DSC D200", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY), +UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200, + "NIKON", + "NIKON DSC D200", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), /* Reported by Emil Larsson */ UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, -- cgit v1.2.3 From 9e3e31046fc4e994583b1197eeefb26811bc9364 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 7 Nov 2007 16:27:23 -0800 Subject: USB: fix directory references in usb/README Another one in the "ok, this is trivial to fix" list... :-) [PATCH] fix directory references in usb/README Signed-off-by: Dirk Hohndel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/README b/drivers/usb/README index 3c843412855..284f46b3e1c 100644 --- a/drivers/usb/README +++ b/drivers/usb/README @@ -39,12 +39,12 @@ first subdirectory in the list below that it fits into. image/ - This is for still image drivers, like scanners or digital cameras. -input/ - This is for any driver that uses the input subsystem, +../input/ - This is for any driver that uses the input subsystem, like keyboard, mice, touchscreens, tablets, etc. -media/ - This is for multimedia drivers, like video cameras, +../media/ - This is for multimedia drivers, like video cameras, radios, and any other drivers that talk to the v4l subsystem. -net/ - This is for network drivers. +../net/ - This is for network drivers. serial/ - This is for USB to serial drivers. storage/ - This is for USB mass-storage drivers. class/ - This is for all USB device drivers that do not fit -- cgit v1.2.3 From ddac0da4dce2e115633493725601da202359872a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 7 Nov 2007 12:59:54 -0800 Subject: USB: remove USB HUB entry from MAINTAINERS Digging through old mail, I found a note about needing to remove the separate entry for the USB HUB driver. It's not been separable from usbcore (host side!) since quite early in the 2.4 kernel series. And Johanness certainly isn't involved with it any more. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f5bd9bab7ed..bb2387fd9d2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3864,13 +3864,6 @@ L: linux-usb-devel@lists.sourceforge.net T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained -USB HUB DRIVER -P: Johannes Erdfelt -M: johannes@erdfelt.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -S: Maintained - USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee -- cgit v1.2.3 From 6372594ac1779261926f2f2c4ef5e79936e4faef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Nov 2007 15:16:59 -0700 Subject: USB: mailing lists have changed The linux-usb-devel and linux-usb-users are now hosted in the same list at vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 94 +++++++++++++++++++++++-------------------------------------- 1 file changed, 35 insertions(+), 59 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index bb2387fd9d2..6b30cb3eac7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -323,8 +323,7 @@ S: Maintained ALCATEL SPEEDTOUCH USB DRIVER P: Duncan Sands M: duncan.sands@free.fr -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/SpeedTouch/ S: Maintained @@ -1043,7 +1042,7 @@ S: Maintained CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER P: Lennert Buytenhek M: kernel@wantstofly.org -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER @@ -1552,7 +1551,7 @@ S: Maintained FREESCALE HIGHSPEED USB DEVICE DRIVER P: Li Yang M: leoli@freescale.com -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained @@ -3810,22 +3809,20 @@ S: Maintained USB ACM DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB BLOCK DRIVER (UB ub) P: Pete Zaitcev M: zaitcev@redhat.com L: linux-kernel@vger.kernel.org -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB CDC ETHERNET DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ @@ -3839,13 +3836,13 @@ S: Maintained USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Odd Fixes USB ET61X[12]51 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -3853,34 +3850,33 @@ S: Maintained USB GADGET/PERIPHERAL SUBSYSTEM P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) P: Jiri Kosina M: jkosina@suse.cz -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net -L: linux-usb-users@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ @@ -3888,28 +3884,26 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ USB OHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Odd Fixes USB OPTION-CARD DRIVER P: Matthias Urlichs M: smurf@smurf.noris.de -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB OV511 DRIVER P: Mark McClelland M: mmcclell@bigfoot.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained USB PEGASUS DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -3917,14 +3911,13 @@ S: Maintained USB PRINTER DRIVER (usblp) P: Pete Zaitcev M: zaitcev@redhat.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB RTL8150 DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -3932,8 +3925,7 @@ S: Maintained USB SE401 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained @@ -3947,72 +3939,59 @@ USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers M: pberger@brimson.com M: alborchers@steinerpoint.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL DRIVER P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse M: wgreathouse@smva.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL CYPRESS M8 DRIVER P: Lonnie Mendez M: dignome@gmail.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i W: http://firstlight.net/cvs -USB SERIAL CYBERJACK PINPAD/E-COM DRIVER -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -S: Maintained - USB AUERSWALD DRIVER P: Wolfgang Muees M: wolfgang@iksw-muees.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL KEYSPAN DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained USB SERIAL WHITEHEAT DRIVER P: Support Department M: support@connecttech.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4020,8 +3999,7 @@ S: Maintained USB SUBSYSTEM P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported @@ -4029,8 +4007,7 @@ S: Supported USB UHCI DRIVER P: Alan Stern M: stern@rowland.harvard.edu -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB "USBNET" DRIVER FRAMEWORK @@ -4043,7 +4020,7 @@ S: Maintained USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4051,7 +4028,7 @@ S: Maintained USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4059,15 +4036,14 @@ S: Maintained USB ZD1201 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained USB ZR364XX DRIVER P: Antoine Jacquet M: royale@zerezo.com -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://royale.zerezo.com/zr364xx/ S: Maintained -- cgit v1.2.3 From ddc1fd6ac1f3ad3275e19451fb07d2eff249161c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 21 Nov 2007 15:13:10 -0800 Subject: USB HCD: avoid duplicate local_irq_disable() Arnd Bergmann wrote: usb_hcd_flush_endpoint() has a retry loop that starts with a spin_lock_irq(), but only gives up the spinlock, not the irq_disable before jumping to the rescan label. Alan Stern: I agree with your sentiment, but it would be better to solve this problem without using local_irq_disable(). Signed-off-by: Alan Stern Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fea8256a18d..d5ed3fa9e30 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, hcd = bus_to_hcd(udev->bus); /* No more submits can occur */ -rescan: spin_lock_irq(&hcd_urb_list_lock); +rescan: list_for_each_entry (urb, &ep->urb_list, urb_list) { int is_in; @@ -1345,6 +1345,7 @@ rescan: usb_put_urb (urb); /* list contents may have changed */ + spin_lock(&hcd_urb_list_lock); goto rescan; } spin_unlock_irq(&hcd_urb_list_lock); -- cgit v1.2.3 From 5fdcd0396be443e36a4e2128f51818acca570ee7 Mon Sep 17 00:00:00 2001 From: "agilmore@wirelessbeehive.com" Date: Tue, 20 Nov 2007 13:39:03 -0700 Subject: USB: sierra: new product id Per the maintainer of the usbserial/sierra.c driver, the patch below adds a new id to the list of supported cards for the sierra driver. Tested and working for me on Fedora 8, kernel 2.6.23 and on the more recent sierra.c available in http://www.sierrawireless.com/resources/support/Software/Linux/v.1.2.6b(kernel2.6.21).zip Hardware is a MiniPCI card in a Lenovo T61p. Signed-off-by: Andrew Gilmore Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 833f6e1e372..605ebccdcd5 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -136,6 +136,8 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ -- cgit v1.2.3 From 7e61559f6199bb387037abfc7d10a893973561fc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 6 Nov 2007 11:43:42 -0500 Subject: USB: keep track of whether interface sysfs files exist This patch (as1009) solves the problem of multiple registrations for USB sysfs files in a more satisfying way than the existing code. It simply adds a flag to keep track of whether or not the files have been created; that way the files can be created or removed as needed. Signed-off-by: Alan Stern --- drivers/usb/core/message.c | 12 ++---------- drivers/usb/core/sysfs.c | 6 ++++++ include/linux/usb.h | 1 + 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 316a746e008..40fd39de5bf 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) struct usb_host_interface *alt; int ret; int manual = 0; - int changed; if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; @@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) */ /* prevent submissions using previous endpoint settings */ - changed = (iface->cur_altsetting != alt); - if (changed && device_is_registered(&iface->dev)) + if (iface->cur_altsetting != alt && device_is_registered(&iface->dev)) usb_remove_sysfs_intf_files(iface); usb_disable_interface(dev, iface); @@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * (Likewise, EP0 never "halts" on well designed devices.) */ usb_enable_interface(dev, iface); - if (changed && device_is_registered(&iface->dev)) + if (device_is_registered(&iface->dev)) usb_create_sysfs_intf_files(iface); return 0; @@ -1641,12 +1639,6 @@ free_interfaces: intf->dev.bus_id, ret); continue; } - - /* The driver's probe method can call usb_set_interface(), - * which would mean the interface's sysfs files are already - * created. Just in case, we'll remove them first. - */ - usb_remove_sysfs_intf_files(intf); usb_create_sysfs_intf_files(intf); } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index b04afd06e50..32bd130b1ee 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) struct usb_host_interface *alt = intf->cur_altsetting; int retval; + if (intf->sysfs_files_created) + return 0; retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); if (retval) return retval; @@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (intf->intf_assoc) retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); usb_create_intf_ep_files(intf, udev); + intf->sysfs_files_created = 1; return 0; } @@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) { struct device *dev = &intf->dev; + if (!intf->sysfs_files_created) + return; usb_remove_intf_ep_files(intf); device_remove_file(dev, &dev_attr_interface); sysfs_remove_group(&dev->kobj, &intf_attr_grp); sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); + intf->sysfs_files_created = 0; } diff --git a/include/linux/usb.h b/include/linux/usb.h index c5c8f169d3c..416ee7617d9 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -157,6 +157,7 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ unsigned is_active:1; /* the interface is not suspended */ + unsigned sysfs_files_created:1; /* the sysfs attributes exist */ unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ struct device dev; /* interface specific device info */ -- cgit v1.2.3 From 4a9bee8256a2dec26290a3bfff86ab86b8992547 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 6 Nov 2007 15:01:52 -0500 Subject: USB: uevent environment key fix This patch (as1010) was written by both Kay Sievers and me. It solves the problem of duplicated keys in USB uevent structures by refactoring the uevent subroutines, taking advantage of the way the hotplug core calls uevent handlers for the device's bus and for the device's type. Keys needed for both USB-device and USB-interface events are added in usb_uevent(), which is the bus handler. Keys appropriate only for USB-device or USB-interface events are added in usb_dev_uevent() or usb_if_uevent() respectively, the type handlers. In addition, unnecessary tests for NULL pointers are removed as are duplicated debugging log statements. Signed-off-by: Alan Stern Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 11 ----------- drivers/usb/core/message.c | 24 ------------------------ drivers/usb/core/usb.c | 25 +++++++++++++++++++++++++ 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8586817698a..c51f8e9312e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; - if (!dev) - return -ENODEV; - /* driver is often null here; dev_dbg() would oops */ pr_debug ("usb %s: uevent\n", dev->bus_id); @@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(env, "BUSNUM=%03d", - usb_dev->bus->busnum)) - return -ENOMEM; - - if (add_uevent_var(env, "DEVNUM=%03d", - usb_dev->devnum)) - return -ENOMEM; - return 0; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 40fd39de5bf..fcd40ecbeec 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1346,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) struct usb_interface *intf; struct usb_host_interface *alt; - if (!dev) - return -ENODEV; - - /* driver is often null here; dev_dbg() would oops */ - pr_debug ("usb %s: uevent\n", dev->bus_id); - intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; -#ifdef CONFIG_USB_DEVICEFS - if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum)) - return -ENOMEM; -#endif - - if (add_uevent_var(env, "PRODUCT=%x/%x/%x", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice))) - return -ENOMEM; - - if (add_uevent_var(env, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol)) - return -ENOMEM; - if (add_uevent_var(env, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index c4a6f1095b8..8f142370103 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev) kfree(udev); } +#ifdef CONFIG_HOTPLUG +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct usb_device *usb_dev; + + usb_dev = to_usb_device(dev); + + if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) + return -ENOMEM; + + if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) + return -ENOMEM; + + return 0; +} + +#else + +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + return -ENODEV; +} +#endif /* CONFIG_HOTPLUG */ + struct device_type usb_device_type = { .name = "usb_device", .release = usb_release_dev, + .uevent = usb_dev_uevent, }; #ifdef CONFIG_PM -- cgit v1.2.3 From 5cf1973a44bd298e3cfce6f6af8faa8c9d0a6d55 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 12 Nov 2007 14:08:43 +0100 Subject: USB: make the microtek driver and HAL cooperate to make HAL like the microtek driver's devices the parent must be correctly set. Signed-off-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/microtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 91e999c9f68..bc207e3c21f 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -819,7 +819,7 @@ static int mts_usb_probe(struct usb_interface *intf, goto out_kfree2; new_desc->host->hostdata[0] = (unsigned long)new_desc; - if (scsi_add_host(new_desc->host, NULL)) { + if (scsi_add_host(new_desc->host, &dev->dev)) { err_retval = -EIO; goto out_host_put; } -- cgit v1.2.3 From 1cb52658b4f5b10a9e91f8e1c21ca2bcc1b9a3ca Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 13 Nov 2007 16:22:30 -0800 Subject: USB: fix up EHCI startup synchronization A recent patch added software synchronization during EHCI startup, so ports aren't switched away from the companion controllers after resets have started. This patch adds a short delay letting hardware finish that port switching before any new resets begin ... so both ends of that hardware race window are closed. Signed-off-by: David Brownell Cc: Dave Miller Cc: Dely Sy Cc: stable Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c1514442883..5f2d74ed5ad 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -575,12 +575,15 @@ static int ehci_run (struct usb_hcd *hcd) * from the companions to the EHCI controller. If any of the * companions are in the middle of a port reset at the time, it * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. + * guarantees that no resets are in progress. After we set CF, + * a short delay lets the hardware catch up; new resets shouldn't + * be started before the port switching actions could complete. */ down_write(&ehci_cf_port_reset_rwsem); hcd->state = HC_STATE_RUNNING; ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + msleep(5); up_write(&ehci_cf_port_reset_rwsem); temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); -- cgit v1.2.3 From f1e8de0dbb9ee30cd6eb9c510249847d28443cb1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 26 Nov 2007 10:23:05 -0500 Subject: USB: usb-storage: unusual_devs entry for JetFlash TS1GJF2A This patch (as1018) adds an unusual_devs entry for the JetFlash TS1GJF2A. This device doesn't like read requests for more than 188 sectors. Setting max_sectors down to 64 is overkill, but at least it will work without errors. For the torturous debugging history, see this thread: http://marc.info/?t=118745764700005&r=1&w=2 Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 7398229c525..2c27721bd25 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -731,6 +731,13 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif +/* Reported by RTE */ +UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, + "JetFlash", + "TS1GJF2A/120", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Fabrizio Fellini */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", -- cgit v1.2.3 From 899d566a6e7533cb5ad613a656c7f53a2b88abcd Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Nov 2007 22:28:13 +0000 Subject: USB: s3c2410 gadget: Header move fixups Fixup the fallout from the arch moves earlier in the kernel series. Signed-off-by: Ben Dooks Acked-by: David Brownell --- drivers/usb/gadget/s3c2410_udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index e3e90f8a75e..9780f86ae8e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -52,10 +52,10 @@ #include #include -#include #include -#include -#include + +#include +#include #include -- cgit v1.2.3 From 8802bca4feed9e60d22a91cc5ccb1c4a1d8e3d71 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Nov 2007 22:28:14 +0000 Subject: USB: s3c2410 gadget: allow sharing of vbus irq If another driver wants to claim the vbus pin, say to notify the user of an connect/disconnect then allow the IRQ to be shared by specifiying IRQ_SHARED in the flags. Signed-off-by: Ben Dooks Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/s3c2410_udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 9780f86ae8e..5acaddabbe8 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1872,9 +1872,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (udc_info && udc_info->vbus_pin > 0) { irq = s3c2410_gpio_getirq(udc_info->vbus_pin); retval = request_irq(irq, s3c2410_udc_vbus_irq, - IRQF_DISABLED | IRQF_TRIGGER_RISING - | IRQF_TRIGGER_FALLING, - gadget_name, udc); + IRQF_DISABLED | IRQF_TRIGGER_RISING + | IRQF_TRIGGER_FALLING | IRQF_SHARED, + gadget_name, udc); if (retval != 0) { dev_err(dev, "can't get vbus irq %i, err %d\n", -- cgit v1.2.3 From 5f629ad7e5f9b99c6d025bf199d402734bd72d0f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Nov 2007 22:28:15 +0000 Subject: USB: s3c2410 gadget: ensure vbus pin in input mode during read Some CPUs in the S3C24XX series do not support readback of the value of a pin when the pin has been configured to an IRQ. Signed-off-by: Ben Dooks Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/s3c2410_udc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 5acaddabbe8..4ce050c3d13 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1511,7 +1511,11 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) unsigned int value; dprintk(DEBUG_NORMAL, "%s()\n", __func__); + + /* some cpus cannot read from an line configured to IRQ! */ + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT); value = s3c2410_gpio_getpin(udc_info->vbus_pin); + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2); if (udc_info->vbus_pin_inverted) value = !value; -- cgit v1.2.3