aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2008-04-30 11:42:38 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-30 11:42:38 -0700
commiteace7ec517d06ce69c55b1c8244bd8566471fe6e (patch)
tree22d9189c706ffe286c3989a13bc8fd78a65d225c /usb
parent75e56de690c85a25dded4577f2e0a8363f582588 (diff)
downloadpatches-eace7ec517d06ce69c55b1c8244bd8566471fe6e.tar.gz
more patches added
Diffstat (limited to 'usb')
-rw-r--r--usb/ti_usb-kick-firmware-into-user-space.patch227
-rw-r--r--usb/usb-add-new-routine-for-checking-port-resume-type.patch156
-rw-r--r--usb/usb-add-usb_dev_reset_delayed.patch2
-rw-r--r--usb/usb-combine-hub_activate-and-hub_restart.patch130
-rw-r--r--usb/usb-combine-hub_quiesce-and-hub_stop.patch132
-rw-r--r--usb/usb-create-attributes-before-sending-uevent.patch2
-rw-r--r--usb/usb-debounce-before-unregistering.patch93
-rw-r--r--usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch61
-rw-r--r--usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch59
-rw-r--r--usb/usb-optimize-port-debouncing-during-hub-activation.patch99
-rw-r--r--usb/usb-simplify-hub_restart-logic.patch250
-rw-r--r--usb/usb-try-to-salvage-lost-power-sessions.patch181
-rw-r--r--usb/usb_serial-some-coding-style-fixes.patch512
13 files changed, 1902 insertions, 2 deletions
diff --git a/usb/ti_usb-kick-firmware-into-user-space.patch b/usb/ti_usb-kick-firmware-into-user-space.patch
new file mode 100644
index 00000000000000..f18f5705ae9792
--- /dev/null
+++ b/usb/ti_usb-kick-firmware-into-user-space.patch
@@ -0,0 +1,227 @@
+From alan@lxorguk.ukuu.org.uk Wed Apr 30 11:30:07 2008
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Date: Tue, 29 Apr 2008 14:38:22 +0100
+Subject: ti_usb: kick firmware into user space
+To: greg@kroah.com, linux-usb@vger.kernel.org
+Message-ID: <20080429143822.19af46a5@core>
+
+
+The patch leaves a compile it in option as distributions need time to
+update to this, and hopefully to doing the same over time with more
+serial drivers. Firmware belongs on disk (cheap) not in kernel non paged
+memory.
+
+Signed-off-by: Alan Cox <alan@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/Kconfig | 8 ++
+ drivers/usb/serial/ti_fw_3410.h | 4 +
+ drivers/usb/serial/ti_fw_5052.h | 5 +
+ drivers/usb/serial/ti_usb_3410_5052.c | 108 ++++++++++++++++++++++------------
+ 4 files changed, 88 insertions(+), 37 deletions(-)
+
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -514,6 +514,14 @@ config USB_SERIAL_TI
+ To compile this driver as a module, choose M here: the
+ module will be called ti_usb_3410_5052.
+
++config USB_SERIAL_TI_FIRMWARE
++ bool "USB TI 3410/5052 Firmware"
++ depends on USB_SERIAL_TI
++ help
++ say Y to include the firmware into the kernel for compatibility
++ with older setups. Say N if you have the firmware files installed
++ in /etc/firmware.
++
+ config USB_SERIAL_CYBERJACK
+ tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader"
+ ---help---
+--- a/drivers/usb/serial/ti_fw_3410.h
++++ b/drivers/usb/serial/ti_fw_3410.h
+@@ -882,4 +882,8 @@ static unsigned char ti_fw_3410[] = {
+ 0x00,0x00,
+ };
+
++static struct firmware fw_3410 = {
++ sizeof(ti_fw_3410),
++ ti_fw_3410
++};
+ #endif /* ifndef _TI_FW_3410_H_ */
+--- a/drivers/usb/serial/ti_fw_5052.h
++++ b/drivers/usb/serial/ti_fw_5052.h
+@@ -882,4 +882,9 @@ static unsigned char ti_fw_5052[] = {
+ 0x00,
+ };
+
++static struct firmware fw_5052 = {
++ sizeof(ti_fw_5052),
++ ti_fw_5052
++};
++
+ #endif /* ifndef _TI_FW_5052_H_ */
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -70,6 +70,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
++#include <linux/firmware.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/tty.h>
+@@ -86,9 +87,14 @@
+ #include <linux/usb/serial.h>
+
+ #include "ti_usb_3410_5052.h"
++
++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE
++/* Keep compatibility option for a while so we don't break systems
++ as we kick the firmware out into user space. In time this will
++ go away */
+ #include "ti_fw_3410.h" /* firmware image for 3410 */
+ #include "ti_fw_5052.h" /* firmware image for 5052 */
+-
++#endif
+
+ /* Defines */
+
+@@ -194,8 +200,7 @@ static int ti_command_in_sync(struct ti_
+ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ __u8 mask, __u8 byte);
+
+-static int ti_download_firmware(struct ti_device *tdev,
+- unsigned char *firmware, unsigned int firmware_size);
++static int ti_download_firmware(struct ti_device *tdev, int type);
+
+ /* circular buffer */
+ static struct circ_buf *ti_buf_alloc(void);
+@@ -429,13 +434,10 @@ static int ti_startup(struct usb_serial
+
+ /* if we have only 1 configuration, download firmware */
+ if (dev->descriptor.bNumConfigurations == 1) {
+-
+ if (tdev->td_is_3410)
+- status = ti_download_firmware(tdev, ti_fw_3410,
+- sizeof(ti_fw_3410));
++ status = ti_download_firmware(tdev, 3410);
+ else
+- status = ti_download_firmware(tdev, ti_fw_5052,
+- sizeof(ti_fw_5052));
++ status = ti_download_firmware(tdev, 5052);
+ if (status)
+ goto free_tdev;
+
+@@ -1656,50 +1658,82 @@ static int ti_write_byte(struct ti_devic
+ return status;
+ }
+
+-
+-static int ti_download_firmware(struct ti_device *tdev,
+- unsigned char *firmware, unsigned int firmware_size)
++static int ti_do_download(struct usb_device *dev, int pipe,
++ u8 *buffer, int size)
+ {
+- int status = 0;
+- int buffer_size;
+ int pos;
+- int len;
++ u8 cs = 0;
+ int done;
+- __u8 cs = 0;
+- __u8 *buffer;
+- struct usb_device *dev = tdev->td_serial->dev;
+ struct ti_firmware_header *header;
+- unsigned int pipe = usb_sndbulkpipe(dev,
+- tdev->td_serial->port[0]->bulk_out_endpointAddress);
+-
+-
+- buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+- buffer = kmalloc(buffer_size, GFP_KERNEL);
+- if (!buffer) {
+- dev_err(&dev->dev, "%s - out of memory\n", __func__);
+- return -ENOMEM;
+- }
+-
+- memcpy(buffer, firmware, firmware_size);
+- memset(buffer+firmware_size, 0xff, buffer_size-firmware_size);
+-
+- for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++)
++ int status;
++ int len;
++
++ for(pos = sizeof(struct ti_firmware_header); pos < size; pos++)
+ cs = (__u8)(cs + buffer[pos]);
+
+ header = (struct ti_firmware_header *)buffer;
+- header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
++ header->wLength = cpu_to_le16((__u16)(size
++ - sizeof(struct ti_firmware_header)));
+ header->bCheckSum = cs;
+
+ dbg("%s - downloading firmware", __func__);
+- for (pos = 0; pos < buffer_size; pos += done) {
+- len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+- status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
++ for (pos = 0; pos < size; pos += done) {
++ len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
++ status = usb_bulk_msg(dev, pipe, buffer + pos, len,
++ &done, 1000);
+ if (status)
+ break;
+ }
++ return status;
++}
++
+
+- kfree(buffer);
++static int ti_download_firmware(struct ti_device *tdev, int type)
++{
++ int status = -ENOMEM;
++ int buffer_size;
++ __u8 *buffer;
++ struct usb_device *dev = tdev->td_serial->dev;
++ unsigned int pipe = usb_sndbulkpipe(dev,
++ tdev->td_serial->port[0]->bulk_out_endpointAddress);
++ const struct firmware *fw_p;
+
++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE
++ switch (type) {
++ case 3410:
++ fw_p = &fw_3410;
++ break;
++ case 5052:
++ fw_p = &fw_5052;
++ break;
++ default:
++ return -EINVAL;
++ }
++#else
++ char buf[32];
++ sprintf(buf, "ti_usb-%d.bin", type);
++
++ if (request_firmware(&fw_p, buf, &dev->dev)) {
++ dev_err(&dev->dev, "%s - firmware not found\n", __func__);
++ return -ENOENT;
++ }
++ if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
++ dev_err(&dev->dev, "%s - firmware too large\n", __func__);
++ return -ENOENT;
++ }
++#endif
++
++ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
++ buffer = kmalloc(buffer_size, GFP_KERNEL);
++ if (buffer) {
++ memcpy(buffer, fw_p->data, fw_p->size);
++ memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
++ ti_do_download(dev, pipe, buffer, fw_p->size);
++ kfree(buffer);
++ }
++#ifdef CONFIG_USB_SERIAL_TI_FIRMWARE
++ release_firmware(fw_p);
++#endif
+ if (status) {
+ dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+ return status;
diff --git a/usb/usb-add-new-routine-for-checking-port-resume-type.patch b/usb/usb-add-new-routine-for-checking-port-resume-type.patch
new file mode 100644
index 00000000000000..ca77ec06de55eb
--- /dev/null
+++ b/usb/usb-add-new-routine-for-checking-port-resume-type.patch
@@ -0,0 +1,156 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:30:50 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:06:11 -0400 (EDT)
+Subject: USB: add new routine for checking port-resume type
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281055310.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1070) creates a new subroutine to check whether a device
+can be resumed. This code is needed even when CONFIG_USB_SUSPEND
+isn't set, because devices do suspend themselves when the root hub
+(and hence the entire bus) is suspended, and power sessions can get
+lost during a system sleep even without individual port suspends.
+
+The patch also fixes a loose end in USB-Persist reset-resume handling.
+When a low- or full-speed device is attached to an EHCI's companion
+controller, the port handoff during resume will cause the companion
+port's connect-status-change feature to be set. If that flag isn't
+cleared, the port-reset code will think it indicates that the device
+has been unplugged and the reset-resume will fail.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 90 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 63 insertions(+), 27 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1770,6 +1770,45 @@ static int hub_port_reset(struct usb_hub
+
+ #ifdef CONFIG_PM
+
++#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
++ USB_PORT_STAT_SUSPEND)
++#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
++
++/* Determine whether the device on a port is ready for a normal resume,
++ * is ready for a reset-resume, or should be disconnected.
++ */
++static int check_port_resume_type(struct usb_device *udev,
++ struct usb_hub *hub, int port1,
++ int status, unsigned portchange, unsigned portstatus)
++{
++ /* Is the device still present? */
++ if (status || (portstatus & MASK_BITS) != WANT_BITS) {
++ if (status >= 0)
++ status = -ENODEV;
++ }
++
++ /* Can't do a normal resume if the port isn't enabled */
++ else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume)
++ status = -ENODEV;
++
++ if (status) {
++ dev_dbg(hub->intfdev,
++ "port %d status %04x.%04x after resume, %d\n",
++ port1, portchange, portstatus, status);
++ } else if (udev->reset_resume) {
++
++ /* Late port handoff can set status-change bits */
++ if (portchange & USB_PORT_STAT_C_CONNECTION)
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_CONNECTION);
++ if (portchange & USB_PORT_STAT_C_ENABLE)
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_ENABLE);
++ }
++
++ return status;
++}
++
+ #ifdef CONFIG_USB_SUSPEND
+
+ /*
+@@ -1974,7 +2013,6 @@ int usb_port_resume(struct usb_device *u
+ int port1 = udev->portnum;
+ int status;
+ u16 portchange, portstatus;
+- unsigned mask_flags, want_flags;
+
+ /* Skip the initial Clear-Suspend step for a remote wakeup */
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+@@ -2003,33 +2041,20 @@ int usb_port_resume(struct usb_device *u
+ */
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+
+- SuspendCleared:
+- if (udev->reset_resume)
+- want_flags = USB_PORT_STAT_POWER
+- | USB_PORT_STAT_CONNECTION;
+- else
+- want_flags = USB_PORT_STAT_POWER
+- | USB_PORT_STAT_CONNECTION
+- | USB_PORT_STAT_ENABLE;
+- mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+-
+- if (status < 0 || (portstatus & mask_flags) != want_flags) {
+- dev_dbg(hub->intfdev,
+- "port %d status %04x.%04x after resume, %d\n",
+- port1, portchange, portstatus, status);
+- if (status >= 0)
+- status = -ENODEV;
+- } else {
+- if (portchange & USB_PORT_STAT_C_SUSPEND)
+- clear_port_feature(hub->hdev, port1,
+- USB_PORT_FEAT_C_SUSPEND);
+- /* TRSMRCY = 10 msec */
+- msleep(10);
+- }
++ /* TRSMRCY = 10 msec */
++ msleep(10);
+ }
+
++ SuspendCleared:
++ if (status == 0) {
++ if (portchange & USB_PORT_STAT_C_SUSPEND)
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_SUSPEND);
++ }
+ clear_bit(port1, hub->busy_bits);
+
++ status = check_port_resume_type(udev,
++ hub, port1, status, portchange, portstatus);
+ if (status == 0)
+ status = finish_port_resume(udev);
+ if (status < 0) {
+@@ -2062,12 +2087,23 @@ int usb_port_suspend(struct usb_device *
+ return 0;
+ }
+
++/* However we may need to do a reset-resume */
++
+ int usb_port_resume(struct usb_device *udev)
+ {
+- int status = 0;
++ struct usb_hub *hub = hdev_to_hub(udev->parent);
++ int port1 = udev->portnum;
++ int status;
++ u16 portchange, portstatus;
+
+- /* However we may need to do a reset-resume */
+- if (udev->reset_resume) {
++ status = hub_port_status(hub, port1, &portstatus, &portchange);
++ status = check_port_resume_type(udev,
++ hub, port1, status, portchange, portstatus);
++
++ if (status) {
++ dev_dbg(&udev->dev, "can't resume, status %d\n", status);
++ hub_port_logical_disconnect(hub, port1);
++ } else if (udev->reset_resume) {
+ dev_dbg(&udev->dev, "reset-resume\n");
+ status = usb_reset_device(udev);
+ }
diff --git a/usb/usb-add-usb_dev_reset_delayed.patch b/usb/usb-add-usb_dev_reset_delayed.patch
index 9295bc016005d6..197373ec3829cf 100644
--- a/usb/usb-add-usb_dev_reset_delayed.patch
+++ b/usb/usb-add-usb_dev_reset_delayed.patch
@@ -20,7 +20,7 @@ Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
-@@ -3304,3 +3304,86 @@ int usb_reset_composite_device(struct us
+@@ -3393,3 +3393,86 @@ int usb_reset_composite_device(struct us
return ret;
}
EXPORT_SYMBOL_GPL(usb_reset_composite_device);
diff --git a/usb/usb-combine-hub_activate-and-hub_restart.patch b/usb/usb-combine-hub_activate-and-hub_restart.patch
new file mode 100644
index 00000000000000..a3c1e6d622038e
--- /dev/null
+++ b/usb/usb-combine-hub_activate-and-hub_restart.patch
@@ -0,0 +1,130 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:32:59 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:07:17 -0400 (EDT)
+Subject: USB: combine hub_activate and hub_restart
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281100130.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1071) combines hub_activate() and hub_restart() into a
+single routine. There's no point keeping them separate, since they
+are always called together.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 49 +++++++++++++++++++++++--------------------------
+ 1 file changed, 23 insertions(+), 26 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -551,22 +551,6 @@ static void hub_quiesce(struct usb_hub *
+ cancel_work_sync(&hub->tt.kevent);
+ }
+
+-static void hub_activate(struct usb_hub *hub)
+-{
+- int status;
+-
+- hub->quiescing = 0;
+-
+- status = usb_submit_urb(hub->urb, GFP_NOIO);
+- if (status < 0)
+- dev_err(hub->intfdev, "activate --> %d\n", status);
+- if (hub->has_indicators && blinkenlights)
+- schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+-
+- /* scan all ports ASAP */
+- kick_khubd(hub);
+-}
+-
+ static int hub_hub_status(struct usb_hub *hub,
+ u16 *status, u16 *change)
+ {
+@@ -643,18 +627,24 @@ enum hub_activation_type {
+ HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+ };
+
+-static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
++static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ struct usb_device *hdev = hub->hdev;
+ int port1;
++ int status;
+ bool need_debounce_delay = false;
+
++ /* After a resume, port power should still be on.
++ * For any other type of activation, turn it on.
++ */
++ if (type != HUB_RESUME)
++ hub_power_on(hub);
++
+ /* Check each port and set hub->change_bits to let khubd know
+ * which ports need attention.
+ */
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ struct usb_device *udev = hdev->children[port1-1];
+- int status;
+ u16 portstatus, portchange;
+
+ portstatus = portchange = 0;
+@@ -729,7 +719,17 @@ static void hub_restart(struct usb_hub *
+ */
+ if (need_debounce_delay)
+ msleep(HUB_DEBOUNCE_STABLE);
+- hub_activate(hub);
++
++ hub->quiescing = 0;
++
++ status = usb_submit_urb(hub->urb, GFP_NOIO);
++ if (status < 0)
++ dev_err(hub->intfdev, "activate --> %d\n", status);
++ if (hub->has_indicators && blinkenlights)
++ schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
++
++ /* Scan all ports that need attention */
++ kick_khubd(hub);
+ }
+
+ /* caller has locked the hub device */
+@@ -746,8 +746,7 @@ static int hub_post_reset(struct usb_int
+ {
+ struct usb_hub *hub = usb_get_intfdata(intf);
+
+- hub_power_on(hub);
+- hub_restart(hub, HUB_POST_RESET);
++ hub_activate(hub, HUB_POST_RESET);
+ return 0;
+ }
+
+@@ -993,8 +992,7 @@ static int hub_configure(struct usb_hub
+ if (hub->has_indicators && blinkenlights)
+ hub->indicator [0] = INDICATOR_CYCLE;
+
+- hub_power_on(hub);
+- hub_activate(hub);
++ hub_activate(hub, HUB_INIT);
+ return 0;
+
+ fail:
+@@ -2166,7 +2164,7 @@ static int hub_resume(struct usb_interfa
+ struct usb_hub *hub = usb_get_intfdata(intf);
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+- hub_restart(hub, HUB_RESUME);
++ hub_activate(hub, HUB_RESUME);
+ return 0;
+ }
+
+@@ -2175,8 +2173,7 @@ static int hub_reset_resume(struct usb_i
+ struct usb_hub *hub = usb_get_intfdata(intf);
+
+ dev_dbg(&intf->dev, "%s\n", __func__);
+- hub_power_on(hub);
+- hub_restart(hub, HUB_RESET_RESUME);
++ hub_activate(hub, HUB_RESET_RESUME);
+ return 0;
+ }
+
diff --git a/usb/usb-combine-hub_quiesce-and-hub_stop.patch b/usb/usb-combine-hub_quiesce-and-hub_stop.patch
new file mode 100644
index 00000000000000..7ac8b466bae7b6
--- /dev/null
+++ b/usb/usb-combine-hub_quiesce-and-hub_stop.patch
@@ -0,0 +1,132 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:33:23 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:07:31 -0400 (EDT)
+Subject: USB: combine hub_quiesce and hub_stop
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281100360.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1083) combines hub_quiesce() and hub_stop() into a
+single routine. There's no point keeping them separate since they are
+usually called together.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 63 ++++++++++++++++++++++++-------------------------
+ 1 file changed, 32 insertions(+), 31 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -538,19 +538,6 @@ static void hub_power_on(struct usb_hub
+ msleep(max(pgood_delay, (unsigned) 100));
+ }
+
+-static void hub_quiesce(struct usb_hub *hub)
+-{
+- /* (nonblocking) khubd and related activity won't re-trigger */
+- hub->quiescing = 1;
+-
+- /* (blocking) stop khubd and related activity */
+- usb_kill_urb(hub->urb);
+- if (hub->has_indicators)
+- cancel_delayed_work_sync(&hub->leds);
+- if (hub->tt.hub)
+- cancel_work_sync(&hub->tt.kevent);
+-}
+-
+ static int hub_hub_status(struct usb_hub *hub,
+ u16 *status, u16 *change)
+ {
+@@ -609,20 +596,6 @@ static void hub_port_logical_disconnect(
+ kick_khubd(hub);
+ }
+
+-/* caller has locked the hub device */
+-static void hub_stop(struct usb_hub *hub)
+-{
+- struct usb_device *hdev = hub->hdev;
+- int i;
+-
+- /* Disconnect all the children */
+- for (i = 0; i < hdev->maxchild; ++i) {
+- if (hdev->children[i])
+- usb_disconnect(&hdev->children[i]);
+- }
+- hub_quiesce(hub);
+-}
+-
+ enum hub_activation_type {
+ HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+ };
+@@ -732,12 +705,40 @@ static void hub_activate(struct usb_hub
+ kick_khubd(hub);
+ }
+
++enum hub_quiescing_type {
++ HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
++};
++
++static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
++{
++ struct usb_device *hdev = hub->hdev;
++ int i;
++
++ /* khubd and related activity won't re-trigger */
++ hub->quiescing = 1;
++
++ if (type != HUB_SUSPEND) {
++ /* Disconnect all the children */
++ for (i = 0; i < hdev->maxchild; ++i) {
++ if (hdev->children[i])
++ usb_disconnect(&hdev->children[i]);
++ }
++ }
++
++ /* Stop khubd and related activity */
++ usb_kill_urb(hub->urb);
++ if (hub->has_indicators)
++ cancel_delayed_work_sync(&hub->leds);
++ if (hub->tt.hub)
++ cancel_work_sync(&hub->tt.kevent);
++}
++
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+ struct usb_hub *hub = usb_get_intfdata(intf);
+
+- hub_stop(hub);
++ hub_quiesce(hub, HUB_PRE_RESET);
+ return 0;
+ }
+
+@@ -1024,7 +1025,7 @@ static void hub_disconnect(struct usb_in
+
+ /* Disconnect all children and quiesce the hub */
+ hub->error = 0;
+- hub_stop(hub);
++ hub_quiesce(hub, HUB_DISCONNECT);
+
+ usb_set_intfdata (intf, NULL);
+
+@@ -2155,7 +2156,7 @@ static int hub_suspend(struct usb_interf
+ dev_dbg(&intf->dev, "%s\n", __func__);
+
+ /* stop khubd and related activity */
+- hub_quiesce(hub);
++ hub_quiesce(hub, HUB_SUSPEND);
+ return 0;
+ }
+
+@@ -2898,7 +2899,7 @@ static void hub_events(void)
+ /* If the hub has died, clean up after it */
+ if (hdev->state == USB_STATE_NOTATTACHED) {
+ hub->error = -ENODEV;
+- hub_stop(hub);
++ hub_quiesce(hub, HUB_DISCONNECT);
+ goto loop;
+ }
+
diff --git a/usb/usb-create-attributes-before-sending-uevent.patch b/usb/usb-create-attributes-before-sending-uevent.patch
index eec9198f13730e..c17ffdcddaa9c4 100644
--- a/usb/usb-create-attributes-before-sending-uevent.patch
+++ b/usb/usb-create-attributes-before-sending-uevent.patch
@@ -80,7 +80,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
destroy_endpoint_class();
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
-@@ -1605,6 +1605,7 @@ free_interfaces:
+@@ -1607,6 +1607,7 @@ free_interfaces:
intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
diff --git a/usb/usb-debounce-before-unregistering.patch b/usb/usb-debounce-before-unregistering.patch
new file mode 100644
index 00000000000000..fc9c1ee18cf57c
--- /dev/null
+++ b/usb/usb-debounce-before-unregistering.patch
@@ -0,0 +1,93 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:31:33 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:06:28 -0400 (EDT)
+Subject: USB: debounce before unregistering
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281056190.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1080) makes a significant change to the way khubd
+handles port connect-change and enable-change events. Both types of
+event are now debounced, and the debouncing is carried out _before_ an
+existing usb_device is unregistered, instead of afterward.
+
+This means that drivers will have to deal with longer runs of errors
+when a device is unplugged, but they are supposed to be prepared for
+that in any case.
+
+The advantage is that when an enable-change occurs (caused for example
+by electromagnetic interference), the debouncing period will provide
+time for the cause of the problem to die away. A simple port reset
+(added in a forthcoming patch) will then allow us to recover from the
+fault.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 31 +++++++++++++++++++------------
+ 1 file changed, 19 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2619,9 +2619,10 @@ static void hub_port_connect_change(stru
+ struct usb_device *hdev = hub->hdev;
+ struct device *hub_dev = hub->intfdev;
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+- u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
++ unsigned wHubCharacteristics =
++ le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ int status, i;
+-
++
+ dev_dbg (hub_dev,
+ "port %d, status %04x, change %04x, %s\n",
+ port1, portstatus, portchange, portspeed (portstatus));
+@@ -2630,30 +2631,36 @@ static void hub_port_connect_change(stru
+ set_port_led(hub, port1, HUB_LED_AUTO);
+ hub->indicator[port1-1] = INDICATOR_AUTO;
+ }
+-
+- /* Disconnect any existing devices under this port */
+- if (hdev->children[port1-1])
+- usb_disconnect(&hdev->children[port1-1]);
+- clear_bit(port1, hub->change_bits);
+
+ #ifdef CONFIG_USB_OTG
+ /* during HNP, don't repeat the debounce */
+ if (hdev->bus->is_b_host)
+- portchange &= ~USB_PORT_STAT_C_CONNECTION;
++ portchange &= ~(USB_PORT_STAT_C_CONNECTION |
++ USB_PORT_STAT_C_ENABLE);
+ #endif
+
+- if (portchange & USB_PORT_STAT_C_CONNECTION) {
++ /* Try to use the debounce delay for protection against
++ * port-enable changes caused, for example, by EMI.
++ */
++ if (portchange & (USB_PORT_STAT_C_CONNECTION |
++ USB_PORT_STAT_C_ENABLE)) {
+ status = hub_port_debounce(hub, port1);
+ if (status < 0) {
+ if (printk_ratelimit())
+ dev_err (hub_dev, "connect-debounce failed, "
+ "port %d disabled\n", port1);
+- goto done;
++ portstatus &= ~USB_PORT_STAT_CONNECTION;
++ } else {
++ portstatus = status;
+ }
+- portstatus = status;
+ }
+
+- /* Return now if nothing is connected */
++ /* Disconnect any existing devices under this port */
++ if (hdev->children[port1-1])
++ usb_disconnect(&hdev->children[port1-1]);
++ clear_bit(port1, hub->change_bits);
++
++ /* Return now if debouncing failed or nothing is connected */
+ if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
+
+ /* maybe switch power back on (e.g. root hub was reset) */
diff --git a/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch
new file mode 100644
index 00000000000000..d72b9774875e4e
--- /dev/null
+++ b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance-clear-feature-ignore.patch
@@ -0,0 +1,61 @@
+From dlopo@chipidea.mips.com Wed Apr 30 11:35:20 2008
+From: David Lopo <dlopo@chipidea.mips.com>
+Date: Tue, 29 Apr 2008 10:14:38 +0100
+Subject: USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance, clear-feature ignore
+To: greg@kroah.com, gregkh@suse.de
+Cc: Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org
+Message-ID: <4816E6FE.20509@chipidea.mips.com>
+
+
+From: David Lopo <lopo.david@gmail.com>
+
+Gadget tells controller driver to ignore Clear-Feature(HALT_ENDPOINT)
+
+Signed-off-by: David Lopo <lopo.david@gmail.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+---
+---
+ drivers/usb/gadget/file_storage.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -2307,6 +2307,29 @@ static int halt_bulk_in_endpoint(struct
+ return rc;
+ }
+
++static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
++{
++ int rc;
++
++ DBG(fsg, "bulk-in set wedge\n");
++ rc = usb_ep_set_wedge(fsg->bulk_in);
++ if (rc == -EAGAIN)
++ VDBG(fsg, "delayed bulk-in endpoint wedge\n");
++ while (rc != 0) {
++ if (rc != -EAGAIN) {
++ WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
++ rc = 0;
++ break;
++ }
++
++ /* Wait for a short time and then try again */
++ if (msleep_interruptible(100) != 0)
++ return -EINTR;
++ rc = usb_ep_set_wedge(fsg->bulk_in);
++ }
++ return rc;
++}
++
+ static int pad_with_zeros(struct fsg_dev *fsg)
+ {
+ struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
+@@ -2957,7 +2980,7 @@ static int received_cbw(struct fsg_dev *
+ * We aren't required to halt the OUT endpoint; instead
+ * we can simply accept and discard any data received
+ * until the next reset. */
+- halt_bulk_in_endpoint(fsg);
++ wedge_bulk_in_endpoint(fsg);
+ set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ return -EINVAL;
+ }
diff --git a/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch
new file mode 100644
index 00000000000000..dfaa09b6bce31f
--- /dev/null
+++ b/usb/usb-gadget-peripheral-g_file_storage-bulk-only-transport-compliance.patch
@@ -0,0 +1,59 @@
+From dlopo@chipidea.mips.com Wed Apr 30 11:34:54 2008
+From: David Lopo <dlopo@chipidea.mips.com>
+Date: Tue, 29 Apr 2008 10:12:37 +0100
+Subject: USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance
+To: greg@kroah.com, gregkh@suse.de
+Cc: stern@rowland.harvard.edu, linux-usb@vger.kernel.org
+Message-ID: <4816E685.2040208@chipidea.mips.com>
+
+
+From: David Lopo <lopo.david@gmail.com>
+
+Gadget can tell controller driver to ignore Clear-Feature(HALT_ENDPOINT)
+This API change enables future support for Bulk-Only Transport compliance
+
+Signed-off-by: David Lopo <lopo.david@gmail.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb/gadget.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -114,6 +114,8 @@ struct usb_ep_ops {
+ int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
+
+ int (*set_halt) (struct usb_ep *ep, int value);
++ int (*set_wedge) (struct usb_ep *ep);
++
+ int (*fifo_status) (struct usb_ep *ep);
+ void (*fifo_flush) (struct usb_ep *ep);
+ };
+@@ -349,6 +351,25 @@ static inline int usb_ep_clear_halt(stru
+ }
+
+ /**
++ * usb_ep_set_wedge - sets the halt feature and ignores clear requests
++ * @ep: the endpoint being wedged
++ *
++ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
++ * requests. If the gadget driver clears the halt status, it will
++ * automatically unwedge the endpoint.
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_ep_set_wedge(struct usb_ep *ep)
++{
++ if (ep->ops->set_wedge)
++ return ep->ops->set_wedge(ep);
++ else
++ return ep->ops->set_halt(ep, 1);
++}
++
++/**
+ * usb_ep_fifo_status - returns number of bytes in fifo, or error
+ * @ep: the endpoint whose fifo status is being checked.
+ *
diff --git a/usb/usb-optimize-port-debouncing-during-hub-activation.patch b/usb/usb-optimize-port-debouncing-during-hub-activation.patch
new file mode 100644
index 00000000000000..44b5dbbfabf5b7
--- /dev/null
+++ b/usb/usb-optimize-port-debouncing-during-hub-activation.patch
@@ -0,0 +1,99 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:32:40 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:07:07 -0400 (EDT)
+Subject: USB: optimize port debouncing during hub activation
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281058350.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1082) makes a small optimization to the way the hub
+driver carries out port debouncing immediately after a hub is
+activated (i.e., initialized, reset, or resumed). If any port-change
+statuses are observed, the code will delay for a minimal debounce
+period -- thereby making a good start at debouncing all the ports at
+once.
+
+If this wasn't sufficient then khubd will debounce any port that still
+requires attention. But in most cases it should suffice; it's rare
+for a device to need more than a minimal debounce delay. (In the
+cases of hub initialization or reset even that is most likely not
+needed, since any devices plugged in at such times have probably been
+attached for a while.)
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 32 +++++++++++++++++++++++++++-----
+ 1 file changed, 27 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -130,6 +130,10 @@ MODULE_PARM_DESC(use_both_schemes,
+ DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
+ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
+
++#define HUB_DEBOUNCE_TIMEOUT 1500
++#define HUB_DEBOUNCE_STEP 25
++#define HUB_DEBOUNCE_STABLE 100
++
+
+ static inline char *portspeed(int portstatus)
+ {
+@@ -643,6 +647,7 @@ static void hub_restart(struct usb_hub *
+ {
+ struct usb_device *hdev = hub->hdev;
+ int port1;
++ bool need_debounce_delay = false;
+
+ /* Check each port and set hub->change_bits to let khubd know
+ * which ports need attention.
+@@ -673,6 +678,18 @@ static void hub_restart(struct usb_hub *
+ portstatus &= ~USB_PORT_STAT_ENABLE;
+ }
+
++ /* Clear status-change flags; we'll debounce later */
++ if (portchange & USB_PORT_STAT_C_CONNECTION) {
++ need_debounce_delay = true;
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_CONNECTION);
++ }
++ if (portchange & USB_PORT_STAT_C_ENABLE) {
++ need_debounce_delay = true;
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_ENABLE);
++ }
++
+ if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+ /* Tell khubd to disconnect the device or
+ * check for a new connection
+@@ -702,6 +719,16 @@ static void hub_restart(struct usb_hub *
+ }
+ }
+
++ /* If no port-status-change flags were set, we don't need any
++ * debouncing. If flags were set we can try to debounce the
++ * ports all at once right now, instead of letting khubd do them
++ * one at a time later on.
++ *
++ * If any port-status changes do occur during this delay, khubd
++ * will see them later and handle them normally.
++ */
++ if (need_debounce_delay)
++ msleep(HUB_DEBOUNCE_STABLE);
+ hub_activate(hub);
+ }
+
+@@ -2199,11 +2226,6 @@ static inline int remote_wakeup(struct u
+ * every 25ms for transient disconnects. When the port status has been
+ * unchanged for 100ms it returns the port status.
+ */
+-
+-#define HUB_DEBOUNCE_TIMEOUT 1500
+-#define HUB_DEBOUNCE_STEP 25
+-#define HUB_DEBOUNCE_STABLE 100
+-
+ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ {
+ int ret;
diff --git a/usb/usb-simplify-hub_restart-logic.patch b/usb/usb-simplify-hub_restart-logic.patch
new file mode 100644
index 00000000000000..779e85fad6058e
--- /dev/null
+++ b/usb/usb-simplify-hub_restart-logic.patch
@@ -0,0 +1,250 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:32:02 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:06:42 -0400 (EDT)
+Subject: USB: simplify hub_restart() logic
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281057080.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1081) straightens out the logic of the hub_restart()
+routine. Each port of the hub is scanned and the driver makes sure
+that ports which are supposed to be disabled really _are_ disabled.
+Any ports with a significant change in status are flagged in
+hub->change_bits, so that khubd can focus on them without the need to
+scan all the ports a second time -- which means the hub->activating
+flag is no longer needed.
+
+Also, it is now recognized explicitly that the only reason for
+resuming a port which was not suspended is to carry out a reset-resume
+operation, which happens only in a non-CONFIG_USB_SUSPEND setting.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/driver.c | 7 --
+ drivers/usb/core/hub.c | 112 +++++++++++++++++++++-------------------------
+ 2 files changed, 53 insertions(+), 66 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -805,8 +805,6 @@ static int usb_resume_device(struct usb_
+
+ if (udev->state == USB_STATE_NOTATTACHED)
+ goto done;
+- if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
+- goto done;
+
+ /* Can't resume it if it doesn't have a driver. */
+ if (udev->dev.driver == NULL) {
+@@ -1173,11 +1171,8 @@ static int usb_resume_both(struct usb_de
+ * then we're stuck. */
+ status = usb_resume_device(udev);
+ }
+- } else {
+-
+- /* Needed for reset-resume */
++ } else if (udev->reset_resume)
+ status = usb_resume_device(udev);
+- }
+
+ if (status == 0 && udev->actconfig) {
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -72,7 +72,6 @@ struct usb_hub {
+
+ unsigned limited_power:1;
+ unsigned quiescing:1;
+- unsigned activating:1;
+ unsigned disconnected:1;
+
+ unsigned has_indicators:1;
+@@ -539,7 +538,6 @@ static void hub_quiesce(struct usb_hub *
+ {
+ /* (nonblocking) khubd and related activity won't re-trigger */
+ hub->quiescing = 1;
+- hub->activating = 0;
+
+ /* (blocking) stop khubd and related activity */
+ usb_kill_urb(hub->urb);
+@@ -554,7 +552,6 @@ static void hub_activate(struct usb_hub
+ int status;
+
+ hub->quiescing = 0;
+- hub->activating = 1;
+
+ status = usb_submit_urb(hub->urb, GFP_NOIO);
+ if (status < 0)
+@@ -638,81 +635,83 @@ static void hub_stop(struct usb_hub *hub
+ hub_quiesce(hub);
+ }
+
+-#define HUB_RESET 1
+-#define HUB_RESUME 2
+-#define HUB_RESET_RESUME 3
+-
+-#ifdef CONFIG_PM
++enum hub_activation_type {
++ HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
++};
+
+-static void hub_restart(struct usb_hub *hub, int type)
++static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ struct usb_device *hdev = hub->hdev;
+ int port1;
+
+- /* Check each of the children to see if they require
+- * USB-PERSIST handling or disconnection. Also check
+- * each unoccupied port to make sure it is still disabled.
++ /* Check each port and set hub->change_bits to let khubd know
++ * which ports need attention.
+ */
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ struct usb_device *udev = hdev->children[port1-1];
+- int status = 0;
++ int status;
+ u16 portstatus, portchange;
+
+- if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+- if (type != HUB_RESET) {
+- status = hub_port_status(hub, port1,
+- &portstatus, &portchange);
+- if (status == 0 && (portstatus &
+- USB_PORT_STAT_ENABLE))
+- clear_port_feature(hdev, port1,
+- USB_PORT_FEAT_ENABLE);
+- }
+- continue;
++ portstatus = portchange = 0;
++ status = hub_port_status(hub, port1, &portstatus, &portchange);
++ if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
++ dev_dbg(hub->intfdev,
++ "port %d: status %04x change %04x\n",
++ port1, portstatus, portchange);
++
++ /* After anything other than HUB_RESUME (i.e., initialization
++ * or any sort of reset), every port should be disabled.
++ * Unconnected ports should likewise be disabled (paranoia),
++ * and so should ports for which we have no usb_device.
++ */
++ if ((portstatus & USB_PORT_STAT_ENABLE) && (
++ type != HUB_RESUME ||
++ !(portstatus & USB_PORT_STAT_CONNECTION) ||
++ !udev ||
++ udev->state == USB_STATE_NOTATTACHED)) {
++ clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
++ portstatus &= ~USB_PORT_STAT_ENABLE;
+ }
+
+- /* Was the power session lost while we were suspended? */
+- switch (type) {
+- case HUB_RESET_RESUME:
+- portstatus = 0;
+- portchange = USB_PORT_STAT_C_CONNECTION;
+- break;
++ if (!udev || udev->state == USB_STATE_NOTATTACHED) {
++ /* Tell khubd to disconnect the device or
++ * check for a new connection
++ */
++ if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
++ set_bit(port1, hub->change_bits);
+
+- case HUB_RESET:
+- case HUB_RESUME:
+- status = hub_port_status(hub, port1,
+- &portstatus, &portchange);
+- break;
+- }
++ } else if (portstatus & USB_PORT_STAT_ENABLE) {
++ /* The power session apparently survived the resume.
++ * If there was an overcurrent or suspend change
++ * (i.e., remote wakeup request), have khubd
++ * take care of it.
++ */
++ if (portchange)
++ set_bit(port1, hub->change_bits);
+
+- /* For "USB_PERSIST"-enabled children we must
+- * mark the child device for reset-resume and
+- * turn off the various status changes to prevent
+- * khubd from disconnecting it later.
+- */
+- if (udev->persist_enabled && status == 0 &&
+- !(portstatus & USB_PORT_STAT_ENABLE)) {
++ } else if (udev->persist_enabled) {
++ /* Turn off the status changes to prevent khubd
++ * from disconnecting the device.
++ */
+ if (portchange & USB_PORT_STAT_C_ENABLE)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_ENABLE);
+ if (portchange & USB_PORT_STAT_C_CONNECTION)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_CONNECTION);
++#ifdef CONFIG_PM
+ udev->reset_resume = 1;
++#endif
++ } else {
++ /* The power session is gone; tell khubd */
++ usb_set_device_state(udev, USB_STATE_NOTATTACHED);
++ set_bit(port1, hub->change_bits);
+ }
+-
+- /* Otherwise for a reset_resume we must disconnect the child,
+- * but as we may not lock the child device here
+- * we have to do a "logical" disconnect.
+- */
+- else if (type == HUB_RESET_RESUME)
+- hub_port_logical_disconnect(hub, port1);
+ }
+
+ hub_activate(hub);
+ }
+
+-#endif /* CONFIG_PM */
+-
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+@@ -728,7 +727,7 @@ static int hub_post_reset(struct usb_int
+ struct usb_hub *hub = usb_get_intfdata(intf);
+
+ hub_power_on(hub);
+- hub_activate(hub);
++ hub_restart(hub, HUB_POST_RESET);
+ return 0;
+ }
+
+@@ -2887,7 +2886,7 @@ static void hub_events(void)
+ continue;
+ connect_change = test_bit(i, hub->change_bits);
+ if (!test_and_clear_bit(i, hub->event_bits) &&
+- !connect_change && !hub->activating)
++ !connect_change)
+ continue;
+
+ ret = hub_port_status(hub, i,
+@@ -2895,11 +2894,6 @@ static void hub_events(void)
+ if (ret < 0)
+ continue;
+
+- if (hub->activating && !hdev->children[i-1] &&
+- (portstatus &
+- USB_PORT_STAT_CONNECTION))
+- connect_change = 1;
+-
+ if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_CONNECTION);
+@@ -2995,8 +2989,6 @@ static void hub_events(void)
+ }
+ }
+
+- hub->activating = 0;
+-
+ loop_autopm:
+ /* Allow autosuspend if we're not going to run again */
+ if (list_empty(&hub->event_list))
diff --git a/usb/usb-try-to-salvage-lost-power-sessions.patch b/usb/usb-try-to-salvage-lost-power-sessions.patch
new file mode 100644
index 00000000000000..7ff2dc3d8cb248
--- /dev/null
+++ b/usb/usb-try-to-salvage-lost-power-sessions.patch
@@ -0,0 +1,181 @@
+From stern@rowland.harvard.edu Wed Apr 30 11:32:15 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 28 Apr 2008 11:06:55 -0400 (EDT)
+Subject: USB: try to salvage lost power sessions
+To: Greg KH <greg@kroah.com>
+Cc: USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.0804281057480.5827-100000@iolanthe.rowland.org>
+
+
+This patch (as1073) adds to khubd a way to recover from power-session
+interruption caused by transient connect-change or enable-change
+events. After the debouncing period, khubd attempts to do a
+USB-Persist-style reset or reset-resume. If it works, the connection
+will remain unscathed.
+
+The upshot is that we will be more immune to noise caused by EMI. The
+grace period is on the order of 100 ms, so this won't permit recovery
+from the "accidentally knocked the USB cable out of its socket" type
+of event, but it's a start.
+
+As an added bonus, if a device was suspended when the system goes to
+sleep then we no longer need to check for power-session interruptions
+when the system wakes up. Khubd will naturally see the status change
+while processing the device's parent hub and will do the right thing.
+
+The remote_wakeup() routine is changed; now it expects the caller to
+acquire the device lock rather than acquiring the lock itself.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/driver.c | 13 +++------
+ drivers/usb/core/hub.c | 62 +++++++++++++++++++++++++++++++++++-----------
+ 2 files changed, 53 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1537,14 +1537,11 @@ static int usb_resume(struct device *dev
+ udev = to_usb_device(dev);
+
+ /* If udev->skip_sys_resume is set then udev was already suspended
+- * when the system suspend started, so we don't want to resume
+- * udev during this system wakeup. However a reset-resume counts
+- * as a wakeup event, so allow a reset-resume to occur if remote
+- * wakeup is enabled. */
+- if (udev->skip_sys_resume) {
+- if (!(udev->reset_resume && udev->do_remote_wakeup))
+- return -EHOSTUNREACH;
+- }
++ * when the system sleep started, so we don't want to resume it
++ * during this system wakeup.
++ */
++ if (udev->skip_sys_resume)
++ return 0;
+ return usb_external_resume_device(udev);
+ }
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -690,18 +690,11 @@ static void hub_restart(struct usb_hub *
+ set_bit(port1, hub->change_bits);
+
+ } else if (udev->persist_enabled) {
+- /* Turn off the status changes to prevent khubd
+- * from disconnecting the device.
+- */
+- if (portchange & USB_PORT_STAT_C_ENABLE)
+- clear_port_feature(hub->hdev, port1,
+- USB_PORT_FEAT_C_ENABLE);
+- if (portchange & USB_PORT_STAT_C_CONNECTION)
+- clear_port_feature(hub->hdev, port1,
+- USB_PORT_FEAT_C_CONNECTION);
+ #ifdef CONFIG_PM
+ udev->reset_resume = 1;
+ #endif
++ set_bit(port1, hub->change_bits);
++
+ } else {
+ /* The power session is gone; tell khubd */
+ usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+@@ -2063,17 +2056,16 @@ int usb_port_resume(struct usb_device *u
+ return status;
+ }
+
++/* caller has locked udev */
+ static int remote_wakeup(struct usb_device *udev)
+ {
+ int status = 0;
+
+- usb_lock_device(udev);
+ if (udev->state == USB_STATE_SUSPENDED) {
+ dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+ usb_mark_last_busy(udev);
+ status = usb_external_resume_device(udev);
+ }
+- usb_unlock_device(udev);
+ return status;
+ }
+
+@@ -2620,6 +2612,7 @@ static void hub_port_connect_change(stru
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+ unsigned wHubCharacteristics =
+ le16_to_cpu(hub->descriptor->wHubCharacteristics);
++ struct usb_device *udev;
+ int status, i;
+
+ dev_dbg (hub_dev,
+@@ -2654,8 +2647,45 @@ static void hub_port_connect_change(stru
+ }
+ }
+
++ /* Try to resuscitate an existing device */
++ udev = hdev->children[port1-1];
++ if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
++ udev->state != USB_STATE_NOTATTACHED) {
++
++ usb_lock_device(udev);
++ if (portstatus & USB_PORT_STAT_ENABLE) {
++ status = 0; /* Nothing to do */
++ } else if (!udev->persist_enabled) {
++ status = -ENODEV; /* Mustn't resuscitate */
++
++#ifdef CONFIG_USB_SUSPEND
++ } else if (udev->state == USB_STATE_SUSPENDED) {
++ /* For a suspended device, treat this as a
++ * remote wakeup event.
++ */
++ if (udev->do_remote_wakeup)
++ status = remote_wakeup(udev);
++
++ /* Otherwise leave it be; devices can't tell the
++ * difference between suspended and disabled.
++ */
++ else
++ status = 0;
++#endif
++
++ } else {
++ status = usb_reset_composite_device(udev, NULL);
++ }
++ usb_unlock_device(udev);
++
++ if (status == 0) {
++ clear_bit(port1, hub->change_bits);
++ return;
++ }
++ }
++
+ /* Disconnect any existing devices under this port */
+- if (hdev->children[port1-1])
++ if (udev)
+ usb_disconnect(&hdev->children[port1-1]);
+ clear_bit(port1, hub->change_bits);
+
+@@ -2673,7 +2703,6 @@ static void hub_port_connect_change(stru
+ }
+
+ for (i = 0; i < SET_CONFIG_TRIES; i++) {
+- struct usb_device *udev;
+
+ /* reallocate for each attempt, since references
+ * to the previous one can escape in various ways
+@@ -2928,11 +2957,16 @@ static void hub_events(void)
+ }
+
+ if (portchange & USB_PORT_STAT_C_SUSPEND) {
++ struct usb_device *udev;
++
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_SUSPEND);
+- if (hdev->children[i-1]) {
++ udev = hdev->children[i-1];
++ if (udev) {
++ usb_lock_device(udev);
+ ret = remote_wakeup(hdev->
+ children[i-1]);
++ usb_unlock_device(udev);
+ if (ret < 0)
+ connect_change = 1;
+ } else {
diff --git a/usb/usb_serial-some-coding-style-fixes.patch b/usb/usb_serial-some-coding-style-fixes.patch
new file mode 100644
index 00000000000000..f828b71b854014
--- /dev/null
+++ b/usb/usb_serial-some-coding-style-fixes.patch
@@ -0,0 +1,512 @@
+From alan@lxorguk.ukuu.org.uk Wed Apr 30 11:28:49 2008
+From: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Date: Tue, 29 Apr 2008 14:35:39 +0100
+Subject: usb_serial: some coding style fixes
+To: linux-usb@vger.kernel.org, greg@kroah.com
+Message-ID: <20080429143539.35def80c@core>
+
+
+Signed-off-by: Alan Cox <alan@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/aircable.c | 98 +++++++++++++++++++++---------------------
+ drivers/usb/serial/airprime.c | 61 ++++++++++++++------------
+ drivers/usb/serial/ark3116.c | 54 +++++++++++------------
+ drivers/usb/serial/ch341.c | 2
+ 4 files changed, 112 insertions(+), 103 deletions(-)
+
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -147,7 +147,7 @@ static void serial_buf_free(struct circ_
+ */
+ static int serial_buf_data_avail(struct circ_buf *cb)
+ {
+- return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
++ return CIRC_CNT(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+ }
+
+ /*
+@@ -171,7 +171,7 @@ static int serial_buf_put(struct circ_bu
+ cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
+ buf += c;
+ count -= c;
+- ret= c;
++ ret = c;
+ }
+ return ret;
+ }
+@@ -197,7 +197,7 @@ static int serial_buf_get(struct circ_bu
+ cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
+ buf += c;
+ count -= c;
+- ret= c;
++ ret = c;
+ }
+ return ret;
+ }
+@@ -208,7 +208,7 @@ static void aircable_send(struct usb_ser
+ {
+ int count, result;
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+- unsigned char* buf;
++ unsigned char *buf;
+ __le16 *dbuf;
+ dbg("%s - port %d", __func__, port->number);
+ if (port->write_urb_busy)
+@@ -229,7 +229,8 @@ static void aircable_send(struct usb_ser
+ buf[1] = TX_HEADER_1;
+ dbuf = (__le16 *)&buf[2];
+ *dbuf = cpu_to_le16((u16)count);
+- serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
++ serial_buf_get(priv->tx_buf, buf + HCI_HEADER_LENGTH,
++ MAX_HCI_FRAMESIZE);
+
+ memcpy(port->write_urb->transfer_buffer, buf,
+ count + HCI_HEADER_LENGTH);
+@@ -261,7 +262,7 @@ static void aircable_read(struct work_st
+ struct tty_struct *tty;
+ unsigned char *data;
+ int count;
+- if (priv->rx_flags & THROTTLED){
++ if (priv->rx_flags & THROTTLED) {
+ if (priv->rx_flags & ACTUALLY_THROTTLED)
+ schedule_work(&priv->rx_work);
+ return;
+@@ -282,10 +283,10 @@ static void aircable_read(struct work_st
+ count = min(64, serial_buf_data_avail(priv->rx_buf));
+
+ if (count <= 0)
+- return; //We have finished sending everything.
++ return; /* We have finished sending everything. */
+
+ tty_prepare_flip_string(tty, &data, count);
+- if (!data){
++ if (!data) {
+ err("%s- kzalloc(%d) failed.", __func__, count);
+ return;
+ }
+@@ -304,9 +305,10 @@ static void aircable_read(struct work_st
+ static int aircable_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+ {
+- struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
++ struct usb_host_interface *iface_desc = serial->interface->
++ cur_altsetting;
+ struct usb_endpoint_descriptor *endpoint;
+- int num_bulk_out=0;
++ int num_bulk_out = 0;
+ int i;
+
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+@@ -325,13 +327,13 @@ static int aircable_probe(struct usb_ser
+ return 0;
+ }
+
+-static int aircable_attach (struct usb_serial *serial)
++static int aircable_attach(struct usb_serial *serial)
+ {
+ struct usb_serial_port *port = serial->port[0];
+ struct aircable_private *priv;
+
+ priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+- if (!priv){
++ if (!priv) {
+ err("%s- kmalloc(%Zd) failed.", __func__,
+ sizeof(struct aircable_private));
+ return -ENOMEM;
+@@ -392,7 +394,7 @@ static int aircable_write(struct usb_ser
+
+ usb_serial_debug_data(debug, &port->dev, __func__, count, source);
+
+- if (!count){
++ if (!count) {
+ dbg("%s - write request of 0 bytes", __func__);
+ return count;
+ }
+@@ -418,31 +420,31 @@ static void aircable_write_bulk_callback
+
+ /* This has been taken from cypress_m8.c cypress_write_int_callback */
+ switch (status) {
+- case 0:
+- /* success */
+- break;
+- case -ECONNRESET:
+- case -ENOENT:
+- case -ESHUTDOWN:
+- /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d",
+- __func__, status);
+- port->write_urb_busy = 0;
++ case 0:
++ /* success */
++ break;
++ case -ECONNRESET:
++ case -ENOENT:
++ case -ESHUTDOWN:
++ /* this urb is terminated, clean up */
++ dbg("%s - urb shutting down with status: %d",
++ __func__, status);
++ port->write_urb_busy = 0;
++ return;
++ default:
++ /* error in the urb, so we have to resubmit it */
++ dbg("%s - Overflow in write", __func__);
++ dbg("%s - nonzero write bulk status received: %d",
++ __func__, status);
++ port->write_urb->transfer_buffer_length = 1;
++ port->write_urb->dev = port->serial->dev;
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result)
++ dev_err(&urb->dev->dev,
++ "%s - failed resubmitting write urb, error %d\n",
++ __func__, result);
++ else
+ return;
+- default:
+- /* error in the urb, so we have to resubmit it */
+- dbg("%s - Overflow in write", __func__);
+- dbg("%s - nonzero write bulk status received: %d",
+- __func__, status);
+- port->write_urb->transfer_buffer_length = 1;
+- port->write_urb->dev = port->serial->dev;
+- result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+- if (result)
+- dev_err(&urb->dev->dev,
+- "%s - failed resubmitting write urb, error %d\n",
+- __func__, result);
+- else
+- return;
+ }
+
+ port->write_urb_busy = 0;
+@@ -472,11 +474,11 @@ static void aircable_read_bulk_callback(
+ dbg("%s - caught -EPROTO, resubmitting the urb",
+ __func__);
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- aircable_read_bulk_callback, port);
++ usb_rcvbulkpipe(port->serial->dev,
++ port->bulk_in_endpointAddress),
++ port->read_urb->transfer_buffer,
++ port->read_urb->transfer_buffer_length,
++ aircable_read_bulk_callback, port);
+
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+@@ -490,7 +492,7 @@ static void aircable_read_bulk_callback(
+ }
+
+ usb_serial_debug_data(debug, &port->dev, __func__,
+- urb->actual_length,urb->transfer_buffer);
++ urb->actual_length, urb->transfer_buffer);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -507,9 +509,9 @@ static void aircable_read_bulk_callback(
+ no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
+
+ if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
+- no_packages+=1;
++ no_packages++;
+
+- for (i = 0; i < no_packages ;i++) {
++ for (i = 0; i < no_packages; i++) {
+ if (remaining > (HCI_COMPLETE_FRAME))
+ package_length = HCI_COMPLETE_FRAME;
+ else
+@@ -529,7 +531,7 @@ static void aircable_read_bulk_callback(
+ if (port->open_count) {
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
++ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ aircable_read_bulk_callback, port);
+@@ -602,7 +604,7 @@ static struct usb_serial_driver aircable
+ .unthrottle = aircable_unthrottle,
+ };
+
+-static int __init aircable_init (void)
++static int __init aircable_init(void)
+ {
+ int retval;
+ retval = usb_serial_register(&aircable_device);
+@@ -619,7 +621,7 @@ failed_usb_register:
+ return retval;
+ }
+
+-static void __exit aircable_exit (void)
++static void __exit aircable_exit(void)
+ {
+ usb_deregister(&aircable_driver);
+ usb_serial_deregister(&aircable_device);
+--- a/drivers/usb/serial/airprime.c
++++ b/drivers/usb/serial/airprime.c
+@@ -68,8 +68,9 @@ static int airprime_send_setup(struct us
+ val |= 0x02;
+
+ return usb_control_msg(serial->dev,
+- usb_rcvctrlpipe(serial->dev, 0),
+- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
++ usb_rcvctrlpipe(serial->dev, 0),
++ 0x22, 0x21, val, 0, NULL, 0,
++ USB_CTRL_SET_TIMEOUT);
+ }
+
+ return 0;
+@@ -90,17 +91,19 @@ static void airprime_read_bulk_callback(
+ __func__, status);
+ return;
+ }
+- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__,
++ urb->actual_length, data);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+- tty_insert_flip_string (tty, data, urb->actual_length);
+- tty_flip_buffer_push (tty);
++ tty_insert_flip_string(tty, data, urb->actual_length);
++ tty_flip_buffer_push(tty);
+ }
+
+- result = usb_submit_urb (urb, GFP_ATOMIC);
++ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
++ dev_err(&port->dev,
++ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
+ return;
+ }
+@@ -115,7 +118,7 @@ static void airprime_write_bulk_callback
+ dbg("%s - port %d", __func__, port->number);
+
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+- kfree (urb->transfer_buffer);
++ kfree(urb->transfer_buffer);
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+@@ -171,7 +174,7 @@ static int airprime_open(struct usb_seri
+ }
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+- port->bulk_out_endpointAddress),
++ port->bulk_out_endpointAddress),
+ buffer, buffer_size,
+ airprime_read_bulk_callback, port);
+ result = usb_submit_urb(urb, GFP_KERNEL);
+@@ -183,7 +186,8 @@ static int airprime_open(struct usb_seri
+ __func__, i, port->number, result);
+ goto errout;
+ }
+- /* remember this urb so we can kill it when the port is closed */
++ /* remember this urb so we can kill it when the
++ port is closed */
+ priv->read_urbp[i] = urb;
+ }
+
+@@ -192,22 +196,22 @@ static int airprime_open(struct usb_seri
+ goto out;
+
+ errout:
+- /* some error happened, cancel any submitted urbs and clean up anything that
+- got allocated successfully */
++ /* some error happened, cancel any submitted urbs and clean up
++ anything that got allocated successfully */
+
+ while (i-- != 0) {
+ urb = priv->read_urbp[i];
+ buffer = urb->transfer_buffer;
+- usb_kill_urb (urb);
+- usb_free_urb (urb);
+- kfree (buffer);
++ usb_kill_urb(urb);
++ usb_free_urb(urb);
++ kfree(buffer);
+ }
+
+ out:
+ return result;
+ }
+
+-static void airprime_close(struct usb_serial_port *port, struct file * filp)
++static void airprime_close(struct usb_serial_port *port, struct file *filp)
+ {
+ struct airprime_private *priv = usb_get_serial_port_data(port);
+ int i;
+@@ -223,13 +227,13 @@ static void airprime_close(struct usb_se
+ mutex_unlock(&port->serial->disc_mutex);
+
+ for (i = 0; i < NUM_READ_URBS; ++i) {
+- usb_kill_urb (priv->read_urbp[i]);
+- kfree (priv->read_urbp[i]->transfer_buffer);
+- usb_free_urb (priv->read_urbp[i]);
++ usb_kill_urb(priv->read_urbp[i]);
++ kfree(priv->read_urbp[i]->transfer_buffer);
++ usb_free_urb(priv->read_urbp[i]);
+ }
+
+ /* free up private structure */
+- kfree (priv);
++ kfree(priv);
+ usb_set_serial_port_data(port, NULL);
+ }
+
+@@ -259,10 +263,10 @@ static int airprime_write(struct usb_ser
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(&port->dev, "no more free urbs\n");
+- kfree (buffer);
++ kfree(buffer);
+ return -ENOMEM;
+ }
+- memcpy (buffer, buf, count);
++ memcpy(buffer, buf, count);
+
+ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+@@ -279,7 +283,7 @@ static int airprime_write(struct usb_ser
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+ __func__, status);
+ count = status;
+- kfree (buffer);
++ kfree(buffer);
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ ++priv->outstanding_urbs;
+@@ -287,7 +291,7 @@ static int airprime_write(struct usb_ser
+ }
+ /* we are done with this urb, so let the host driver
+ * really free it when it is finished with it */
+- usb_free_urb (urb);
++ usb_free_urb(urb);
+ return count;
+ }
+
+@@ -315,8 +319,10 @@ static int __init airprime_init(void)
+ {
+ int retval;
+
+- airprime_device.num_ports =
+- (endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
++ airprime_device.num_ports = endpoints;
++ if (endpoints < 0 || endpoints >= MAX_BULK_EPS)
++ airprime_device.num_ports = NUM_BULK_EPS;
++
+ retval = usb_serial_register(&airprime_device);
+ if (retval)
+ return retval;
+@@ -341,6 +347,7 @@ MODULE_LICENSE("GPL");
+ module_param(debug, bool, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(debug, "Debug enabled");
+ module_param(buffer_size, int, 0);
+-MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
++MODULE_PARM_DESC(buffer_size,
++ "Size of the transfer buffers in bytes (default 4096)");
+ module_param(endpoints, int, 0);
+ MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -24,7 +24,7 @@
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+ #include <linux/serial.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+
+
+ static int debug;
+@@ -246,29 +246,29 @@ static void ark3116_set_termios(struct u
+ baud = tty_get_baud_rate(port->tty);
+
+ switch (baud) {
+- case 75:
+- case 150:
+- case 300:
+- case 600:
+- case 1200:
+- case 1800:
+- case 2400:
+- case 4800:
+- case 9600:
+- case 19200:
+- case 38400:
+- case 57600:
+- case 115200:
+- case 230400:
+- case 460800:
+- /* Report the resulting rate back to the caller */
+- tty_encode_baud_rate(port->tty, baud, baud);
+- break;
+- /* set 9600 as default (if given baudrate is invalid for example) */
+- default:
+- tty_encode_baud_rate(port->tty, 9600, 9600);
+- case 0:
+- baud = 9600;
++ case 75:
++ case 150:
++ case 300:
++ case 600:
++ case 1200:
++ case 1800:
++ case 2400:
++ case 4800:
++ case 9600:
++ case 19200:
++ case 38400:
++ case 57600:
++ case 115200:
++ case 230400:
++ case 460800:
++ /* Report the resulting rate back to the caller */
++ tty_encode_baud_rate(port->tty, baud, baud);
++ break;
++ /* set 9600 as default (if given baudrate is invalid for example) */
++ default:
++ tty_encode_baud_rate(port->tty, 9600, 9600);
++ case 0:
++ baud = 9600;
+ }
+
+ /*
+@@ -380,19 +380,19 @@ static int ark3116_ioctl(struct usb_seri
+ switch (cmd) {
+ case TIOCGSERIAL:
+ /* XXX: Some of these values are probably wrong. */
+- memset(&serstruct, 0, sizeof (serstruct));
++ memset(&serstruct, 0, sizeof(serstruct));
+ serstruct.type = PORT_16654;
+ serstruct.line = port->serial->minor;
+ serstruct.port = port->number;
+ serstruct.custom_divisor = 0;
+ serstruct.baud_base = 460800;
+
+- if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
++ if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
+ return -EFAULT;
+
+ return 0;
+ case TIOCSSERIAL:
+- if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
++ if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
+ return -EFAULT;
+ return 0;
+ default:
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -130,7 +130,7 @@ static int ch341_get_status(struct usb_d
+ return -ENOMEM;
+
+ r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
+- if ( r < 0)
++ if (r < 0)
+ goto out;
+
+ /* Not having the datasheet for the CH341, we ignore the bytes returned