aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-04-29 13:28:50 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-29 13:28:50 -0700
commit9c3de47550378c2c5cb83ff5e0f7138b6fa00f83 (patch)
treef0e9a76652a4cf3b74c3b5244a96db942715b76b /usb
parentbccc6afa0ed3ca2fedde5fe95de3a7df61866e7a (diff)
downloadpatches-9c3de47550378c2c5cb83ff5e0f7138b6fa00f83.tar.gz
lots of crap
Diffstat (limited to 'usb')
-rw-r--r--usb/devices-fix-coding-styles.patch72
-rw-r--r--usb/musb-blackfin-remove-bfin_vbus_power.patch41
-rw-r--r--usb/musb-blackfin-remove-musb_platform_-suspend-resume.patch46
-rw-r--r--usb/musb-omap-make-musb_platform_suspend-static.patch31
-rw-r--r--usb/musb-omap-remove-omap_vbus_power.patch51
-rw-r--r--usb/short-new-graph-for-usb-serial.txt.patch56
-rw-r--r--usb/usb-add-parsing-of-superspeed-endpoint-companion-descriptor.patch33
-rw-r--r--usb/usb-add-stream-id-field-to-struct-urb.patch34
-rw-r--r--usb/usb-deprecate-the-power-level-sysfs-attribute.patch203
-rw-r--r--usb/usb-don-t-enable-remote-wakeup-by-default.patch36
-rw-r--r--usb/usb-ehci-elide-i-o-watchdog-on-nec-parts.patch34
-rw-r--r--usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch508
-rw-r--r--usb/usb-gadget-allow-larger-configuration-descriptors.patch30
-rw-r--r--usb/usb-gadget-f_mass_storage-per-function.patch88
-rw-r--r--usb/usb-improve-runtime-remote-wakeup-settings.patch77
-rw-r--r--usb/usb-musb-add-extvbus-in-musb_board_data.patch56
-rw-r--r--usb/usb-musb-add-ulpi-access-operations.patch150
-rw-r--r--usb/usb-musb-debugfs-musb_exit_debugfs-can-be-called-on-probe.patch57
-rw-r--r--usb/usb-musb-makefile-remove-unexistent-config-option.patch35
-rw-r--r--usb/usb-musb-omap2430-remove-unused-define.patch34
-rw-r--r--usb/usb-musb-omap2430.c-remove-unnecessary-includes.patch31
-rw-r--r--usb/usb-musb-support-host-gadget-role-switching-on-blackfin-parts.patch138
-rw-r--r--usb/usb-omap-switch-to-subsys_initcall-for-isp1301-transceiver.patch27
-rw-r--r--usb/usb-option-use-generic-usb-wwan-code.patch783
-rw-r--r--usb/usb-otg-twl4030-use-the-global-ulpi-register-definitions.patch215
-rw-r--r--usb/usb-pxa27x_udc-use-four-bits-to-store-endpoint-addresses.patch31
-rw-r--r--usb/usb-qcserial-add-support-for-qualcomm-gobi-2000-devices.patch105
-rw-r--r--usb/usb-qcserial-use-generic-usb-wwan-code.patch82
-rw-r--r--usb/usb-serial-add-generic-usb-wwan-support.patch784
-rw-r--r--usb/usb-storage-remove-unneeded-sl11r-unusual_devs-entry.patch42
-rw-r--r--usb/usb-support-for-allocating-usb-3.0-streams.patch248
-rw-r--r--usb/usb-ueagle-fix-coding-styles.patch745
-rw-r--r--usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch138
-rw-r--r--usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch802
-rw-r--r--usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch1086
35 files changed, 6929 insertions, 0 deletions
diff --git a/usb/devices-fix-coding-styles.patch b/usb/devices-fix-coding-styles.patch
new file mode 100644
index 00000000000000..195090f8104c6a
--- /dev/null
+++ b/usb/devices-fix-coding-styles.patch
@@ -0,0 +1,72 @@
+From csanchez@neurowork.net Thu Apr 29 13:12:22 2010
+From: "Carlos S�nchez Acosta" <csanchez@neurowork.net>
+Date: Wed, 14 Apr 2010 06:58:53 -0500
+Subject: USB: devices: fix Coding Styles
+To: "Greg KH" <gregkh@suse.de>
+Message-ID: <b2ff38f0d4b7b167a0691997a238cb8e.squirrel@neurowork.net>
+
+
+Fixed coding styles in the config usb driver.
+
+Signed-off-by: Carlos S�nchez Acosta <csanchez@neurowork.net>
+Signed-off-by: Alejandro S�nchez Acosta <asanchez@neurowork.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devices.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -1,7 +1,8 @@
+ /*
+ * devices.c
+ * (C) Copyright 1999 Randy Dunlap.
+- * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
++ * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>.
++ * (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -56,7 +57,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/usbdevice_fs.h>
+ #include <linux/mutex.h>
+-#include <asm/uaccess.h>
++#include <linux/uaccess.h>
+
+ #include "usb.h"
+ #include "hcd.h"
+@@ -138,8 +139,8 @@ struct class_info {
+ char *class_name;
+ };
+
+-static const struct class_info clas_info[] =
+-{ /* max. 5 chars. per name string */
++static const struct class_info clas_info[] = {
++ /* max. 5 chars. per name string */
+ {USB_CLASS_PER_INTERFACE, ">ifc"},
+ {USB_CLASS_AUDIO, "audio"},
+ {USB_CLASS_COMM, "comm."},
+@@ -191,8 +192,10 @@ static char *usb_dump_endpoint_descripto
+
+ if (speed == USB_SPEED_HIGH) {
+ switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
+- case 1 << 11: bandwidth = 2; break;
+- case 2 << 11: bandwidth = 3; break;
++ case 1 << 11:
++ bandwidth = 2; break;
++ case 2 << 11:
++ bandwidth = 3; break;
+ }
+ }
+
+@@ -200,7 +203,7 @@ static char *usb_dump_endpoint_descripto
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ type = "Ctrl";
+- if (speed == USB_SPEED_HIGH) /* uframes per NAK */
++ if (speed == USB_SPEED_HIGH) /* uframes per NAK */
+ interval = desc->bInterval;
+ else
+ interval = 0;
diff --git a/usb/musb-blackfin-remove-bfin_vbus_power.patch b/usb/musb-blackfin-remove-bfin_vbus_power.patch
new file mode 100644
index 00000000000000..458891193faf56
--- /dev/null
+++ b/usb/musb-blackfin-remove-bfin_vbus_power.patch
@@ -0,0 +1,41 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:36:20 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:21 +0200
+Subject: MUSB: Blackfin: remove bfin_vbus_power()
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-5-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+This function does nothing...
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/blackfin.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -289,10 +289,6 @@ void musb_platform_disable(struct musb *
+ {
+ }
+
+-static void bfin_vbus_power(struct musb *musb, int is_on, int sleeping)
+-{
+-}
+-
+ static void bfin_set_vbus(struct musb *musb, int is_on)
+ {
+ int value = musb->config->gpio_vrsel_active;
+@@ -410,7 +406,6 @@ int musb_platform_resume(struct musb *mu
+ int musb_platform_exit(struct musb *musb)
+ {
+
+- bfin_vbus_power(musb, 0 /*off*/, 1);
+ gpio_free(musb->config->gpio_vrsel);
+ musb_platform_suspend(musb);
+
diff --git a/usb/musb-blackfin-remove-musb_platform_-suspend-resume.patch b/usb/musb-blackfin-remove-musb_platform_-suspend-resume.patch
new file mode 100644
index 00000000000000..3c1aa9be3023c9
--- /dev/null
+++ b/usb/musb-blackfin-remove-musb_platform_-suspend-resume.patch
@@ -0,0 +1,46 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:37:02 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:23 +0200
+Subject: MUSB: Blackfin: remove musb_platform_{suspend|resume}()
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-7-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+These functions do nothing and also are both unnecessarily 'extern'; actually,
+musb_platform_resume() in not even called...
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/blackfin.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -392,22 +392,10 @@ int __init musb_platform_init(struct mus
+ return 0;
+ }
+
+-int musb_platform_suspend(struct musb *musb)
+-{
+- return 0;
+-}
+-
+-int musb_platform_resume(struct musb *musb)
+-{
+- return 0;
+-}
+-
+-
+ int musb_platform_exit(struct musb *musb)
+ {
+
+ gpio_free(musb->config->gpio_vrsel);
+- musb_platform_suspend(musb);
+
+ return 0;
+ }
diff --git a/usb/musb-omap-make-musb_platform_suspend-static.patch b/usb/musb-omap-make-musb_platform_suspend-static.patch
new file mode 100644
index 00000000000000..47fffe2a3a5f1e
--- /dev/null
+++ b/usb/musb-omap-make-musb_platform_suspend-static.patch
@@ -0,0 +1,31 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:36:51 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:22 +0200
+Subject: MUSB: OMAP: make musb_platform_suspend() 'static'
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-6-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+This function is only called inside omap2430.c...
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/omap2430.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -275,7 +275,7 @@ void musb_platform_restore_context(struc
+ }
+ #endif
+
+-int musb_platform_suspend(struct musb *musb)
++static int musb_platform_suspend(struct musb *musb)
+ {
+ u32 l;
+
diff --git a/usb/musb-omap-remove-omap_vbus_power.patch b/usb/musb-omap-remove-omap_vbus_power.patch
new file mode 100644
index 00000000000000..28ab0d92a05a83
--- /dev/null
+++ b/usb/musb-omap-remove-omap_vbus_power.patch
@@ -0,0 +1,51 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:36:10 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:20 +0200
+Subject: MUSB: OMAP: remove omap_vbus_power()
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-4-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+
+This function does nothing...
+
+Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/omap2430.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -145,10 +145,6 @@ void musb_platform_enable(struct musb *m
+ void musb_platform_disable(struct musb *musb)
+ {
+ }
+-static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
+-{
+-}
+-
+ static void omap_set_vbus(struct musb *musb, int is_on)
+ {
+ u8 devctl;
+@@ -255,8 +251,6 @@ int __init musb_platform_init(struct mus
+ musb_readl(musb->mregs, OTG_INTERFSEL),
+ musb_readl(musb->mregs, OTG_SIMENABLE));
+
+- omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
+-
+ if (is_host_enabled(musb))
+ musb->board_set_vbus = omap_set_vbus;
+
+@@ -336,8 +330,6 @@ static int musb_platform_resume(struct m
+ int musb_platform_exit(struct musb *musb)
+ {
+
+- omap_vbus_power(musb, 0 /*off*/, 1);
+-
+ musb_platform_suspend(musb);
+
+ return 0;
diff --git a/usb/short-new-graph-for-usb-serial.txt.patch b/usb/short-new-graph-for-usb-serial.txt.patch
new file mode 100644
index 00000000000000..5c64137916e83a
--- /dev/null
+++ b/usb/short-new-graph-for-usb-serial.txt.patch
@@ -0,0 +1,56 @@
+From esr@thyrsus.com Thu Apr 29 13:12:53 2010
+From: Eric Raymond <esr@thyrsus.com>
+Date: Thu, 15 Apr 2010 01:35:50 -0400
+Subject: USB: Short new 'graph for usb-serial.txt
+To: Greg KH <greg@kroah.com>
+Cc: Eric Raymond <esr@snark.thyrsus.com>
+Message-ID: <20100415053550.GA21098@thyrsus.com>
+Content-Disposition: inline
+
+From: Eric Raymond <esr@thyrsus.com>
+
+Documentation update
+
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/usb-serial.txt | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/Documentation/usb/usb-serial.txt
++++ b/Documentation/usb/usb-serial.txt
+@@ -194,6 +194,10 @@ FTDI Single Port Serial Driver
+
+ This is a single port DB-25 serial adapter.
+
++ Devices supported include:
++ -TripNav TN-200 USB GPS
++ -Navis Engineering Bureau CH-4711 USB GPS
++
+ For any questions or problems with this driver, please contact Bill Ryder.
+
+
+@@ -216,7 +220,7 @@ Cypress M8 CY4601 Family Serial Driver
+
+ Devices supported:
+
+- -DeLorme's USB Earthmate (SiRF Star II lp arch)
++ -DeLorme's USB Earthmate GPS (SiRF Star II lp arch)
+ -Cypress HID->COM RS232 adapter
+
+ Note: Cypress Semiconductor claims no affiliation with the
+@@ -392,9 +396,10 @@ REINER SCT cyberJack pinpad/e-com USB ch
+ Prolific PL2303 Driver
+
+ This driver supports any device that has the PL2303 chip from Prolific
+- in it. This includes a number of single port USB to serial
+- converters and USB GPS devices. Devices from Aten (the UC-232) and
+- IO-Data work with this driver, as does the DCU-11 mobile-phone cable.
++ in it. This includes a number of single port USB to serial converters,
++ more than 70% of USB GPS devices (in 2010), and some USB UPSes. Devices
++ from Aten (the UC-232) and IO-Data work with this driver, as does
++ the DCU-11 mobile-phone cable.
+
+ For any questions or problems with this driver, please contact Greg
+ Kroah-Hartman at greg@kroah.com
diff --git a/usb/usb-add-parsing-of-superspeed-endpoint-companion-descriptor.patch b/usb/usb-add-parsing-of-superspeed-endpoint-companion-descriptor.patch
new file mode 100644
index 00000000000000..48a4f471e8e71c
--- /dev/null
+++ b/usb/usb-add-parsing-of-superspeed-endpoint-companion-descriptor.patch
@@ -0,0 +1,33 @@
+From sarah.a.sharp@linux.intel.com Thu Apr 29 12:57:38 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 2 Apr 2010 15:33:56 -0700
+Subject: USB: Add parsing of SuperSpeed endpoint companion descriptor.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, usb-storage@lists.one-eyed-alien.net, Hrant Dalalyan <Hrant.Dalalyan@synopsys.com>, Alan Stern <stern@rowland.harvard.edu>, Paul Zimmerman <Paul.Zimmerman@synopsys.com>, Ashot Madatyan <Ashot.Madatyan@synopsys.com>
+Message-ID: <20100402223356.GA1235@xanatos>
+Content-Disposition: inline
+
+
+Allow the xHCI drivers (and any new USB 3.0 drivers) to parse the
+SuperSpeed endpoint companion descriptor to find the maximum number of
+bulk endpoint streams the endpoint supports. This is used to calculate
+the maximum total number of streams the driver can allocate.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb/ch9.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/include/linux/usb/ch9.h
++++ b/include/linux/usb/ch9.h
+@@ -556,6 +556,8 @@ struct usb_ss_ep_comp_descriptor {
+ } __attribute__ ((packed));
+
+ #define USB_DT_SS_EP_COMP_SIZE 6
++/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
++#define USB_SS_MAX_STREAMS(p) (1 << (p & 0x1f))
+
+ /*-------------------------------------------------------------------------*/
+
diff --git a/usb/usb-add-stream-id-field-to-struct-urb.patch b/usb/usb-add-stream-id-field-to-struct-urb.patch
new file mode 100644
index 00000000000000..322927c15eccb1
--- /dev/null
+++ b/usb/usb-add-stream-id-field-to-struct-urb.patch
@@ -0,0 +1,34 @@
+From sarah.a.sharp@linux.intel.com Thu Apr 29 12:57:58 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 2 Apr 2010 15:34:10 -0700
+Subject: USB: Add stream ID field to struct urb.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, usb-storage@lists.one-eyed-alien.net, Hrant Dalalyan <Hrant.Dalalyan@synopsys.com>, Alan Stern <stern@rowland.harvard.edu>, Paul Zimmerman <Paul.Zimmerman@synopsys.com>, Ashot Madatyan <Ashot.Madatyan@synopsys.com>
+Message-ID: <20100402223410.GA1399@xanatos>
+Content-Disposition: inline
+
+
+Bulk endpoint streams were added in the USB 3.0 specification. Streams
+allow a device driver to overload a bulk endpoint so that multiple
+transfers can be queued at once.
+
+Add a new field, stream_id, to struct urb so that USB 3.0 drivers can
+specify which stream they want the URB to be queued to.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1196,6 +1196,7 @@ struct urb {
+ struct usb_device *dev; /* (in) pointer to associated device */
+ struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
+ unsigned int pipe; /* (in) pipe information */
++ unsigned int stream_id; /* (in) stream ID */
+ int status; /* (return) non-ISO status */
+ unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
+ void *transfer_buffer; /* (in) associated data buffer */
diff --git a/usb/usb-deprecate-the-power-level-sysfs-attribute.patch b/usb/usb-deprecate-the-power-level-sysfs-attribute.patch
new file mode 100644
index 00000000000000..2c8373abead109
--- /dev/null
+++ b/usb/usb-deprecate-the-power-level-sysfs-attribute.patch
@@ -0,0 +1,203 @@
+From stern@rowland.harvard.edu Thu Apr 29 12:52:02 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 2 Apr 2010 13:22:16 -0400 (EDT)
+Subject: USB: deprecate the power/level sysfs attribute
+To: Greg KH <greg@kroah.com>
+Message-ID: <Pine.LNX.4.44L0.1004021314040.1324-100000@iolanthe.rowland.org>
+
+
+This patch (as1367) deprecates USB's power/level sysfs attribute in
+favor of the power/control attribute provided by the runtime PM core.
+The two attributes do the same thing.
+
+It would be nice to replace power/level with a symlink to
+power/control, but at the moment sysfs doesn't offer any way to do so.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/ABI/obsolete/sysfs-bus-usb | 31 +++++++++++++++++++++++++++++++
+ Documentation/ABI/testing/sysfs-bus-usb | 28 ----------------------------
+ Documentation/usb/power-management.txt | 19 +++++++++++--------
+ drivers/usb/core/sysfs.c | 12 ++++++++++++
+ 4 files changed, 54 insertions(+), 36 deletions(-)
+
+--- /dev/null
++++ b/Documentation/ABI/obsolete/sysfs-bus-usb
+@@ -0,0 +1,31 @@
++What: /sys/bus/usb/devices/.../power/level
++Date: March 2007
++KernelVersion: 2.6.21
++Contact: Alan Stern <stern@rowland.harvard.edu>
++Description:
++ Each USB device directory will contain a file named
++ power/level. This file holds a power-level setting for
++ the device, either "on" or "auto".
++
++ "on" means that the device is not allowed to autosuspend,
++ although normal suspends for system sleep will still
++ be honored. "auto" means the device will autosuspend
++ and autoresume in the usual manner, according to the
++ capabilities of its driver.
++
++ During normal use, devices should be left in the "auto"
++ level. The "on" level is meant for administrative uses.
++ If you want to suspend a device immediately but leave it
++ free to wake up in response to I/O requests, you should
++ write "0" to power/autosuspend.
++
++ Device not capable of proper suspend and resume should be
++ left in the "on" level. Although the USB spec requires
++ devices to support suspend/resume, many of them do not.
++ In fact so many don't that by default, the USB core
++ initializes all non-hub devices in the "on" level. Some
++ drivers may change this setting when they are bound.
++
++ This file is deprecated and will be removed after 2010.
++ Use the power/control file instead; it does exactly the
++ same thing.
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -14,34 +14,6 @@ Description:
+ The autosuspend delay for newly-created devices is set to
+ the value of the usbcore.autosuspend module parameter.
+
+-What: /sys/bus/usb/devices/.../power/level
+-Date: March 2007
+-KernelVersion: 2.6.21
+-Contact: Alan Stern <stern@rowland.harvard.edu>
+-Description:
+- Each USB device directory will contain a file named
+- power/level. This file holds a power-level setting for
+- the device, either "on" or "auto".
+-
+- "on" means that the device is not allowed to autosuspend,
+- although normal suspends for system sleep will still
+- be honored. "auto" means the device will autosuspend
+- and autoresume in the usual manner, according to the
+- capabilities of its driver.
+-
+- During normal use, devices should be left in the "auto"
+- level. The "on" level is meant for administrative uses.
+- If you want to suspend a device immediately but leave it
+- free to wake up in response to I/O requests, you should
+- write "0" to power/autosuspend.
+-
+- Device not capable of proper suspend and resume should be
+- left in the "on" level. Although the USB spec requires
+- devices to support suspend/resume, many of them do not.
+- In fact so many don't that by default, the USB core
+- initializes all non-hub devices in the "on" level. Some
+- drivers may change this setting when they are bound.
+-
+ What: /sys/bus/usb/devices/.../power/persist
+ Date: May 2007
+ KernelVersion: 2.6.23
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -107,7 +107,9 @@ allowed to issue dynamic suspends.
+ The user interface for controlling dynamic PM is located in the power/
+ subdirectory of each USB device's sysfs directory, that is, in
+ /sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
+-relevant attribute files are: wakeup, level, and autosuspend.
++relevant attribute files are: wakeup, control, and autosuspend.
++(There may also be a file named "level"; this file was deprecated
++as of the 2.6.35 kernel and replaced by the "control" file.)
+
+ power/wakeup
+
+@@ -120,7 +122,7 @@ relevant attribute files are: wakeup, le
+ while the device is suspended, the change won't take
+ effect until the following suspend.)
+
+- power/level
++ power/control
+
+ This file contains one of two words: "on" or "auto".
+ You can write those words to the file to change the
+@@ -148,14 +150,15 @@ relevant attribute files are: wakeup, le
+ never to autosuspend. You can write a number to the
+ file to change the autosuspend idle-delay time.
+
+-Writing "-1" to power/autosuspend and writing "on" to power/level do
++Writing "-1" to power/autosuspend and writing "on" to power/control do
+ essentially the same thing -- they both prevent the device from being
+ autosuspended. Yes, this is a redundancy in the API.
+
+ (In 2.6.21 writing "0" to power/autosuspend would prevent the device
+ from being autosuspended; the behavior was changed in 2.6.22. The
+ power/autosuspend attribute did not exist prior to 2.6.21, and the
+-power/level attribute did not exist prior to 2.6.22.)
++power/level attribute did not exist prior to 2.6.22. power/control
++was added in 2.6.34.)
+
+
+ Changing the default idle-delay time
+@@ -212,7 +215,7 @@ among printers and scanners, but plenty
+ the same deficiency.
+
+ For this reason, by default the kernel disables autosuspend (the
+-power/level attribute is initialized to "on") for all devices other
++power/control attribute is initialized to "on") for all devices other
+ than hubs. Hubs, at least, appear to be reasonably well-behaved in
+ this regard.
+
+@@ -373,7 +376,7 @@ usb_autopm_put_interface() in its close
+ patterns are possible.
+
+ The autosuspend attempts mentioned above will often fail for one
+-reason or another. For example, the power/level attribute might be
++reason or another. For example, the power/control attribute might be
+ set to "on", or another interface in the same device might not be
+ idle. This is perfectly normal. If the reason for failure was that
+ the device hasn't been idle for long enough, a timer is scheduled to
+@@ -394,12 +397,12 @@ Drivers can enable autosuspend for their
+
+ in their probe() routine, if they know that the device is capable of
+ suspending and resuming correctly. This is exactly equivalent to
+-writing "auto" to the device's power/level attribute. Likewise,
++writing "auto" to the device's power/control attribute. Likewise,
+ drivers can disable autosuspend by calling
+
+ usb_disable_autosuspend(struct usb_device *udev);
+
+-This is exactly the same as writing "on" to the power/level attribute.
++This is exactly the same as writing "on" to the power/control attribute.
+
+ Sometimes a driver needs to make sure that remote wakeup is enabled
+ during autosuspend. For example, there's not much point
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -383,12 +383,23 @@ static DEVICE_ATTR(autosuspend, S_IRUGO
+ static const char on_string[] = "on";
+ static const char auto_string[] = "auto";
+
++static void warn_level(void) {
++ static int level_warned;
++
++ if (!level_warned) {
++ level_warned = 1;
++ printk(KERN_WARNING "WARNING! power/level is deprecated; "
++ "use power/control instead\n");
++ }
++}
++
+ static ssize_t
+ show_level(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct usb_device *udev = to_usb_device(dev);
+ const char *p = auto_string;
+
++ warn_level();
+ if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
+ p = on_string;
+ return sprintf(buf, "%s\n", p);
+@@ -403,6 +414,7 @@ set_level(struct device *dev, struct dev
+ char *cp;
+ int rc = count;
+
++ warn_level();
+ cp = memchr(buf, '\n', count);
+ if (cp)
+ len = cp - buf;
diff --git a/usb/usb-don-t-enable-remote-wakeup-by-default.patch b/usb/usb-don-t-enable-remote-wakeup-by-default.patch
new file mode 100644
index 00000000000000..0eef17f4964813
--- /dev/null
+++ b/usb/usb-don-t-enable-remote-wakeup-by-default.patch
@@ -0,0 +1,36 @@
+From stern@rowland.harvard.edu Thu Apr 29 12:51:34 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 2 Apr 2010 13:21:33 -0400 (EDT)
+Subject: USB: don't enable remote wakeup by default
+To: Greg KH <greg@kroah.com>
+Message-ID: <Pine.LNX.4.44L0.1004021309260.1324-100000@iolanthe.rowland.org>
+
+
+This patch (as1364) avoids enabling remote wakeup by default on all
+non-root-hub USB devices. Individual drivers or userspace will have
+to enable it wherever it is needed, such as for keyboards or network
+interfaces. Note: This affects only system sleep, not autosuspend.
+
+External hubs will continue to relay wakeup requests received from
+downstream through their upstream port, even when remote wakeup is not
+enabled for the hub itself. Disabling remote wakeup on a hub merely
+prevents it from generating wakeup requests in response to connect,
+disconnect, and overcurrent events.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1784,7 +1784,6 @@ int usb_new_device(struct usb_device *ud
+ * sysfs power/wakeup controls wakeup enabled/disabled
+ */
+ device_init_wakeup(&udev->dev, 0);
+- device_set_wakeup_enable(&udev->dev, 1);
+ }
+
+ /* Tell the runtime-PM framework the device is active */
diff --git a/usb/usb-ehci-elide-i-o-watchdog-on-nec-parts.patch b/usb/usb-ehci-elide-i-o-watchdog-on-nec-parts.patch
new file mode 100644
index 00000000000000..86de5bc11b377a
--- /dev/null
+++ b/usb/usb-ehci-elide-i-o-watchdog-on-nec-parts.patch
@@ -0,0 +1,34 @@
+From davem@davemloft.net Thu Apr 29 13:05:42 2010
+From: David Miller <davem@davemloft.net>
+Date: Tue, 06 Apr 2010 18:26:03 -0700 (PDT)
+Subject: USB: ehci: Elide I/O watchdog on NEC parts
+To: linux-usb@vger.kernel.org
+Cc: dbrownell@users.sourceforge.net
+Message-ID: <20100406.182603.267636346.davem@davemloft.net>
+
+
+
+I've been running with this patch on my Niagara2 boxes for some time
+and have not seen any ill effects yet. Maybe we can stash this into
+the USB tree to get exposure for some time in -next and if anything
+crops up we can simply revert?
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -109,6 +109,9 @@ static int ehci_pci_setup(struct usb_hcd
+ return retval;
+
+ switch (pdev->vendor) {
++ case PCI_VENDOR_ID_NEC:
++ ehci->need_io_watchdog = 0;
++ break;
+ case PCI_VENDOR_ID_INTEL:
+ ehci->need_io_watchdog = 0;
+ if (pdev->device == 0x27cc) {
diff --git a/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch
new file mode 100644
index 00000000000000..1bd7002f0875ba
--- /dev/null
+++ b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch
@@ -0,0 +1,508 @@
+From stern@rowland.harvard.edu Thu Apr 29 12:50:58 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 2 Apr 2010 13:27:28 -0400 (EDT)
+Subject: USB: fix usbmon and DMA mapping for scatter-gather URBs
+To: Greg KH <greg@kroah.com>
+Cc: David Vrabel <david.vrabel@csr.com>, Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Message-ID: <Pine.LNX.4.44L0.1004021324010.1324-100000@iolanthe.rowland.org>
+
+
+This patch (as1368) fixes a rather obscure bug in usbmon: When tracing
+URBs sent by the scatter-gather library, it accesses the data buffers
+while they are still mapped for DMA.
+
+The solution is to move the mapping and unmapping out of the s-g
+library and into the usual place in hcd.c. This requires the addition
+of new URB flag bits to describe the kind of mapping needed, since we
+have to call dma_map_sg() if the HCD supports native scatter-gather
+operation and dma_map_page() if it doesn't. The nice thing about
+having the new flags is that they simplify the testing for unmapping.
+
+The patch removes the only caller of usb_buffer_[un]map_sg(), so those
+functions are #if'ed out. A later patch will remove them entirely.
+
+As a result of this change, urb->sg will be set in situations where
+it wasn't set previously. Hence the xhci and whci drivers are
+adjusted to test urb->num_sgs instead, which retains its original
+meaning and is nonzero only when the HCD has to handle a scatterlist.
+
+Finally, even when a submission error occurs we don't want to hand
+URBs to usbmon before they are unmapped. The submission path is
+rearranged so that map_urb_for_dma() is called only for non-root-hub
+URBs and unmap_urb_for_dma() is called immediately after a submission
+error. This simplifies the error handling.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/core/hcd.c | 169 ++++++++++++++++++++++++++-----------------
+ drivers/usb/core/message.c | 45 ++---------
+ drivers/usb/core/urb.c | 9 +-
+ drivers/usb/core/usb.c | 4 +
+ drivers/usb/host/whci/qset.c | 2
+ drivers/usb/host/xhci-ring.c | 2
+ drivers/usb/mon/mon_bin.c | 2
+ drivers/usb/mon/mon_text.c | 4 -
+ include/linux/usb.h | 9 ++
+ 9 files changed, 138 insertions(+), 108 deletions(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1260,6 +1260,51 @@ static void hcd_free_coherent(struct usb
+ *dma_handle = 0;
+ }
+
++static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
++{
++ enum dma_data_direction dir;
++
++ if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
++ dma_unmap_single(hcd->self.controller,
++ urb->setup_dma,
++ sizeof(struct usb_ctrlrequest),
++ DMA_TO_DEVICE);
++ else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL)
++ hcd_free_coherent(urb->dev->bus,
++ &urb->setup_dma,
++ (void **) &urb->setup_packet,
++ sizeof(struct usb_ctrlrequest),
++ DMA_TO_DEVICE);
++
++ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
++ if (urb->transfer_flags & URB_DMA_MAP_SG)
++ dma_unmap_sg(hcd->self.controller,
++ urb->sg->sg,
++ urb->num_sgs,
++ dir);
++ else if (urb->transfer_flags & URB_DMA_MAP_PAGE)
++ dma_unmap_page(hcd->self.controller,
++ urb->transfer_dma,
++ urb->transfer_buffer_length,
++ dir);
++ else if (urb->transfer_flags & URB_DMA_MAP_SINGLE)
++ dma_unmap_single(hcd->self.controller,
++ urb->transfer_dma,
++ urb->transfer_buffer_length,
++ dir);
++ else if (urb->transfer_flags & URB_MAP_LOCAL)
++ hcd_free_coherent(urb->dev->bus,
++ &urb->transfer_dma,
++ &urb->transfer_buffer,
++ urb->transfer_buffer_length,
++ dir);
++
++ /* Make it safe to call this routine more than once */
++ urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
++ URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
++ URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
++}
++
+ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+ {
+@@ -1271,8 +1316,6 @@ static int map_urb_for_dma(struct usb_hc
+ * unless it uses pio or talks to another transport,
+ * or uses the provided scatter gather list for bulk.
+ */
+- if (is_root_hub(urb->dev))
+- return 0;
+
+ if (usb_endpoint_xfer_control(&urb->ep->desc)
+ && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+@@ -1285,6 +1328,7 @@ static int map_urb_for_dma(struct usb_hc
+ if (dma_mapping_error(hcd->self.controller,
+ urb->setup_dma))
+ return -EAGAIN;
++ urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
+ } else if (hcd->driver->flags & HCD_LOCAL_MEM)
+ ret = hcd_alloc_coherent(
+ urb->dev->bus, mem_flags,
+@@ -1292,20 +1336,57 @@ static int map_urb_for_dma(struct usb_hc
+ (void **)&urb->setup_packet,
+ sizeof(struct usb_ctrlrequest),
+ DMA_TO_DEVICE);
++ if (ret)
++ return ret;
++ urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
+ }
+
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+- if (ret == 0 && urb->transfer_buffer_length != 0
++ if (urb->transfer_buffer_length != 0
+ && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+ if (hcd->self.uses_dma) {
+- urb->transfer_dma = dma_map_single (
+- hcd->self.controller,
+- urb->transfer_buffer,
+- urb->transfer_buffer_length,
+- dir);
+- if (dma_mapping_error(hcd->self.controller,
++ if (urb->num_sgs) {
++ int n = dma_map_sg(
++ hcd->self.controller,
++ urb->sg->sg,
++ urb->num_sgs,
++ dir);
++ if (n <= 0)
++ ret = -EAGAIN;
++ else
++ urb->transfer_flags |= URB_DMA_MAP_SG;
++ if (n != urb->num_sgs) {
++ urb->num_sgs = n;
++ urb->transfer_flags |=
++ URB_DMA_SG_COMBINED;
++ }
++ } else if (urb->sg) {
++ struct scatterlist *sg;
++
++ sg = (struct scatterlist *) urb->sg;
++ urb->transfer_dma = dma_map_page(
++ hcd->self.controller,
++ sg_page(sg),
++ sg->offset,
++ urb->transfer_buffer_length,
++ dir);
++ if (dma_mapping_error(hcd->self.controller,
+ urb->transfer_dma))
+- return -EAGAIN;
++ ret = -EAGAIN;
++ else
++ urb->transfer_flags |= URB_DMA_MAP_PAGE;
++ } else {
++ urb->transfer_dma = dma_map_single(
++ hcd->self.controller,
++ urb->transfer_buffer,
++ urb->transfer_buffer_length,
++ dir);
++ if (dma_mapping_error(hcd->self.controller,
++ urb->transfer_dma))
++ ret = -EAGAIN;
++ else
++ urb->transfer_flags |= URB_DMA_MAP_SINGLE;
++ }
+ } else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+ ret = hcd_alloc_coherent(
+ urb->dev->bus, mem_flags,
+@@ -1313,55 +1394,16 @@ static int map_urb_for_dma(struct usb_hc
+ &urb->transfer_buffer,
+ urb->transfer_buffer_length,
+ dir);
+-
+- if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
+- && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+- hcd_free_coherent(urb->dev->bus,
+- &urb->setup_dma,
+- (void **)&urb->setup_packet,
+- sizeof(struct usb_ctrlrequest),
+- DMA_TO_DEVICE);
++ if (ret == 0)
++ urb->transfer_flags |= URB_MAP_LOCAL;
+ }
++ if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
++ URB_SETUP_MAP_LOCAL)))
++ unmap_urb_for_dma(hcd, urb);
+ }
+ return ret;
+ }
+
+-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+-{
+- enum dma_data_direction dir;
+-
+- if (is_root_hub(urb->dev))
+- return;
+-
+- if (usb_endpoint_xfer_control(&urb->ep->desc)
+- && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+- if (hcd->self.uses_dma)
+- dma_unmap_single(hcd->self.controller, urb->setup_dma,
+- sizeof(struct usb_ctrlrequest),
+- DMA_TO_DEVICE);
+- else if (hcd->driver->flags & HCD_LOCAL_MEM)
+- hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+- (void **)&urb->setup_packet,
+- sizeof(struct usb_ctrlrequest),
+- DMA_TO_DEVICE);
+- }
+-
+- dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+- if (urb->transfer_buffer_length != 0
+- && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+- if (hcd->self.uses_dma)
+- dma_unmap_single(hcd->self.controller,
+- urb->transfer_dma,
+- urb->transfer_buffer_length,
+- dir);
+- else if (hcd->driver->flags & HCD_LOCAL_MEM)
+- hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+- &urb->transfer_buffer,
+- urb->transfer_buffer_length,
+- dir);
+- }
+-}
+-
+ /*-------------------------------------------------------------------------*/
+
+ /* may be called in any context with a valid urb->dev usecount
+@@ -1390,21 +1432,20 @@ int usb_hcd_submit_urb (struct urb *urb,
+ * URBs must be submitted in process context with interrupts
+ * enabled.
+ */
+- status = map_urb_for_dma(hcd, urb, mem_flags);
+- if (unlikely(status)) {
+- usbmon_urb_submit_error(&hcd->self, urb, status);
+- goto error;
+- }
+
+- if (is_root_hub(urb->dev))
++ if (is_root_hub(urb->dev)) {
+ status = rh_urb_enqueue(hcd, urb);
+- else
+- status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
++ } else {
++ status = map_urb_for_dma(hcd, urb, mem_flags);
++ if (likely(status == 0)) {
++ status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
++ if (unlikely(status))
++ unmap_urb_for_dma(hcd, urb);
++ }
++ }
+
+ if (unlikely(status)) {
+ usbmon_urb_submit_error(&hcd->self, urb, status);
+- unmap_urb_for_dma(hcd, urb);
+- error:
+ urb->hcpriv = NULL;
+ INIT_LIST_HEAD(&urb->urb_list);
+ atomic_dec(&urb->use_count);
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -259,9 +259,6 @@ static void sg_clean(struct usb_sg_reque
+ kfree(io->urbs);
+ io->urbs = NULL;
+ }
+- if (io->dev->dev.dma_mask != NULL)
+- usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
+- io->sg, io->nents);
+ io->dev = NULL;
+ }
+
+@@ -364,7 +361,6 @@ int usb_sg_init(struct usb_sg_request *i
+ {
+ int i;
+ int urb_flags;
+- int dma;
+ int use_sg;
+
+ if (!io || !dev || !sg
+@@ -378,21 +374,9 @@ int usb_sg_init(struct usb_sg_request *i
+ io->pipe = pipe;
+ io->sg = sg;
+ io->nents = nents;
+-
+- /* not all host controllers use DMA (like the mainstream pci ones);
+- * they can use PIO (sl811) or be software over another transport.
+- */
+- dma = (dev->dev.dma_mask != NULL);
+- if (dma)
+- io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
+- sg, nents);
+- else
+- io->entries = nents;
++ io->entries = nents;
+
+ /* initialize all the urbs we'll use */
+- if (io->entries <= 0)
+- return io->entries;
+-
+ if (dev->bus->sg_tablesize > 0) {
+ io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
+ use_sg = true;
+@@ -404,8 +388,6 @@ int usb_sg_init(struct usb_sg_request *i
+ goto nomem;
+
+ urb_flags = 0;
+- if (dma)
+- urb_flags |= URB_NO_TRANSFER_DMA_MAP;
+ if (usb_pipein(pipe))
+ urb_flags |= URB_SHORT_NOT_OK;
+
+@@ -423,12 +405,13 @@ int usb_sg_init(struct usb_sg_request *i
+
+ io->urbs[0]->complete = sg_complete;
+ io->urbs[0]->context = io;
++
+ /* A length of zero means transfer the whole sg list */
+ io->urbs[0]->transfer_buffer_length = length;
+ if (length == 0) {
+ for_each_sg(sg, sg, io->entries, i) {
+ io->urbs[0]->transfer_buffer_length +=
+- sg_dma_len(sg);
++ sg->length;
+ }
+ }
+ io->urbs[0]->sg = io;
+@@ -454,26 +437,16 @@ int usb_sg_init(struct usb_sg_request *i
+ io->urbs[i]->context = io;
+
+ /*
+- * Some systems need to revert to PIO when DMA is temporarily
+- * unavailable. For their sakes, both transfer_buffer and
+- * transfer_dma are set when possible.
+- *
+- * Note that if IOMMU coalescing occurred, we cannot
+- * trust sg_page anymore, so check if S/G list shrunk.
++ * Some systems can't use DMA; they use PIO instead.
++ * For their sakes, transfer_buffer is set whenever
++ * possible.
+ */
+- if (io->nents == io->entries && !PageHighMem(sg_page(sg)))
++ if (!PageHighMem(sg_page(sg)))
+ io->urbs[i]->transfer_buffer = sg_virt(sg);
+ else
+ io->urbs[i]->transfer_buffer = NULL;
+
+- if (dma) {
+- io->urbs[i]->transfer_dma = sg_dma_address(sg);
+- len = sg_dma_len(sg);
+- } else {
+- /* hc may use _only_ transfer_buffer */
+- len = sg->length;
+- }
+-
++ len = sg->length;
+ if (length) {
+ len = min_t(unsigned, len, length);
+ length -= len;
+@@ -481,6 +454,8 @@ int usb_sg_init(struct usb_sg_request *i
+ io->entries = i + 1;
+ }
+ io->urbs[i]->transfer_buffer_length = len;
++
++ io->urbs[i]->sg = (struct usb_sg_request *) sg;
+ }
+ io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+ }
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -333,9 +333,12 @@ int usb_submit_urb(struct urb *urb, gfp_
+ is_out = usb_endpoint_dir_out(&ep->desc);
+ }
+
+- /* Cache the direction for later use */
+- urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
+- (is_out ? URB_DIR_OUT : URB_DIR_IN);
++ /* Clear the internal flags and cache the direction for later use */
++ urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
++ URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
++ URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
++ URB_DMA_SG_COMBINED);
++ urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN);
+
+ if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
+ dev->state < USB_STATE_CONFIGURED)
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -881,6 +881,7 @@ void usb_buffer_unmap(struct urb *urb)
+ EXPORT_SYMBOL_GPL(usb_buffer_unmap);
+ #endif /* 0 */
+
++#if 0
+ /**
+ * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
+ * @dev: device to which the scatterlist will be mapped
+@@ -924,6 +925,7 @@ int usb_buffer_map_sg(const struct usb_d
+ is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM;
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
++#endif
+
+ /* XXX DISABLED, no users currently. If you wish to re-enable this
+ * XXX please determine whether the sync is to transfer ownership of
+@@ -960,6 +962,7 @@ void usb_buffer_dmasync_sg(const struct
+ EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
+ #endif
+
++#if 0
+ /**
+ * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
+ * @dev: device to which the scatterlist will be mapped
+@@ -985,6 +988,7 @@ void usb_buffer_unmap_sg(const struct us
+ is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
++#endif
+
+ /* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
+ #ifdef MODULE
+--- a/drivers/usb/host/whci/qset.c
++++ b/drivers/usb/host/whci/qset.c
+@@ -646,7 +646,7 @@ int qset_add_urb(struct whc *whc, struct
+ wurb->urb = urb;
+ INIT_WORK(&wurb->dequeue_work, urb_dequeue_work);
+
+- if (urb->sg) {
++ if (urb->num_sgs) {
+ ret = qset_add_urb_sg(whc, qset, urb, mem_flags);
+ if (ret == -EINVAL) {
+ qset_free_stds(qset, urb);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1938,7 +1938,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ int running_total, trb_buff_len, ret;
+ u64 addr;
+
+- if (urb->sg)
++ if (urb->num_sgs)
+ return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
+
+ ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -416,7 +416,7 @@ static unsigned int mon_bin_get_data(con
+
+ } else {
+ /* If IOMMU coalescing occurred, we cannot trust sg_page */
+- if (urb->sg->nents != urb->num_sgs) {
++ if (urb->transfer_flags & URB_DMA_SG_COMBINED) {
+ *flag = 'D';
+ return length;
+ }
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -161,9 +161,7 @@ static inline char mon_text_get_data(str
+ } else {
+ struct scatterlist *sg = urb->sg->sg;
+
+- /* If IOMMU coalescing occurred, we cannot trust sg_page */
+- if (urb->sg->nents != urb->num_sgs ||
+- PageHighMem(sg_page(sg)))
++ if (PageHighMem(sg_page(sg)))
+ return 'D';
+
+ /* For the text interface we copy only the first sg buffer */
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -965,10 +965,19 @@ extern int usb_disabled(void);
+ * needed */
+ #define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
+
++/* The following flags are used internally by usbcore and HCDs */
+ #define URB_DIR_IN 0x0200 /* Transfer from device to host */
+ #define URB_DIR_OUT 0
+ #define URB_DIR_MASK URB_DIR_IN
+
++#define URB_DMA_MAP_SINGLE 0x00010000 /* Non-scatter-gather mapping */
++#define URB_DMA_MAP_PAGE 0x00020000 /* HCD-unsupported S-G */
++#define URB_DMA_MAP_SG 0x00040000 /* HCD-supported S-G */
++#define URB_MAP_LOCAL 0x00080000 /* HCD-local-memory mapping */
++#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
++#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
++#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
++
+ struct usb_iso_packet_descriptor {
+ unsigned int offset;
+ unsigned int length; /* expected length */
diff --git a/usb/usb-gadget-allow-larger-configuration-descriptors.patch b/usb/usb-gadget-allow-larger-configuration-descriptors.patch
new file mode 100644
index 00000000000000..17b8cc46ee8131
--- /dev/null
+++ b/usb/usb-gadget-allow-larger-configuration-descriptors.patch
@@ -0,0 +1,30 @@
+From Robert.Lukassen@tomtom.com Thu Apr 29 12:38:47 2010
+From: "Robert Lukassen" <Robert.Lukassen@tomtom.com>
+Date: Tue, 30 Mar 2010 14:14:01 +0200
+Subject: usb: gadget: Allow larger configuration descriptors
+Message-ID: <D6DB9C7EDECDA944B870F62B5870086229B68C@NL-EXC-06.intra.local>
+
+
+The composite framework allows gadgets with more than one function. This
+can lead to situations where the configuration descriptor is larger than
+the maximum of 512 bytes currently allowed by the composite framework.
+This patch proposes to double that limit to 1024.
+
+Signed-off-by: Robert Lukassen <robert.lukassen@tomtom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/composite.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -36,7 +36,7 @@
+ */
+
+ /* big enough to hold our biggest descriptor */
+-#define USB_BUFSIZ 512
++#define USB_BUFSIZ 1024
+
+ static struct usb_composite_driver *composite;
+
diff --git a/usb/usb-gadget-f_mass_storage-per-function.patch b/usb/usb-gadget-f_mass_storage-per-function.patch
new file mode 100644
index 00000000000000..4db35b39d744df
--- /dev/null
+++ b/usb/usb-gadget-f_mass_storage-per-function.patch
@@ -0,0 +1,88 @@
+From m.nazarewicz@samsung.com Thu Apr 29 12:40:28 2010
+From: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Date: Mon, 29 Mar 2010 14:01:32 +0200
+Subject: USB: gadget: f_mass_storage: per function
+To: Johannes Weiner <hannes@cmpxchg.org>, David Brownell <dbrownell@users.sourceforge.net>
+Cc: Peter Korsgaard <jacmet@sunsite.dk>, Marek Szyprowski <m.szyprowski@samsung.com>, Kyungmin Park <kyungmin.park@samsung.com>, Michal Nazarewicz <m.nazarewicz@samsung.com>
+Message-ID: <7d23e1b58c7263c7b2479a409f9bf9d7922df3ab.1269863632.git.mina86@mina86.com>
+
+
+Mass Storage Function (MSF) used the same descriptors for each
+usb_function instance (meaning usb_function::descriptors of different
+functions pointed to the same static area (the same was true for
+usb_function::hs_descriptors)).
+
+This would leads to problems if MSF were used in several USB
+configurations with different interface and/or endpoint numbers.
+Descriptors for all configurations would have interface/endpoint
+numbers overwritten by the values valid for the last configuration.
+
+This patch adds code that copies the descriptors each time MSF is
+added to USB configuration (that is for each usb_function).
+
+Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Cc: Kyungmin Park <kyungmin.park@samsung.com>
+
+---
+ drivers/usb/gadget/f_mass_storage.c | 28 ++++++++++++++++++++++------
+ 1 file changed, 22 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -2919,6 +2919,8 @@ static void fsg_unbind(struct usb_config
+
+ DBG(fsg, "unbind\n");
+ fsg_common_put(fsg->common);
++ usb_free_descriptors(fsg->function.descriptors);
++ usb_free_descriptors(fsg->function.hs_descriptors);
+ kfree(fsg);
+ }
+
+@@ -2959,7 +2961,9 @@ static int __init fsg_bind(struct usb_co
+ fsg_fs_bulk_in_desc.bEndpointAddress;
+ fsg_hs_bulk_out_desc.bEndpointAddress =
+ fsg_fs_bulk_out_desc.bEndpointAddress;
+- f->hs_descriptors = fsg_hs_function;
++ f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
++ if (unlikely(!f->hs_descriptors))
++ return -ENOMEM;
+ }
+
+ return 0;
+@@ -2991,7 +2995,11 @@ static int fsg_add(struct usb_composite_
+
+ fsg->function.name = FSG_DRIVER_DESC;
+ fsg->function.strings = fsg_strings_array;
+- fsg->function.descriptors = fsg_fs_function;
++ fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
++ if (unlikely(!fsg->function.descriptors)) {
++ rc = -ENOMEM;
++ goto error_free_fsg;
++ }
+ fsg->function.bind = fsg_bind;
+ fsg->function.unbind = fsg_unbind;
+ fsg->function.setup = fsg_setup;
+@@ -3006,11 +3014,19 @@ static int fsg_add(struct usb_composite_
+ * call to usb_add_function() was successful. */
+
+ rc = usb_add_function(c, &fsg->function);
++ if (unlikely(rc))
++ goto error_free_all;
++
++ fsg_common_get(fsg->common);
++ return 0;
+
+- if (likely(rc == 0))
+- fsg_common_get(fsg->common);
+- else
+- kfree(fsg);
++error_free_all:
++ usb_free_descriptors(fsg->function.descriptors);
++ /* fsg_bind() might have copied those; or maybe not? who cares
++ * -- free it just in case. */
++ usb_free_descriptors(fsg->function.hs_descriptors);
++error_free_fsg:
++ kfree(fsg);
+
+ return rc;
+ }
diff --git a/usb/usb-improve-runtime-remote-wakeup-settings.patch b/usb/usb-improve-runtime-remote-wakeup-settings.patch
new file mode 100644
index 00000000000000..d716bd5357879c
--- /dev/null
+++ b/usb/usb-improve-runtime-remote-wakeup-settings.patch
@@ -0,0 +1,77 @@
+From stern@rowland.harvard.edu Thu Apr 29 12:51:13 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 2 Apr 2010 13:18:50 -0400 (EDT)
+Subject: USB: improve runtime remote wakeup settings
+To: Greg KH <greg@kroah.com>
+Message-ID: <Pine.LNX.4.44L0.1004021306440.1324-100000@iolanthe.rowland.org>
+
+
+This patch (as1362) adjusts the way the USB autosuspend routines
+handle remote-wakeup settings. They aren't supposed to use
+device_may_wakeup(); that test is intended only for system sleep, not
+runtime power management. Instead the code checks to see if any
+interface drivers need remote wakeup; if they do then it is enabled,
+provided the device is capable of it.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/driver.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1485,9 +1485,6 @@ int usb_autoresume_device(struct usb_dev
+ * 0, a delayed autosuspend request for @intf's device is attempted. The
+ * attempt may fail (see autosuspend_check()).
+ *
+- * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+- * take place only if the device's remote-wakeup facility is enabled.
+- *
+ * This routine can run only in process context.
+ */
+ void usb_autopm_put_interface(struct usb_interface *intf)
+@@ -1672,14 +1669,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interfa
+ /* Internal routine to check whether we may autosuspend a device. */
+ static int autosuspend_check(struct usb_device *udev)
+ {
+- int i;
++ int w, i;
+ struct usb_interface *intf;
+ unsigned long suspend_time, j;
+
+ /* Fail if autosuspend is disabled, or any interfaces are in use, or
+ * any interface drivers require remote wakeup but it isn't available.
+ */
+- udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++ w = 0;
+ if (udev->actconfig) {
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ intf = udev->actconfig->interface[i];
+@@ -1693,12 +1690,7 @@ static int autosuspend_check(struct usb_
+ continue;
+ if (atomic_read(&intf->dev.power.usage_count) > 0)
+ return -EBUSY;
+- if (intf->needs_remote_wakeup &&
+- !udev->do_remote_wakeup) {
+- dev_dbg(&udev->dev, "remote wakeup needed "
+- "for autosuspend\n");
+- return -EOPNOTSUPP;
+- }
++ w |= intf->needs_remote_wakeup;
+
+ /* Don't allow autosuspend if the device will need
+ * a reset-resume and any of its interface drivers
+@@ -1714,6 +1706,11 @@ static int autosuspend_check(struct usb_
+ }
+ }
+ }
++ if (w && !device_can_wakeup(&udev->dev)) {
++ dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
++ return -EOPNOTSUPP;
++ }
++ udev->do_remote_wakeup = w;
+
+ /* If everything is okay but the device hasn't been idle for long
+ * enough, queue a delayed autosuspend request.
diff --git a/usb/usb-musb-add-extvbus-in-musb_board_data.patch b/usb/usb-musb-add-extvbus-in-musb_board_data.patch
new file mode 100644
index 00000000000000..fb63d60b0b5b3f
--- /dev/null
+++ b/usb/usb-musb-add-extvbus-in-musb_board_data.patch
@@ -0,0 +1,56 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:37:54 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:27 +0200
+Subject: usb: musb: Add extvbus in musb_board_data
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-11-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+
+EXTVBUS programming is required by OMAP3EVM REV >=E to supply 500mA
+power so adding a flag which can be used by musb driver to program
+EXTVBUS.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-omap2/board-omap3evm.c | 3 +++
+ arch/arm/mach-omap2/usb-musb.c | 1 +
+ arch/arm/plat-omap/include/plat/usb.h | 1 +
+ 3 files changed, 5 insertions(+)
+
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -702,6 +702,9 @@ static void __init omap3_evm_init(void)
+ omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
+ ehci_pdata.reset_gpio_port[1] = 21;
+
++ /* EVM REV >= E can supply 500mA with EXTVBUS programming */
++ musb_board_data.power = 500;
++ musb_board_data.extvbus = 1;
+ } else {
+ /* setup EHCI phy reset on MDC */
+ omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
+--- a/arch/arm/mach-omap2/usb-musb.c
++++ b/arch/arm/mach-omap2/usb-musb.c
+@@ -107,6 +107,7 @@ void __init usb_musb_init(struct omap_mu
+ musb_plat.board_data = board_data;
+ musb_plat.power = board_data->power >> 1;
+ musb_plat.mode = board_data->mode;
++ musb_plat.extvbus = board_data->extvbus;
+
+ if (platform_device_register(&musb_device) < 0)
+ printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -47,6 +47,7 @@ struct omap_musb_board_data {
+ u8 interface_type;
+ u8 mode;
+ u16 power;
++ unsigned extvbus:1;
+ };
+
+ enum musb_interface {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
diff --git a/usb/usb-musb-add-ulpi-access-operations.patch b/usb/usb-musb-add-ulpi-access-operations.patch
new file mode 100644
index 00000000000000..953c2607b1bccb
--- /dev/null
+++ b/usb/usb-musb-add-ulpi-access-operations.patch
@@ -0,0 +1,150 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:38:12 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:28 +0200
+Subject: usb: musb: add ulpi access operations
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-12-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+
+This adds helper functions for ULPI access, and implements
+otg_io_access_ops for musb.
+
+Signed-off-by: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_core.c | 86 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/musb/musb_regs.h | 10 +++++
+ 2 files changed, 96 insertions(+)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -149,6 +149,87 @@ static inline struct musb *dev_to_musb(s
+
+ /*-------------------------------------------------------------------------*/
+
++#ifndef CONFIG_BLACKFIN
++static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset)
++{
++ void __iomem *addr = otg->io_priv;
++ int i = 0;
++ u8 r;
++ u8 power;
++
++ /* Make sure the transceiver is not in low power mode */
++ power = musb_readb(addr, MUSB_POWER);
++ power &= ~MUSB_POWER_SUSPENDM;
++ musb_writeb(addr, MUSB_POWER, power);
++
++ /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the
++ * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
++ */
++
++ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
++ musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
++ MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
++
++ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
++ & MUSB_ULPI_REG_CMPLT)) {
++ i++;
++ if (i == 10000) {
++ DBG(3, "ULPI read timed out\n");
++ return -ETIMEDOUT;
++ }
++
++ }
++ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
++ r &= ~MUSB_ULPI_REG_CMPLT;
++ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
++
++ return musb_readb(addr, MUSB_ULPI_REG_DATA);
++}
++
++static int musb_ulpi_write(struct otg_transceiver *otg,
++ u32 offset, u32 data)
++{
++ void __iomem *addr = otg->io_priv;
++ int i = 0;
++ u8 r = 0;
++ u8 power;
++
++ /* Make sure the transceiver is not in low power mode */
++ power = musb_readb(addr, MUSB_POWER);
++ power &= ~MUSB_POWER_SUSPENDM;
++ musb_writeb(addr, MUSB_POWER, power);
++
++ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
++ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
++ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
++
++ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
++ & MUSB_ULPI_REG_CMPLT)) {
++ i++;
++ if (i == 10000) {
++ DBG(3, "ULPI write timed out\n");
++ return -ETIMEDOUT;
++ }
++ }
++
++ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
++ r &= ~MUSB_ULPI_REG_CMPLT;
++ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
++
++ return 0;
++}
++#else
++#define musb_ulpi_read(a, b) NULL
++#define musb_ulpi_write(a, b, c) NULL
++#endif
++
++static struct otg_io_access_ops musb_ulpi_access = {
++ .read = musb_ulpi_read,
++ .write = musb_ulpi_write,
++};
++
++/*-------------------------------------------------------------------------*/
++
+ #if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
+
+ /*
+@@ -1954,6 +2035,11 @@ bad_config:
+ goto fail3;
+ }
+
++ if (!musb->xceiv->io_ops) {
++ musb->xceiv->io_priv = musb->mregs;
++ musb->xceiv->io_ops = &musb_ulpi_access;
++ }
++
+ #ifndef CONFIG_MUSB_PIO_ONLY
+ if (use_dma && dev->dma_mask) {
+ struct dma_controller *c;
+--- a/drivers/usb/musb/musb_regs.h
++++ b/drivers/usb/musb/musb_regs.h
+@@ -75,6 +75,10 @@
+ /* MUSB ULPI VBUSCONTROL */
+ #define MUSB_ULPI_USE_EXTVBUS 0x01
+ #define MUSB_ULPI_USE_EXTVBUSIND 0x02
++/* ULPI_REG_CONTROL */
++#define MUSB_ULPI_REG_REQ (1 << 0)
++#define MUSB_ULPI_REG_CMPLT (1 << 1)
++#define MUSB_ULPI_RDN_WR (1 << 2)
+
+ /* TESTMODE */
+ #define MUSB_TEST_FORCE_HOST 0x80
+@@ -251,6 +255,12 @@
+ /* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */
+ #define MUSB_HWVERS 0x6C /* 8 bit */
+ #define MUSB_ULPI_BUSCONTROL 0x70 /* 8 bit */
++#define MUSB_ULPI_INT_MASK 0x72 /* 8 bit */
++#define MUSB_ULPI_INT_SRC 0x73 /* 8 bit */
++#define MUSB_ULPI_REG_DATA 0x74 /* 8 bit */
++#define MUSB_ULPI_REG_ADDR 0x75 /* 8 bit */
++#define MUSB_ULPI_REG_CONTROL 0x76 /* 8 bit */
++#define MUSB_ULPI_RAW_DATA 0x77 /* 8 bit */
+
+ #define MUSB_EPINFO 0x78 /* 8 bit */
+ #define MUSB_RAMINFO 0x79 /* 8 bit */
diff --git a/usb/usb-musb-debugfs-musb_exit_debugfs-can-be-called-on-probe.patch b/usb/usb-musb-debugfs-musb_exit_debugfs-can-be-called-on-probe.patch
new file mode 100644
index 00000000000000..d8d98e5f69d477
--- /dev/null
+++ b/usb/usb-musb-debugfs-musb_exit_debugfs-can-be-called-on-probe.patch
@@ -0,0 +1,57 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:35:06 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:18 +0200
+Subject: usb: musb: debugfs: musb_exit_debugfs() can be called on probe
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-2-git-send-email-felipe.balbi@nokia.com>
+
+
+when we fail to probe(), we can call musb_exit_debugfs().
+Allow that by removing section annotations.
+
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/musb_core.c | 7 +++++--
+ drivers/usb/musb/musb_debugfs.c | 2 +-
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2056,12 +2056,12 @@ bad_config:
+
+ status = musb_init_debugfs(musb);
+ if (status < 0)
+- goto fail2;
++ goto fail4;
+
+ #ifdef CONFIG_SYSFS
+ status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
+ if (status)
+- goto fail4;
++ goto fail5;
+ #endif
+
+ dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
+@@ -2078,6 +2078,9 @@ bad_config:
+
+ return 0;
+
++fail5:
++ musb_exit_debugfs(musb);
++
+ fail4:
+ if (!is_otg_enabled(musb) && is_host_enabled(musb))
+ usb_remove_hcd(musb_to_hcd(musb));
+--- a/drivers/usb/musb/musb_debugfs.c
++++ b/drivers/usb/musb/musb_debugfs.c
+@@ -289,7 +289,7 @@ err0:
+ return ret;
+ }
+
+-void __exit musb_exit_debugfs(struct musb *musb)
++void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
+ {
+ debugfs_remove_recursive(musb_debugfs_root);
+ }
diff --git a/usb/usb-musb-makefile-remove-unexistent-config-option.patch b/usb/usb-musb-makefile-remove-unexistent-config-option.patch
new file mode 100644
index 00000000000000..a0a0229ff51d66
--- /dev/null
+++ b/usb/usb-musb-makefile-remove-unexistent-config-option.patch
@@ -0,0 +1,35 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:37:42 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:26 +0200
+Subject: usb: musb: Makefile: remove unexistent config option
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-10-git-send-email-felipe.balbi@nokia.com>
+
+
+Remove the unexistent CONFIG_USB_INVENTRA_MUSB_HAS_AHB_ID
+option from our Makefile.
+
+Problem reported by Sergei Shtylyov <sshtylyov@mvista.com>
+
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/Makefile | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/usb/musb/Makefile
++++ b/drivers/usb/musb/Makefile
+@@ -72,12 +72,6 @@ endif
+
+ ################################################################################
+
+-# FIXME remove all these extra "-DMUSB_* things, stick to CONFIG_*
+-
+-ifeq ($(CONFIG_USB_INVENTRA_MUSB_HAS_AHB_ID),y)
+- EXTRA_CFLAGS += -DMUSB_AHB_ID
+-endif
+-
+ # Debugging
+
+ ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
diff --git a/usb/usb-musb-omap2430-remove-unused-define.patch b/usb/usb-musb-omap2430-remove-unused-define.patch
new file mode 100644
index 00000000000000..b4aa2458f7a36a
--- /dev/null
+++ b/usb/usb-musb-omap2430-remove-unused-define.patch
@@ -0,0 +1,34 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:37:19 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:24 +0200
+Subject: usb: musb: omap2430: remove unused define
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-8-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Anand Gadiyar <gadiyar@ti.com>
+
+get_cpu_rev() is unused in this driver. It is probably legacy
+code. So remove it.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/omap2430.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -39,10 +39,6 @@
+ #include "musb_core.h"
+ #include "omap2430.h"
+
+-#ifdef CONFIG_ARCH_OMAP3430
+-#define get_cpu_rev() 2
+-#endif
+-
+
+ static struct timer_list musb_idle_timer;
+
diff --git a/usb/usb-musb-omap2430.c-remove-unnecessary-includes.patch b/usb/usb-musb-omap2430.c-remove-unnecessary-includes.patch
new file mode 100644
index 00000000000000..c685df0750c210
--- /dev/null
+++ b/usb/usb-musb-omap2430.c-remove-unnecessary-includes.patch
@@ -0,0 +1,31 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:37:30 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:25 +0200
+Subject: usb: musb: omap2430.c: remove unnecessary includes
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-9-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Anand Gadiyar <gadiyar@ti.com>
+
+We don't need mach-types and hardware.h
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/omap2430.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -32,8 +32,6 @@
+ #include <linux/clk.h>
+ #include <linux/io.h>
+
+-#include <asm/mach-types.h>
+-#include <mach/hardware.h>
+ #include <plat/mux.h>
+
+ #include "musb_core.h"
diff --git a/usb/usb-musb-support-host-gadget-role-switching-on-blackfin-parts.patch b/usb/usb-musb-support-host-gadget-role-switching-on-blackfin-parts.patch
new file mode 100644
index 00000000000000..a7fd811c4d414f
--- /dev/null
+++ b/usb/usb-musb-support-host-gadget-role-switching-on-blackfin-parts.patch
@@ -0,0 +1,138 @@
+From felipe.balbi@nokia.com Thu Apr 29 12:35:57 2010
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Thu, 25 Mar 2010 13:25:19 +0200
+Subject: USB: musb: support host/gadget role switching on Blackfin parts
+To: Greg KH <greg@kroah.com>
+Message-ID: <1269516328-28267-3-git-send-email-felipe.balbi@nokia.com>
+
+
+From: Cliff Cai <cliff.cai@analog.com>
+
+Signed-off-by: Cliff Cai <cliff.cai@analog.com>
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/blackfin.c | 69 ++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 63 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -170,6 +170,13 @@ static irqreturn_t blackfin_interrupt(in
+ retval = musb_interrupt(musb);
+ }
+
++ /* Start sampling ID pin, when plug is removed from MUSB */
++ if (is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE
++ || musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
++ mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
++ musb->a_wait_bcon = TIMER_DELAY;
++ }
++
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return retval;
+@@ -180,6 +187,7 @@ static void musb_conn_timer_handler(unsi
+ struct musb *musb = (void *)_musb;
+ unsigned long flags;
+ u16 val;
++ static u8 toggle;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+@@ -187,10 +195,44 @@ static void musb_conn_timer_handler(unsi
+ case OTG_STATE_A_WAIT_BCON:
+ /* Start a new session */
+ val = musb_readw(musb->mregs, MUSB_DEVCTL);
++ val &= ~MUSB_DEVCTL_SESSION;
++ musb_writew(musb->mregs, MUSB_DEVCTL, val);
+ val |= MUSB_DEVCTL_SESSION;
+ musb_writew(musb->mregs, MUSB_DEVCTL, val);
++ /* Check if musb is host or peripheral. */
++ val = musb_readw(musb->mregs, MUSB_DEVCTL);
++
++ if (!(val & MUSB_DEVCTL_BDEVICE)) {
++ gpio_set_value(musb->config->gpio_vrsel, 1);
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
++ } else {
++ gpio_set_value(musb->config->gpio_vrsel, 0);
++ /* Ignore VBUSERROR and SUSPEND IRQ */
++ val = musb_readb(musb->mregs, MUSB_INTRUSBE);
++ val &= ~MUSB_INTR_VBUSERROR;
++ musb_writeb(musb->mregs, MUSB_INTRUSBE, val);
++
++ val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR;
++ musb_writeb(musb->mregs, MUSB_INTRUSB, val);
++ if (is_otg_enabled(musb))
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++ else
++ musb_writeb(musb->mregs, MUSB_POWER, MUSB_POWER_HSENAB);
++ }
++ mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
++ break;
++ case OTG_STATE_B_IDLE:
+
++ if (!is_peripheral_enabled(musb))
++ break;
++ /* Start a new session. It seems that MUSB needs taking
++ * some time to recognize the type of the plug inserted?
++ */
++ val = musb_readw(musb->mregs, MUSB_DEVCTL);
++ val |= MUSB_DEVCTL_SESSION;
++ musb_writew(musb->mregs, MUSB_DEVCTL, val);
+ val = musb_readw(musb->mregs, MUSB_DEVCTL);
++
+ if (!(val & MUSB_DEVCTL_BDEVICE)) {
+ gpio_set_value(musb->config->gpio_vrsel, 1);
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+@@ -205,12 +247,27 @@ static void musb_conn_timer_handler(unsi
+ val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR;
+ musb_writeb(musb->mregs, MUSB_INTRUSB, val);
+
+- val = MUSB_POWER_HSENAB;
+- musb_writeb(musb->mregs, MUSB_POWER, val);
++ /* Toggle the Soft Conn bit, so that we can response to
++ * the inserting of either A-plug or B-plug.
++ */
++ if (toggle) {
++ val = musb_readb(musb->mregs, MUSB_POWER);
++ val &= ~MUSB_POWER_SOFTCONN;
++ musb_writeb(musb->mregs, MUSB_POWER, val);
++ toggle = 0;
++ } else {
++ val = musb_readb(musb->mregs, MUSB_POWER);
++ val |= MUSB_POWER_SOFTCONN;
++ musb_writeb(musb->mregs, MUSB_POWER, val);
++ toggle = 1;
++ }
++ /* The delay time is set to 1/4 second by default,
++ * shortening it, if accelerating A-plug detection
++ * is needed in OTG mode.
++ */
++ mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY / 4);
+ }
+- mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
+ break;
+-
+ default:
+ DBG(1, "%s state not handled\n", otg_state_string(musb));
+ break;
+@@ -222,7 +279,7 @@ static void musb_conn_timer_handler(unsi
+
+ void musb_platform_enable(struct musb *musb)
+ {
+- if (is_host_enabled(musb)) {
++ if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+ mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
+ musb->a_wait_bcon = TIMER_DELAY;
+ }
+@@ -256,7 +313,7 @@ static int bfin_set_power(struct otg_tra
+
+ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+ {
+- if (is_host_enabled(musb))
++ if (!is_otg_enabled(musb) && is_host_enabled(musb))
+ mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
+ }
+
diff --git a/usb/usb-omap-switch-to-subsys_initcall-for-isp1301-transceiver.patch b/usb/usb-omap-switch-to-subsys_initcall-for-isp1301-transceiver.patch
new file mode 100644
index 00000000000000..99c0a57b5f3974
--- /dev/null
+++ b/usb/usb-omap-switch-to-subsys_initcall-for-isp1301-transceiver.patch
@@ -0,0 +1,27 @@
+From Viral.Mehta@lntinfotech.com Thu Apr 29 13:05:59 2010
+From: Viral Mehta <Viral.Mehta@lntinfotech.com>
+Date: Tue, 6 Apr 2010 11:51:00 +0530
+Subject: USB: omap: switch to subsys_initcall for isp1301 transceiver
+Message-ID: <70376CA23424B34D86F1C7DE6B9973430254343A39@VSHINMSMBX01.vshodc.lntinfotech.com>
+
+
+isp1301 transceiver driver init should be done before we do ohci omap init
+
+Signed-off-by: Viral Mehta <viral.mehta@lntinfotech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/otg/isp1301_omap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/otg/isp1301_omap.c
++++ b/drivers/usb/otg/isp1301_omap.c
+@@ -1654,7 +1654,7 @@ static int __init isp_init(void)
+ {
+ return i2c_add_driver(&isp1301_driver);
+ }
+-module_init(isp_init);
++subsys_initcall(isp_init);
+
+ static void __exit isp_exit(void)
+ {
diff --git a/usb/usb-option-use-generic-usb-wwan-code.patch b/usb/usb-option-use-generic-usb-wwan-code.patch
new file mode 100644
index 00000000000000..ca57a8e1d08786
--- /dev/null
+++ b/usb/usb-option-use-generic-usb-wwan-code.patch
@@ -0,0 +1,783 @@
+From mjg@redhat.com Thu Apr 29 12:53:45 2010
+From: Matthew Garrett <mjg@redhat.com>
+Date: Thu, 1 Apr 2010 12:31:08 -0400
+Subject: USB: option: Use generic USB wwan code
+To: linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Matthew Garrett <mjg@redhat.com>
+Message-ID: <1270139470-24360-2-git-send-email-mjg@redhat.com>
+
+
+As this code was simply factored out of option, this is a simple
+conversion.
+
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/Kconfig | 1
+ drivers/usb/serial/option.c | 672 +-------------------------------------------
+ 2 files changed, 27 insertions(+), 646 deletions(-)
+
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -581,6 +581,7 @@ config USB_SERIAL_WWAN
+
+ config USB_SERIAL_OPTION
+ tristate "USB driver for GSM and CDMA modems"
++ select USB_SERIAL_WWAN
+ help
+ Say Y here if you have a GSM or CDMA modem that's connected to USB.
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -42,35 +42,14 @@
+ #include <linux/bitops.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
++#include "usb-wwan.h"
+
+ /* Function prototypes */
+ static int option_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
+-static int option_open(struct tty_struct *tty, struct usb_serial_port *port);
+-static void option_close(struct usb_serial_port *port);
+-static void option_dtr_rts(struct usb_serial_port *port, int on);
+-
+-static int option_startup(struct usb_serial *serial);
+-static void option_disconnect(struct usb_serial *serial);
+-static void option_release(struct usb_serial *serial);
+-static int option_write_room(struct tty_struct *tty);
+-
++static int option_send_setup(struct usb_serial_port *port);
+ static void option_instat_callback(struct urb *urb);
+
+-static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count);
+-static int option_chars_in_buffer(struct tty_struct *tty);
+-static void option_set_termios(struct tty_struct *tty,
+- struct usb_serial_port *port, struct ktermios *old);
+-static int option_tiocmget(struct tty_struct *tty, struct file *file);
+-static int option_tiocmset(struct tty_struct *tty, struct file *file,
+- unsigned int set, unsigned int clear);
+-static int option_send_setup(struct usb_serial_port *port);
+-#ifdef CONFIG_PM
+-static int option_suspend(struct usb_serial *serial, pm_message_t message);
+-static int option_resume(struct usb_serial *serial);
+-#endif
+-
+ /* Vendor and product IDs */
+ #define OPTION_VENDOR_ID 0x0AF0
+ #define OPTION_PRODUCT_COLT 0x5000
+@@ -757,22 +736,22 @@ static struct usb_serial_driver option_1
+ .id_table = option_ids,
+ .num_ports = 1,
+ .probe = option_probe,
+- .open = option_open,
+- .close = option_close,
+- .dtr_rts = option_dtr_rts,
+- .write = option_write,
+- .write_room = option_write_room,
+- .chars_in_buffer = option_chars_in_buffer,
+- .set_termios = option_set_termios,
+- .tiocmget = option_tiocmget,
+- .tiocmset = option_tiocmset,
+- .attach = option_startup,
+- .disconnect = option_disconnect,
+- .release = option_release,
++ .open = usb_wwan_open,
++ .close = usb_wwan_close,
++ .dtr_rts = usb_wwan_dtr_rts,
++ .write = usb_wwan_write,
++ .write_room = usb_wwan_write_room,
++ .chars_in_buffer = usb_wwan_chars_in_buffer,
++ .set_termios = usb_wwan_set_termios,
++ .tiocmget = usb_wwan_tiocmget,
++ .tiocmset = usb_wwan_tiocmset,
++ .attach = usb_wwan_startup,
++ .disconnect = usb_wwan_disconnect,
++ .release = usb_wwan_release,
+ .read_int_callback = option_instat_callback,
+ #ifdef CONFIG_PM
+- .suspend = option_suspend,
+- .resume = option_resume,
++ .suspend = usb_wwan_suspend,
++ .resume = usb_wwan_resume,
+ #endif
+ };
+
+@@ -785,13 +764,6 @@ static int debug;
+ #define IN_BUFLEN 4096
+ #define OUT_BUFLEN 4096
+
+-struct option_intf_private {
+- spinlock_t susp_lock;
+- unsigned int suspended:1;
+- int in_flight;
+- struct option_blacklist_info *blacklist_info;
+-};
+-
+ struct option_port_private {
+ /* Input endpoints and buffer for this port */
+ struct urb *in_urbs[N_IN_URB];
+@@ -848,8 +820,7 @@ module_exit(option_exit);
+ static int option_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+ {
+- struct option_intf_private *data;
+-
++ struct usb_wwan_intf_private *data;
+ /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
+ if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
+ serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
+@@ -862,11 +833,13 @@ static int option_probe(struct usb_seria
+ serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
+ return -ENODEV;
+
+- data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL);
++ data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
++
+ if (!data)
+ return -ENOMEM;
++ data->send_setup = option_send_setup;
+ spin_lock_init(&data->susp_lock);
+- data->blacklist_info = (struct option_blacklist_info*) id->driver_info;
++ data->private = (void *)id->driver_info;
+ return 0;
+ }
+
+@@ -887,205 +860,6 @@ static enum option_blacklist_reason is_b
+ return OPTION_BLACKLIST_NONE;
+ }
+
+-static void option_set_termios(struct tty_struct *tty,
+- struct usb_serial_port *port, struct ktermios *old_termios)
+-{
+- dbg("%s", __func__);
+- /* Doesn't support option setting */
+- tty_termios_copy_hw(tty->termios, old_termios);
+- option_send_setup(port);
+-}
+-
+-static int option_tiocmget(struct tty_struct *tty, struct file *file)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- unsigned int value;
+- struct option_port_private *portdata;
+-
+- portdata = usb_get_serial_port_data(port);
+-
+- value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
+- ((portdata->dtr_state) ? TIOCM_DTR : 0) |
+- ((portdata->cts_state) ? TIOCM_CTS : 0) |
+- ((portdata->dsr_state) ? TIOCM_DSR : 0) |
+- ((portdata->dcd_state) ? TIOCM_CAR : 0) |
+- ((portdata->ri_state) ? TIOCM_RNG : 0);
+-
+- return value;
+-}
+-
+-static int option_tiocmset(struct tty_struct *tty, struct file *file,
+- unsigned int set, unsigned int clear)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- struct option_port_private *portdata;
+-
+- portdata = usb_get_serial_port_data(port);
+-
+- /* FIXME: what locks portdata fields ? */
+- if (set & TIOCM_RTS)
+- portdata->rts_state = 1;
+- if (set & TIOCM_DTR)
+- portdata->dtr_state = 1;
+-
+- if (clear & TIOCM_RTS)
+- portdata->rts_state = 0;
+- if (clear & TIOCM_DTR)
+- portdata->dtr_state = 0;
+- return option_send_setup(port);
+-}
+-
+-/* Write */
+-static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count)
+-{
+- struct option_port_private *portdata;
+- struct option_intf_private *intfdata;
+- int i;
+- int left, todo;
+- struct urb *this_urb = NULL; /* spurious */
+- int err;
+- unsigned long flags;
+-
+- portdata = usb_get_serial_port_data(port);
+- intfdata = port->serial->private;
+-
+- dbg("%s: write (%d chars)", __func__, count);
+-
+- i = 0;
+- left = count;
+- for (i = 0; left > 0 && i < N_OUT_URB; i++) {
+- todo = left;
+- if (todo > OUT_BUFLEN)
+- todo = OUT_BUFLEN;
+-
+- this_urb = portdata->out_urbs[i];
+- if (test_and_set_bit(i, &portdata->out_busy)) {
+- if (time_before(jiffies,
+- portdata->tx_start_time[i] + 10 * HZ))
+- continue;
+- usb_unlink_urb(this_urb);
+- continue;
+- }
+- dbg("%s: endpoint %d buf %d", __func__,
+- usb_pipeendpoint(this_urb->pipe), i);
+-
+- err = usb_autopm_get_interface_async(port->serial->interface);
+- if (err < 0)
+- break;
+-
+- /* send the data */
+- memcpy(this_urb->transfer_buffer, buf, todo);
+- this_urb->transfer_buffer_length = todo;
+-
+- spin_lock_irqsave(&intfdata->susp_lock, flags);
+- if (intfdata->suspended) {
+- usb_anchor_urb(this_urb, &portdata->delayed);
+- spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+- } else {
+- intfdata->in_flight++;
+- spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+- err = usb_submit_urb(this_urb, GFP_ATOMIC);
+- if (err) {
+- dbg("usb_submit_urb %p (write bulk) failed "
+- "(%d)", this_urb, err);
+- clear_bit(i, &portdata->out_busy);
+- spin_lock_irqsave(&intfdata->susp_lock, flags);
+- intfdata->in_flight--;
+- spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+- continue;
+- }
+- }
+-
+- portdata->tx_start_time[i] = jiffies;
+- buf += todo;
+- left -= todo;
+- }
+-
+- count -= left;
+- dbg("%s: wrote (did %d)", __func__, count);
+- return count;
+-}
+-
+-static void option_indat_callback(struct urb *urb)
+-{
+- int err;
+- int endpoint;
+- struct usb_serial_port *port;
+- struct tty_struct *tty;
+- unsigned char *data = urb->transfer_buffer;
+- int status = urb->status;
+-
+- dbg("%s: %p", __func__, urb);
+-
+- endpoint = usb_pipeendpoint(urb->pipe);
+- port = urb->context;
+-
+- 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 on endpoint %02x.",
+- __func__, status, endpoint);
+- return;
+- default:
+- dbg("%s: nonzero status: %d on endpoint %02x.",
+- __func__, status, endpoint);
+- goto exit;
+- }
+-
+- if (urb->actual_length) {
+- tty = tty_port_tty_get(&port->port);
+- tty_insert_flip_string(tty, data, urb->actual_length);
+- tty_flip_buffer_push(tty);
+- tty_kref_put(tty);
+- } else
+- dbg("%s: empty read urb received", __func__);
+-
+-exit:
+- /* Resubmit urb so we continue receiving */
+- err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (err && err != -EPERM)
+- printk(KERN_ERR "%s: resubmit read urb failed. "
+- "(%d)", __func__, err);
+- else
+- usb_mark_last_busy(port->serial->dev);
+-
+- return;
+-}
+-
+-static void option_outdat_callback(struct urb *urb)
+-{
+- struct usb_serial_port *port;
+- struct option_port_private *portdata;
+- struct option_intf_private *intfdata;
+- int i;
+-
+- dbg("%s", __func__);
+-
+- port = urb->context;
+- intfdata = port->serial->private;
+-
+- usb_serial_port_softint(port);
+- usb_autopm_put_interface_async(port->serial->interface);
+- portdata = usb_get_serial_port_data(port);
+- spin_lock(&intfdata->susp_lock);
+- intfdata->in_flight--;
+- spin_unlock(&intfdata->susp_lock);
+-
+- for (i = 0; i < N_OUT_URB; ++i) {
+- if (portdata->out_urbs[i] == urb) {
+- smp_mb__before_clear_bit();
+- clear_bit(i, &portdata->out_busy);
+- break;
+- }
+- }
+-}
+-
+ static void option_instat_callback(struct urb *urb)
+ {
+ int err;
+@@ -1142,183 +916,6 @@ static void option_instat_callback(struc
+ }
+ }
+
+-static int option_write_room(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- struct option_port_private *portdata;
+- int i;
+- int data_len = 0;
+- struct urb *this_urb;
+-
+- portdata = usb_get_serial_port_data(port);
+-
+- for (i = 0; i < N_OUT_URB; i++) {
+- this_urb = portdata->out_urbs[i];
+- if (this_urb && !test_bit(i, &portdata->out_busy))
+- data_len += OUT_BUFLEN;
+- }
+-
+- dbg("%s: %d", __func__, data_len);
+- return data_len;
+-}
+-
+-static int option_chars_in_buffer(struct tty_struct *tty)
+-{
+- struct usb_serial_port *port = tty->driver_data;
+- struct option_port_private *portdata;
+- int i;
+- int data_len = 0;
+- struct urb *this_urb;
+-
+- portdata = usb_get_serial_port_data(port);
+-
+- for (i = 0; i < N_OUT_URB; i++) {
+- this_urb = portdata->out_urbs[i];
+- /* FIXME: This locking is insufficient as this_urb may
+- go unused during the test */
+- if (this_urb && test_bit(i, &portdata->out_busy))
+- data_len += this_urb->transfer_buffer_length;
+- }
+- dbg("%s: %d", __func__, data_len);
+- return data_len;
+-}
+-
+-static int option_open(struct tty_struct *tty, struct usb_serial_port *port)
+-{
+- struct option_port_private *portdata;
+- struct option_intf_private *intfdata;
+- struct usb_serial *serial = port->serial;
+- int i, err;
+- struct urb *urb;
+-
+- portdata = usb_get_serial_port_data(port);
+- intfdata = serial->private;
+-
+- dbg("%s", __func__);
+-
+- /* Start reading from the IN endpoint */
+- for (i = 0; i < N_IN_URB; i++) {
+- urb = portdata->in_urbs[i];
+- if (!urb)
+- continue;
+- err = usb_submit_urb(urb, GFP_KERNEL);
+- if (err) {
+- dbg("%s: submit urb %d failed (%d) %d",
+- __func__, i, err,
+- urb->transfer_buffer_length);
+- }
+- }
+-
+- option_send_setup(port);
+-
+- serial->interface->needs_remote_wakeup = 1;
+- spin_lock_irq(&intfdata->susp_lock);
+- portdata->opened = 1;
+- spin_unlock_irq(&intfdata->susp_lock);
+- usb_autopm_put_interface(serial->interface);
+-
+- return 0;
+-}
+-
+-static void option_dtr_rts(struct usb_serial_port *port, int on)
+-{
+- struct usb_serial *serial = port->serial;
+- struct option_port_private *portdata;
+-
+- dbg("%s", __func__);
+- portdata = usb_get_serial_port_data(port);
+- mutex_lock(&serial->disc_mutex);
+- portdata->rts_state = on;
+- portdata->dtr_state = on;
+- if (serial->dev)
+- option_send_setup(port);
+- mutex_unlock(&serial->disc_mutex);
+-}
+-
+-
+-static void option_close(struct usb_serial_port *port)
+-{
+- int i;
+- struct usb_serial *serial = port->serial;
+- struct option_port_private *portdata;
+- struct option_intf_private *intfdata = port->serial->private;
+-
+- dbg("%s", __func__);
+- portdata = usb_get_serial_port_data(port);
+-
+- if (serial->dev) {
+- /* Stop reading/writing urbs */
+- spin_lock_irq(&intfdata->susp_lock);
+- portdata->opened = 0;
+- spin_unlock_irq(&intfdata->susp_lock);
+-
+- for (i = 0; i < N_IN_URB; i++)
+- usb_kill_urb(portdata->in_urbs[i]);
+- for (i = 0; i < N_OUT_URB; i++)
+- usb_kill_urb(portdata->out_urbs[i]);
+- usb_autopm_get_interface(serial->interface);
+- serial->interface->needs_remote_wakeup = 0;
+- }
+-}
+-
+-/* Helper functions used by option_setup_urbs */
+-static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+- int dir, void *ctx, char *buf, int len,
+- void (*callback)(struct urb *))
+-{
+- struct urb *urb;
+-
+- if (endpoint == -1)
+- return NULL; /* endpoint not needed */
+-
+- urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
+- if (urb == NULL) {
+- dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
+- return NULL;
+- }
+-
+- /* Fill URB using supplied data. */
+- usb_fill_bulk_urb(urb, serial->dev,
+- usb_sndbulkpipe(serial->dev, endpoint) | dir,
+- buf, len, callback, ctx);
+-
+- return urb;
+-}
+-
+-/* Setup urbs */
+-static void option_setup_urbs(struct usb_serial *serial)
+-{
+- int i, j;
+- struct usb_serial_port *port;
+- struct option_port_private *portdata;
+-
+- dbg("%s", __func__);
+-
+- for (i = 0; i < serial->num_ports; i++) {
+- port = serial->port[i];
+- portdata = usb_get_serial_port_data(port);
+-
+- /* Do indat endpoints first */
+- for (j = 0; j < N_IN_URB; ++j) {
+- portdata->in_urbs[j] = option_setup_urb(serial,
+- port->bulk_in_endpointAddress,
+- USB_DIR_IN, port,
+- portdata->in_buffer[j],
+- IN_BUFLEN, option_indat_callback);
+- }
+-
+- /* outdat endpoints */
+- for (j = 0; j < N_OUT_URB; ++j) {
+- portdata->out_urbs[j] = option_setup_urb(serial,
+- port->bulk_out_endpointAddress,
+- USB_DIR_OUT, port,
+- portdata->out_buffer[j],
+- OUT_BUFLEN, option_outdat_callback);
+- }
+- }
+-}
+-
+-
+ /** send RTS/DTR state to the port.
+ *
+ * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
+@@ -1327,15 +924,16 @@ static void option_setup_urbs(struct usb
+ static int option_send_setup(struct usb_serial_port *port)
+ {
+ struct usb_serial *serial = port->serial;
+- struct option_intf_private *intfdata =
+- (struct option_intf_private *) serial->private;
++ struct usb_wwan_intf_private *intfdata =
++ (struct usb_wwan_intf_private *) serial->private;
+ struct option_port_private *portdata;
+ int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ int val = 0;
+ dbg("%s", __func__);
+
+- if (is_blacklisted(ifNum, intfdata->blacklist_info) ==
+- OPTION_BLACKLIST_SENDSETUP) {
++ if (is_blacklisted(ifNum,
++ (struct option_blacklist_info *) intfdata->private)
++ == OPTION_BLACKLIST_SENDSETUP) {
+ dbg("No send_setup on blacklisted interface #%d\n", ifNum);
+ return -EIO;
+ }
+@@ -1352,224 +950,6 @@ static int option_send_setup(struct usb_
+ 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ }
+
+-static int option_startup(struct usb_serial *serial)
+-{
+- int i, j, err;
+- struct usb_serial_port *port;
+- struct option_port_private *portdata;
+- u8 *buffer;
+-
+- dbg("%s", __func__);
+-
+- /* Now setup per port private data */
+- for (i = 0; i < serial->num_ports; i++) {
+- port = serial->port[i];
+- portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+- if (!portdata) {
+- dbg("%s: kmalloc for option_port_private (%d) failed!.",
+- __func__, i);
+- return 1;
+- }
+- init_usb_anchor(&portdata->delayed);
+-
+- for (j = 0; j < N_IN_URB; j++) {
+- buffer = (u8 *)__get_free_page(GFP_KERNEL);
+- if (!buffer)
+- goto bail_out_error;
+- portdata->in_buffer[j] = buffer;
+- }
+-
+- for (j = 0; j < N_OUT_URB; j++) {
+- buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+- if (!buffer)
+- goto bail_out_error2;
+- portdata->out_buffer[j] = buffer;
+- }
+-
+- usb_set_serial_port_data(port, portdata);
+-
+- if (!port->interrupt_in_urb)
+- continue;
+- err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+- if (err)
+- dbg("%s: submit irq_in urb failed %d",
+- __func__, err);
+- }
+- option_setup_urbs(serial);
+- return 0;
+-
+-bail_out_error2:
+- for (j = 0; j < N_OUT_URB; j++)
+- kfree(portdata->out_buffer[j]);
+-bail_out_error:
+- for (j = 0; j < N_IN_URB; j++)
+- if (portdata->in_buffer[j])
+- free_page((unsigned long)portdata->in_buffer[j]);
+- kfree(portdata);
+- return 1;
+-}
+-
+-static void stop_read_write_urbs(struct usb_serial *serial)
+-{
+- int i, j;
+- struct usb_serial_port *port;
+- struct option_port_private *portdata;
+-
+- /* Stop reading/writing urbs */
+- for (i = 0; i < serial->num_ports; ++i) {
+- port = serial->port[i];
+- portdata = usb_get_serial_port_data(port);
+- for (j = 0; j < N_IN_URB; j++)
+- usb_kill_urb(portdata->in_urbs[j]);
+- for (j = 0; j < N_OUT_URB; j++)
+- usb_kill_urb(portdata->out_urbs[j]);
+- }
+-}
+-
+-static void option_disconnect(struct usb_serial *serial)
+-{
+- dbg("%s", __func__);
+-
+- stop_read_write_urbs(serial);
+-}
+-
+-static void option_release(struct usb_serial *serial)
+-{
+- int i, j;
+- struct usb_serial_port *port;
+- struct option_port_private *portdata;
+-
+- dbg("%s", __func__);
+-
+- /* Now free them */
+- for (i = 0; i < serial->num_ports; ++i) {
+- port = serial->port[i];
+- portdata = usb_get_serial_port_data(port);
+-
+- for (j = 0; j < N_IN_URB; j++) {
+- if (portdata->in_urbs[j]) {
+- usb_free_urb(portdata->in_urbs[j]);
+- free_page((unsigned long)
+- portdata->in_buffer[j]);
+- portdata->in_urbs[j] = NULL;
+- }
+- }
+- for (j = 0; j < N_OUT_URB; j++) {
+- if (portdata->out_urbs[j]) {
+- usb_free_urb(portdata->out_urbs[j]);
+- kfree(portdata->out_buffer[j]);
+- portdata->out_urbs[j] = NULL;
+- }
+- }
+- }
+-
+- /* Now free per port private data */
+- for (i = 0; i < serial->num_ports; i++) {
+- port = serial->port[i];
+- kfree(usb_get_serial_port_data(port));
+- }
+-}
+-
+-#ifdef CONFIG_PM
+-static int option_suspend(struct usb_serial *serial, pm_message_t message)
+-{
+- struct option_intf_private *intfdata = serial->private;
+- int b;
+-
+- dbg("%s entered", __func__);
+-
+- if (message.event & PM_EVENT_AUTO) {
+- spin_lock_irq(&intfdata->susp_lock);
+- b = intfdata->in_flight;
+- spin_unlock_irq(&intfdata->susp_lock);
+-
+- if (b)
+- return -EBUSY;
+- }
+-
+- spin_lock_irq(&intfdata->susp_lock);
+- intfdata->suspended = 1;
+- spin_unlock_irq(&intfdata->susp_lock);
+- stop_read_write_urbs(serial);
+-
+- return 0;
+-}
+-
+-static void play_delayed(struct usb_serial_port *port)
+-{
+- struct option_intf_private *data;
+- struct option_port_private *portdata;
+- struct urb *urb;
+- int err;
+-
+- portdata = usb_get_serial_port_data(port);
+- data = port->serial->private;
+- while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+- err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (!err)
+- data->in_flight++;
+- }
+-}
+-
+-static int option_resume(struct usb_serial *serial)
+-{
+- int i, j;
+- struct usb_serial_port *port;
+- struct option_intf_private *intfdata = serial->private;
+- struct option_port_private *portdata;
+- struct urb *urb;
+- int err = 0;
+-
+- dbg("%s entered", __func__);
+- /* get the interrupt URBs resubmitted unconditionally */
+- for (i = 0; i < serial->num_ports; i++) {
+- port = serial->port[i];
+- if (!port->interrupt_in_urb) {
+- dbg("%s: No interrupt URB for port %d", __func__, i);
+- continue;
+- }
+- err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+- dbg("Submitted interrupt URB for port %d (result %d)", i, err);
+- if (err < 0) {
+- err("%s: Error %d for interrupt URB of port%d",
+- __func__, err, i);
+- goto err_out;
+- }
+- }
+-
+- for (i = 0; i < serial->num_ports; i++) {
+- /* walk all ports */
+- port = serial->port[i];
+- portdata = usb_get_serial_port_data(port);
+-
+- /* skip closed ports */
+- spin_lock_irq(&intfdata->susp_lock);
+- if (!portdata->opened) {
+- spin_unlock_irq(&intfdata->susp_lock);
+- continue;
+- }
+-
+- for (j = 0; j < N_IN_URB; j++) {
+- urb = portdata->in_urbs[j];
+- err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (err < 0) {
+- err("%s: Error %d for bulk URB %d",
+- __func__, err, i);
+- spin_unlock_irq(&intfdata->susp_lock);
+- goto err_out;
+- }
+- }
+- play_delayed(port);
+- spin_unlock_irq(&intfdata->susp_lock);
+- }
+- spin_lock_irq(&intfdata->susp_lock);
+- intfdata->suspended = 0;
+- spin_unlock_irq(&intfdata->susp_lock);
+-err_out:
+- return err;
+-}
+-#endif
+-
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_VERSION(DRIVER_VERSION);
diff --git a/usb/usb-otg-twl4030-use-the-global-ulpi-register-definitions.patch b/usb/usb-otg-twl4030-use-the-global-ulpi-register-definitions.patch
new file mode 100644
index 00000000000000..28b2c9f9a6b9f8
--- /dev/null
+++ b/usb/usb-otg-twl4030-use-the-global-ulpi-register-definitions.patch
@@ -0,0 +1,215 @@
+From ext-heikki.krogerus@nokia.com Thu Apr 29 12:48:28 2010
+From: "Krogerus Heikki (EXT-Teleca/Helsinki)" <ext-heikki.krogerus@nokia.com>
+Date: Wed, 31 Mar 2010 10:18:05 +0300
+Subject: usb: otg: twl4030: use the global ULPI register definitions
+To: sshtylyov@mvista.com
+Cc: linux-usb@vger.kernel.org, felipe.balbi@nokia.com, Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Message-ID: <1270019885-23689-1-git-send-email-ext-heikki.krogerus@nokia.com>
+
+
+From: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+
+Rely on the global ULPI register definitions
+
+Signed-off-by: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/otg/twl4030-usb.c | 108 +++---------------------------------------
+ 1 file changed, 8 insertions(+), 100 deletions(-)
+
+--- a/drivers/usb/otg/twl4030-usb.c
++++ b/drivers/usb/otg/twl4030-usb.c
+@@ -33,6 +33,7 @@
+ #include <linux/io.h>
+ #include <linux/delay.h>
+ #include <linux/usb/otg.h>
++#include <linux/usb/ulpi.h>
+ #include <linux/i2c/twl.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/err.h>
+@@ -41,81 +42,7 @@
+
+ /* Register defines */
+
+-#define VENDOR_ID_LO 0x00
+-#define VENDOR_ID_HI 0x01
+-#define PRODUCT_ID_LO 0x02
+-#define PRODUCT_ID_HI 0x03
+-
+-#define FUNC_CTRL 0x04
+-#define FUNC_CTRL_SET 0x05
+-#define FUNC_CTRL_CLR 0x06
+-#define FUNC_CTRL_SUSPENDM (1 << 6)
+-#define FUNC_CTRL_RESET (1 << 5)
+-#define FUNC_CTRL_OPMODE_MASK (3 << 3) /* bits 3 and 4 */
+-#define FUNC_CTRL_OPMODE_NORMAL (0 << 3)
+-#define FUNC_CTRL_OPMODE_NONDRIVING (1 << 3)
+-#define FUNC_CTRL_OPMODE_DISABLE_BIT_NRZI (2 << 3)
+-#define FUNC_CTRL_TERMSELECT (1 << 2)
+-#define FUNC_CTRL_XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */
+-#define FUNC_CTRL_XCVRSELECT_HS (0 << 0)
+-#define FUNC_CTRL_XCVRSELECT_FS (1 << 0)
+-#define FUNC_CTRL_XCVRSELECT_LS (2 << 0)
+-#define FUNC_CTRL_XCVRSELECT_FS4LS (3 << 0)
+-
+-#define IFC_CTRL 0x07
+-#define IFC_CTRL_SET 0x08
+-#define IFC_CTRL_CLR 0x09
+-#define IFC_CTRL_INTERFACE_PROTECT_DISABLE (1 << 7)
+-#define IFC_CTRL_AUTORESUME (1 << 4)
+-#define IFC_CTRL_CLOCKSUSPENDM (1 << 3)
+-#define IFC_CTRL_CARKITMODE (1 << 2)
+-#define IFC_CTRL_FSLSSERIALMODE_3PIN (1 << 1)
+-
+-#define TWL4030_OTG_CTRL 0x0A
+-#define TWL4030_OTG_CTRL_SET 0x0B
+-#define TWL4030_OTG_CTRL_CLR 0x0C
+-#define TWL4030_OTG_CTRL_DRVVBUS (1 << 5)
+-#define TWL4030_OTG_CTRL_CHRGVBUS (1 << 4)
+-#define TWL4030_OTG_CTRL_DISCHRGVBUS (1 << 3)
+-#define TWL4030_OTG_CTRL_DMPULLDOWN (1 << 2)
+-#define TWL4030_OTG_CTRL_DPPULLDOWN (1 << 1)
+-#define TWL4030_OTG_CTRL_IDPULLUP (1 << 0)
+-
+-#define USB_INT_EN_RISE 0x0D
+-#define USB_INT_EN_RISE_SET 0x0E
+-#define USB_INT_EN_RISE_CLR 0x0F
+-#define USB_INT_EN_FALL 0x10
+-#define USB_INT_EN_FALL_SET 0x11
+-#define USB_INT_EN_FALL_CLR 0x12
+-#define USB_INT_STS 0x13
+-#define USB_INT_LATCH 0x14
+-#define USB_INT_IDGND (1 << 4)
+-#define USB_INT_SESSEND (1 << 3)
+-#define USB_INT_SESSVALID (1 << 2)
+-#define USB_INT_VBUSVALID (1 << 1)
+-#define USB_INT_HOSTDISCONNECT (1 << 0)
+-
+-#define CARKIT_CTRL 0x19
+-#define CARKIT_CTRL_SET 0x1A
+-#define CARKIT_CTRL_CLR 0x1B
+-#define CARKIT_CTRL_MICEN (1 << 6)
+-#define CARKIT_CTRL_SPKRIGHTEN (1 << 5)
+-#define CARKIT_CTRL_SPKLEFTEN (1 << 4)
+-#define CARKIT_CTRL_RXDEN (1 << 3)
+-#define CARKIT_CTRL_TXDEN (1 << 2)
+-#define CARKIT_CTRL_IDGNDDRV (1 << 1)
+-#define CARKIT_CTRL_CARKITPWR (1 << 0)
+-#define CARKIT_PLS_CTRL 0x22
+-#define CARKIT_PLS_CTRL_SET 0x23
+-#define CARKIT_PLS_CTRL_CLR 0x24
+-#define CARKIT_PLS_CTRL_SPKRRIGHT_BIASEN (1 << 3)
+-#define CARKIT_PLS_CTRL_SPKRLEFT_BIASEN (1 << 2)
+-#define CARKIT_PLS_CTRL_RXPLSEN (1 << 1)
+-#define CARKIT_PLS_CTRL_TXPLSEN (1 << 0)
+-
+ #define MCPC_CTRL 0x30
+-#define MCPC_CTRL_SET 0x31
+-#define MCPC_CTRL_CLR 0x32
+ #define MCPC_CTRL_RTSOL (1 << 7)
+ #define MCPC_CTRL_EXTSWR (1 << 6)
+ #define MCPC_CTRL_EXTSWC (1 << 5)
+@@ -125,8 +52,6 @@
+ #define MCPC_CTRL_HS_UART (1 << 0)
+
+ #define MCPC_IO_CTRL 0x33
+-#define MCPC_IO_CTRL_SET 0x34
+-#define MCPC_IO_CTRL_CLR 0x35
+ #define MCPC_IO_CTRL_MICBIASEN (1 << 5)
+ #define MCPC_IO_CTRL_CTS_NPU (1 << 4)
+ #define MCPC_IO_CTRL_RXD_PU (1 << 3)
+@@ -135,19 +60,13 @@
+ #define MCPC_IO_CTRL_RTSTYP (1 << 0)
+
+ #define MCPC_CTRL2 0x36
+-#define MCPC_CTRL2_SET 0x37
+-#define MCPC_CTRL2_CLR 0x38
+ #define MCPC_CTRL2_MCPC_CK_EN (1 << 0)
+
+ #define OTHER_FUNC_CTRL 0x80
+-#define OTHER_FUNC_CTRL_SET 0x81
+-#define OTHER_FUNC_CTRL_CLR 0x82
+ #define OTHER_FUNC_CTRL_BDIS_ACON_EN (1 << 4)
+ #define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2)
+
+ #define OTHER_IFC_CTRL 0x83
+-#define OTHER_IFC_CTRL_SET 0x84
+-#define OTHER_IFC_CTRL_CLR 0x85
+ #define OTHER_IFC_CTRL_OE_INT_EN (1 << 6)
+ #define OTHER_IFC_CTRL_CEA2011_MODE (1 << 5)
+ #define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN (1 << 4)
+@@ -156,11 +75,7 @@
+ #define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0)
+
+ #define OTHER_INT_EN_RISE 0x86
+-#define OTHER_INT_EN_RISE_SET 0x87
+-#define OTHER_INT_EN_RISE_CLR 0x88
+ #define OTHER_INT_EN_FALL 0x89
+-#define OTHER_INT_EN_FALL_SET 0x8A
+-#define OTHER_INT_EN_FALL_CLR 0x8B
+ #define OTHER_INT_STS 0x8C
+ #define OTHER_INT_LATCH 0x8D
+ #define OTHER_INT_VB_SESS_VLD (1 << 7)
+@@ -178,13 +93,9 @@
+ #define ID_RES_GND (1 << 0)
+
+ #define POWER_CTRL 0xAC
+-#define POWER_CTRL_SET 0xAD
+-#define POWER_CTRL_CLR 0xAE
+ #define POWER_CTRL_OTG_ENAB (1 << 5)
+
+ #define OTHER_IFC_CTRL2 0xAF
+-#define OTHER_IFC_CTRL2_SET 0xB0
+-#define OTHER_IFC_CTRL2_CLR 0xB1
+ #define OTHER_IFC_CTRL2_ULPI_STP_LOW (1 << 4)
+ #define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3)
+ #define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2)
+@@ -193,14 +104,10 @@
+ #define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N (1 << 0)
+
+ #define REG_CTRL_EN 0xB2
+-#define REG_CTRL_EN_SET 0xB3
+-#define REG_CTRL_EN_CLR 0xB4
+ #define REG_CTRL_ERROR 0xB5
+ #define ULPI_I2C_CONFLICT_INTEN (1 << 0)
+
+ #define OTHER_FUNC_CTRL2 0xB8
+-#define OTHER_FUNC_CTRL2_SET 0xB9
+-#define OTHER_FUNC_CTRL2_CLR 0xBA
+ #define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0)
+
+ /* following registers do not have separate _clr and _set registers */
+@@ -328,13 +235,13 @@ static inline int twl4030_usb_read(struc
+ static inline int
+ twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+ {
+- return twl4030_usb_write(twl, reg + 1, bits);
++ return twl4030_usb_write(twl, ULPI_SET(reg), bits);
+ }
+
+ static inline int
+ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+ {
+- return twl4030_usb_write(twl, reg + 2, bits);
++ return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -393,11 +300,12 @@ static void twl4030_usb_set_mode(struct
+
+ switch (mode) {
+ case T2_USB_MODE_ULPI:
+- twl4030_usb_clear_bits(twl, IFC_CTRL, IFC_CTRL_CARKITMODE);
++ twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
++ ULPI_IFC_CTRL_CARKITMODE);
+ twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+- twl4030_usb_clear_bits(twl, FUNC_CTRL,
+- FUNC_CTRL_XCVRSELECT_MASK |
+- FUNC_CTRL_OPMODE_MASK);
++ twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
++ ULPI_FUNC_CTRL_XCVRSEL_MASK |
++ ULPI_FUNC_CTRL_OPMODE_MASK);
+ break;
+ case -1:
+ /* FIXME: power on defaults */
diff --git a/usb/usb-pxa27x_udc-use-four-bits-to-store-endpoint-addresses.patch b/usb/usb-pxa27x_udc-use-four-bits-to-store-endpoint-addresses.patch
new file mode 100644
index 00000000000000..470af7b3db3eeb
--- /dev/null
+++ b/usb/usb-pxa27x_udc-use-four-bits-to-store-endpoint-addresses.patch
@@ -0,0 +1,31 @@
+From mreimer@sdgsystems.com Thu Apr 29 12:48:56 2010
+From: Matt Reimer <mreimer@sdgsystems.com>
+Date: Thu, 1 Apr 2010 13:44:04 -0700
+Subject: USB: pxa27x_udc: use four bits to store endpoint addresses
+To: linux-usb@vger.kernel.org
+Cc: Matt Reimer <mreimer@sdgsystems.com>
+Message-ID: <1270154644-13011-1-git-send-email-mreimer@sdgsystems.com>
+
+
+Endpoint addresses on pxa27x can be programmed as 1-15, but since
+only three bits were being used to store the endpoint number it
+was possible to overflow.
+
+Signed-off-by: Matt Reimer <mreimer@sdgsystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/pxa27x_udc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/pxa27x_udc.h
++++ b/drivers/usb/gadget/pxa27x_udc.h
+@@ -360,7 +360,7 @@ struct pxa_ep {
+ * Specific pxa endpoint data, needed for hardware initialization
+ */
+ unsigned dir_in:1;
+- unsigned addr:3;
++ unsigned addr:4;
+ unsigned config:2;
+ unsigned interface:3;
+ unsigned alternate:3;
diff --git a/usb/usb-qcserial-add-support-for-qualcomm-gobi-2000-devices.patch b/usb/usb-qcserial-add-support-for-qualcomm-gobi-2000-devices.patch
new file mode 100644
index 00000000000000..7878d5db875f86
--- /dev/null
+++ b/usb/usb-qcserial-add-support-for-qualcomm-gobi-2000-devices.patch
@@ -0,0 +1,105 @@
+From mjg@redhat.com Thu Apr 29 12:56:50 2010
+From: Matthew Garrett <mjg@redhat.com>
+Date: Thu, 1 Apr 2010 12:31:10 -0400
+Subject: USB: qcserial: Add support for Qualcomm Gobi 2000 devices
+To: linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Anssi Hannula <anssi.hannula@gmail.com>, Matthew Garrett <mjg@redhat.com>
+Message-ID: <1270139470-24360-4-git-send-email-mjg@redhat.com>
+
+
+From: Anssi Hannula <anssi.hannula@gmail.com>
+
+Add ids for Qualcomm Gobi 2000 QDL and Modem modes. Gobi 2000 has a
+single altsetting in QDL mode, so adapt code to handle that.
+
+Firmware upload protocol is also slightly different, with an
+additional firmware file. However, qcserial doesn't handle firmware
+uploading.
+
+Tested on Lenovo Thinkpad T510.
+
+Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com>
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c | 42 +++++++++++++++++++++++++-----------------
+ 1 file changed, 25 insertions(+), 17 deletions(-)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -78,6 +78,8 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
+ {USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */
+ {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
++ {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
++ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, id_table);
+@@ -95,6 +97,7 @@ static struct usb_driver qcdriver = {
+ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+ {
+ struct usb_wwan_intf_private *data;
++ struct usb_host_interface *intf = serial->interface->cur_altsetting;
+ int retval = -ENODEV;
+ __u8 nintf;
+ __u8 ifnum;
+@@ -103,7 +106,7 @@ static int qcprobe(struct usb_serial *se
+
+ nintf = serial->dev->actconfig->desc.bNumInterfaces;
+ dbg("Num Interfaces = %d", nintf);
+- ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
++ ifnum = intf->desc.bInterfaceNumber;
+ dbg("This Interface = %d", ifnum);
+
+ data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+@@ -116,27 +119,32 @@ static int qcprobe(struct usb_serial *se
+ switch (nintf) {
+ case 1:
+ /* QDL mode */
+- if (serial->interface->num_altsetting == 2) {
+- struct usb_host_interface *intf;
+-
++ /* Gobi 2000 has a single altsetting, older ones have two */
++ if (serial->interface->num_altsetting == 2)
+ intf = &serial->interface->altsetting[1];
+- if (intf->desc.bNumEndpoints == 2) {
+- if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
+- usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
+- dbg("QDL port found");
+- retval = usb_set_interface(serial->dev, ifnum, 1);
+- if (retval < 0) {
+- dev_err(&serial->dev->dev,
+- "Could not set interface, error %d\n",
+- retval);
+- retval = -ENODEV;
+- }
+- return retval;
+- }
++ else if (serial->interface->num_altsetting > 2)
++ break;
++
++ if (intf->desc.bNumEndpoints == 2 &&
++ usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
++ usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
++ dbg("QDL port found");
++
++ if (serial->interface->num_altsetting == 1)
++ return 0;
++
++ retval = usb_set_interface(serial->dev, ifnum, 1);
++ if (retval < 0) {
++ dev_err(&serial->dev->dev,
++ "Could not set interface, error %d\n",
++ retval);
++ retval = -ENODEV;
+ }
++ return retval;
+ }
+ break;
+
++ case 3:
+ case 4:
+ /* Composite mode */
+ if (ifnum == 2) {
diff --git a/usb/usb-qcserial-use-generic-usb-wwan-code.patch b/usb/usb-qcserial-use-generic-usb-wwan-code.patch
new file mode 100644
index 00000000000000..084ce302b54e31
--- /dev/null
+++ b/usb/usb-qcserial-use-generic-usb-wwan-code.patch
@@ -0,0 +1,82 @@
+From mjg@redhat.com Thu Apr 29 12:56:00 2010
+From: Matthew Garrett <mjg@redhat.com>
+Date: Thu, 1 Apr 2010 12:31:09 -0400
+Subject: USB: qcserial: Use generic USB wwan code
+To: linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Matthew Garrett <mjg@redhat.com>
+Message-ID: <1270139470-24360-3-git-send-email-mjg@redhat.com>
+
+
+Make qcserial use the generic USB wwan code. This should result in a
+performance improvement.
+
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/Kconfig | 1 +
+ drivers/usb/serial/qcserial.c | 22 ++++++++++++++++++++++
+ 2 files changed, 23 insertions(+)
+
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -485,6 +485,7 @@ config USB_SERIAL_QCAUX
+
+ config USB_SERIAL_QUALCOMM
+ tristate "USB Qualcomm Serial modem"
++ select USB_SERIAL_WWAN
+ help
+ Say Y here if you have a Qualcomm USB modem device. These are
+ usually wireless cellular modems.
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -15,6 +15,8 @@
+ #include <linux/tty_flip.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
++#include <linux/slab.h>
++#include "usb-wwan.h"
+
+ #define DRIVER_AUTHOR "Qualcomm Inc"
+ #define DRIVER_DESC "Qualcomm USB Serial driver"
+@@ -92,6 +94,7 @@ static struct usb_driver qcdriver = {
+
+ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+ {
++ struct usb_wwan_intf_private *data;
+ int retval = -ENODEV;
+ __u8 nintf;
+ __u8 ifnum;
+@@ -103,6 +106,13 @@ static int qcprobe(struct usb_serial *se
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ dbg("This Interface = %d", ifnum);
+
++ data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ spin_lock_init(&data->susp_lock);
++
+ switch (nintf) {
+ case 1:
+ /* QDL mode */
+@@ -161,6 +171,18 @@ static struct usb_serial_driver qcdevice
+ .usb_driver = &qcdriver,
+ .num_ports = 1,
+ .probe = qcprobe,
++ .open = usb_wwan_open,
++ .close = usb_wwan_close,
++ .write = usb_wwan_write,
++ .write_room = usb_wwan_write_room,
++ .chars_in_buffer = usb_wwan_chars_in_buffer,
++ .attach = usb_wwan_startup,
++ .disconnect = usb_wwan_disconnect,
++ .release = usb_wwan_release,
++#ifdef CONFIG_PM
++ .suspend = usb_wwan_suspend,
++ .resume = usb_wwan_resume,
++#endif
+ };
+
+ static int __init qcinit(void)
diff --git a/usb/usb-serial-add-generic-usb-wwan-support.patch b/usb/usb-serial-add-generic-usb-wwan-support.patch
new file mode 100644
index 00000000000000..5885cf1e03f3aa
--- /dev/null
+++ b/usb/usb-serial-add-generic-usb-wwan-support.patch
@@ -0,0 +1,784 @@
+From mjg@redhat.com Thu Apr 29 12:53:31 2010
+From: Matthew Garrett <mjg@redhat.com>
+Date: Thu, 1 Apr 2010 12:31:07 -0400
+Subject: usb serial: Add generic USB wwan support
+To: linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Matthew Garrett <mjg@redhat.com>
+Message-ID: <1270139470-24360-1-git-send-email-mjg@redhat.com>
+
+
+The generic USB serial code is ill-suited for high-speed USB wwan devices,
+resulting in the option driver. However, other non-option devices may also
+gain similar benefits from not using the generic code. Factorise out the
+non-option specific code from the option driver and make it available to
+other users.
+
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/Kconfig | 3
+ drivers/usb/serial/Makefile | 1
+ drivers/usb/serial/usb-wwan.h | 67 ++++
+ drivers/usb/serial/usb_wwan.c | 664 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 735 insertions(+)
+
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -576,6 +576,9 @@ config USB_SERIAL_XIRCOM
+ To compile this driver as a module, choose M here: the
+ module will be called keyspan_pda.
+
++config USB_SERIAL_WWAN
++ tristate
++
+ config USB_SERIAL_OPTION
+ tristate "USB driver for GSM and CDMA modems"
+ help
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -52,6 +52,7 @@ obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) +=
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
+ obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o
+ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o
++obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o
+ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
+ obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+ obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
+--- /dev/null
++++ b/drivers/usb/serial/usb-wwan.h
+@@ -0,0 +1,67 @@
++/*
++ * Definitions for USB serial mobile broadband cards
++ */
++
++#ifndef __LINUX_USB_USB_WWAN
++#define __LINUX_USB_USB_WWAN
++
++extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
++extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
++extern void usb_wwan_close(struct usb_serial_port *port);
++extern int usb_wwan_startup(struct usb_serial *serial);
++extern void usb_wwan_disconnect(struct usb_serial *serial);
++extern void usb_wwan_release(struct usb_serial *serial);
++extern int usb_wwan_write_room(struct tty_struct *tty);
++extern void usb_wwan_set_termios(struct tty_struct *tty,
++ struct usb_serial_port *port,
++ struct ktermios *old);
++extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
++extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
++ unsigned int set, unsigned int clear);
++extern int usb_wwan_send_setup(struct usb_serial_port *port);
++extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
++ const unsigned char *buf, int count);
++extern int usb_wwan_chars_in_buffer(struct tty_struct *tty);
++#ifdef CONFIG_PM
++extern int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message);
++extern int usb_wwan_resume(struct usb_serial *serial);
++#endif
++
++/* per port private data */
++
++#define N_IN_URB 4
++#define N_OUT_URB 4
++#define IN_BUFLEN 4096
++#define OUT_BUFLEN 4096
++
++struct usb_wwan_intf_private {
++ spinlock_t susp_lock;
++ unsigned int suspended:1;
++ int in_flight;
++ int (*send_setup) (struct usb_serial_port *port);
++ void *private;
++};
++
++struct usb_wwan_port_private {
++ /* Input endpoints and buffer for this port */
++ struct urb *in_urbs[N_IN_URB];
++ u8 *in_buffer[N_IN_URB];
++ /* Output endpoints and buffer for this port */
++ struct urb *out_urbs[N_OUT_URB];
++ u8 *out_buffer[N_OUT_URB];
++ unsigned long out_busy; /* Bit vector of URBs in use */
++ int opened;
++ struct usb_anchor delayed;
++
++ /* Settings for the port */
++ int rts_state; /* Handshaking pins (outputs) */
++ int dtr_state;
++ int cts_state; /* Handshaking pins (inputs) */
++ int dsr_state;
++ int dcd_state;
++ int ri_state;
++
++ unsigned long tx_start_time[N_OUT_URB];
++};
++
++#endif /* __LINUX_USB_USB_WWAN */
+--- /dev/null
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -0,0 +1,664 @@
++/*
++ USB Driver layer for GSM modems
++
++ Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de>
++
++ This driver is free software; you can redistribute it and/or modify
++ it under the terms of Version 2 of the GNU General Public License as
++ published by the Free Software Foundation.
++
++ Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
++
++ History: see the git log.
++
++ Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
++
++ This driver exists because the "normal" serial driver doesn't work too well
++ with GSM modems. Issues:
++ - data loss -- one single Receive URB is not nearly enough
++ - controlling the baud rate doesn't make sense
++*/
++
++#define DRIVER_VERSION "v0.7.2"
++#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
++#define DRIVER_DESC "USB Driver for GSM modems"
++
++#include <linux/kernel.h>
++#include <linux/jiffies.h>
++#include <linux/errno.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/module.h>
++#include <linux/bitops.h>
++#include <linux/usb.h>
++#include <linux/usb/serial.h>
++#include "usb-wwan.h"
++
++static int debug;
++
++void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
++{
++ struct usb_serial *serial = port->serial;
++ struct usb_wwan_port_private *portdata;
++
++ struct usb_wwan_intf_private *intfdata;
++
++ dbg("%s", __func__);
++
++ intfdata = port->serial->private;
++
++ if (!intfdata->send_setup)
++ return;
++
++ portdata = usb_get_serial_port_data(port);
++ mutex_lock(&serial->disc_mutex);
++ portdata->rts_state = on;
++ portdata->dtr_state = on;
++ if (serial->dev)
++ intfdata->send_setup(port);
++ mutex_unlock(&serial->disc_mutex);
++}
++EXPORT_SYMBOL(usb_wwan_dtr_rts);
++
++void usb_wwan_set_termios(struct tty_struct *tty,
++ struct usb_serial_port *port,
++ struct ktermios *old_termios)
++{
++ struct usb_wwan_intf_private *intfdata = port->serial->private;
++
++ dbg("%s", __func__);
++
++ /* Doesn't support option setting */
++ tty_termios_copy_hw(tty->termios, old_termios);
++
++ if (intfdata->send_setup)
++ intfdata->send_setup(port);
++}
++EXPORT_SYMBOL(usb_wwan_set_termios);
++
++int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file)
++{
++ struct usb_serial_port *port = tty->driver_data;
++ unsigned int value;
++ struct usb_wwan_port_private *portdata;
++
++ portdata = usb_get_serial_port_data(port);
++
++ value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
++ ((portdata->dtr_state) ? TIOCM_DTR : 0) |
++ ((portdata->cts_state) ? TIOCM_CTS : 0) |
++ ((portdata->dsr_state) ? TIOCM_DSR : 0) |
++ ((portdata->dcd_state) ? TIOCM_CAR : 0) |
++ ((portdata->ri_state) ? TIOCM_RNG : 0);
++
++ return value;
++}
++EXPORT_SYMBOL(usb_wwan_tiocmget);
++
++int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
++ unsigned int set, unsigned int clear)
++{
++ struct usb_serial_port *port = tty->driver_data;
++ struct usb_wwan_port_private *portdata;
++ struct usb_wwan_intf_private *intfdata;
++
++ portdata = usb_get_serial_port_data(port);
++ intfdata = port->serial->private;
++
++ if (!intfdata->send_setup)
++ return -EINVAL;
++
++ /* FIXME: what locks portdata fields ? */
++ if (set & TIOCM_RTS)
++ portdata->rts_state = 1;
++ if (set & TIOCM_DTR)
++ portdata->dtr_state = 1;
++
++ if (clear & TIOCM_RTS)
++ portdata->rts_state = 0;
++ if (clear & TIOCM_DTR)
++ portdata->dtr_state = 0;
++ return intfdata->send_setup(port);
++}
++EXPORT_SYMBOL(usb_wwan_tiocmset);
++
++/* Write */
++int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
++ const unsigned char *buf, int count)
++{
++ struct usb_wwan_port_private *portdata;
++ struct usb_wwan_intf_private *intfdata;
++ int i;
++ int left, todo;
++ struct urb *this_urb = NULL; /* spurious */
++ int err;
++ unsigned long flags;
++
++ portdata = usb_get_serial_port_data(port);
++ intfdata = port->serial->private;
++
++ dbg("%s: write (%d chars)", __func__, count);
++
++ i = 0;
++ left = count;
++ for (i = 0; left > 0 && i < N_OUT_URB; i++) {
++ todo = left;
++ if (todo > OUT_BUFLEN)
++ todo = OUT_BUFLEN;
++
++ this_urb = portdata->out_urbs[i];
++ if (test_and_set_bit(i, &portdata->out_busy)) {
++ if (time_before(jiffies,
++ portdata->tx_start_time[i] + 10 * HZ))
++ continue;
++ usb_unlink_urb(this_urb);
++ continue;
++ }
++ dbg("%s: endpoint %d buf %d", __func__,
++ usb_pipeendpoint(this_urb->pipe), i);
++
++ err = usb_autopm_get_interface_async(port->serial->interface);
++ if (err < 0)
++ break;
++
++ /* send the data */
++ memcpy(this_urb->transfer_buffer, buf, todo);
++ this_urb->transfer_buffer_length = todo;
++
++ spin_lock_irqsave(&intfdata->susp_lock, flags);
++ if (intfdata->suspended) {
++ usb_anchor_urb(this_urb, &portdata->delayed);
++ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
++ } else {
++ intfdata->in_flight++;
++ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
++ err = usb_submit_urb(this_urb, GFP_ATOMIC);
++ if (err) {
++ dbg("usb_submit_urb %p (write bulk) failed "
++ "(%d)", this_urb, err);
++ clear_bit(i, &portdata->out_busy);
++ spin_lock_irqsave(&intfdata->susp_lock, flags);
++ intfdata->in_flight--;
++ spin_unlock_irqrestore(&intfdata->susp_lock,
++ flags);
++ continue;
++ }
++ }
++
++ portdata->tx_start_time[i] = jiffies;
++ buf += todo;
++ left -= todo;
++ }
++
++ count -= left;
++ dbg("%s: wrote (did %d)", __func__, count);
++ return count;
++}
++EXPORT_SYMBOL(usb_wwan_write);
++
++static void usb_wwan_indat_callback(struct urb *urb)
++{
++ int err;
++ int endpoint;
++ struct usb_serial_port *port;
++ struct tty_struct *tty;
++ unsigned char *data = urb->transfer_buffer;
++ int status = urb->status;
++
++ dbg("%s: %p", __func__, urb);
++
++ endpoint = usb_pipeendpoint(urb->pipe);
++ port = urb->context;
++
++ if (status) {
++ dbg("%s: nonzero status: %d on endpoint %02x.",
++ __func__, status, endpoint);
++ } else {
++ tty = tty_port_tty_get(&port->port);
++ if (urb->actual_length) {
++ tty_insert_flip_string(tty, data, urb->actual_length);
++ tty_flip_buffer_push(tty);
++ } else
++ dbg("%s: empty read urb received", __func__);
++ tty_kref_put(tty);
++
++ /* Resubmit urb so we continue receiving */
++ if (status != -ESHUTDOWN) {
++ err = usb_submit_urb(urb, GFP_ATOMIC);
++ if (err && err != -EPERM)
++ printk(KERN_ERR "%s: resubmit read urb failed. "
++ "(%d)", __func__, err);
++ else
++ usb_mark_last_busy(port->serial->dev);
++ }
++
++ }
++ return;
++}
++
++static void usb_wwan_outdat_callback(struct urb *urb)
++{
++ struct usb_serial_port *port;
++ struct usb_wwan_port_private *portdata;
++ struct usb_wwan_intf_private *intfdata;
++ int i;
++
++ dbg("%s", __func__);
++
++ port = urb->context;
++ intfdata = port->serial->private;
++
++ usb_serial_port_softint(port);
++ usb_autopm_put_interface_async(port->serial->interface);
++ portdata = usb_get_serial_port_data(port);
++ spin_lock(&intfdata->susp_lock);
++ intfdata->in_flight--;
++ spin_unlock(&intfdata->susp_lock);
++
++ for (i = 0; i < N_OUT_URB; ++i) {
++ if (portdata->out_urbs[i] == urb) {
++ smp_mb__before_clear_bit();
++ clear_bit(i, &portdata->out_busy);
++ break;
++ }
++ }
++}
++
++int usb_wwan_write_room(struct tty_struct *tty)
++{
++ struct usb_serial_port *port = tty->driver_data;
++ struct usb_wwan_port_private *portdata;
++ int i;
++ int data_len = 0;
++ struct urb *this_urb;
++
++ portdata = usb_get_serial_port_data(port);
++
++ for (i = 0; i < N_OUT_URB; i++) {
++ this_urb = portdata->out_urbs[i];
++ if (this_urb && !test_bit(i, &portdata->out_busy))
++ data_len += OUT_BUFLEN;
++ }
++
++ dbg("%s: %d", __func__, data_len);
++ return data_len;
++}
++EXPORT_SYMBOL(usb_wwan_write_room);
++
++int usb_wwan_chars_in_buffer(struct tty_struct *tty)
++{
++ struct usb_serial_port *port = tty->driver_data;
++ struct usb_wwan_port_private *portdata;
++ int i;
++ int data_len = 0;
++ struct urb *this_urb;
++
++ portdata = usb_get_serial_port_data(port);
++
++ for (i = 0; i < N_OUT_URB; i++) {
++ this_urb = portdata->out_urbs[i];
++ /* FIXME: This locking is insufficient as this_urb may
++ go unused during the test */
++ if (this_urb && test_bit(i, &portdata->out_busy))
++ data_len += this_urb->transfer_buffer_length;
++ }
++ dbg("%s: %d", __func__, data_len);
++ return data_len;
++}
++EXPORT_SYMBOL(usb_wwan_chars_in_buffer);
++
++int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
++{
++ struct usb_wwan_port_private *portdata;
++ struct usb_wwan_intf_private *intfdata;
++ struct usb_serial *serial = port->serial;
++ int i, err;
++ struct urb *urb;
++
++ portdata = usb_get_serial_port_data(port);
++ intfdata = serial->private;
++
++ dbg("%s", __func__);
++
++ /* Start reading from the IN endpoint */
++ for (i = 0; i < N_IN_URB; i++) {
++ urb = portdata->in_urbs[i];
++ if (!urb)
++ continue;
++ err = usb_submit_urb(urb, GFP_KERNEL);
++ if (err) {
++ dbg("%s: submit urb %d failed (%d) %d",
++ __func__, i, err, urb->transfer_buffer_length);
++ }
++ }
++
++ if (intfdata->send_setup)
++ intfdata->send_setup(port);
++
++ serial->interface->needs_remote_wakeup = 1;
++ spin_lock_irq(&intfdata->susp_lock);
++ portdata->opened = 1;
++ spin_unlock_irq(&intfdata->susp_lock);
++ usb_autopm_put_interface(serial->interface);
++
++ return 0;
++}
++EXPORT_SYMBOL(usb_wwan_open);
++
++void usb_wwan_close(struct usb_serial_port *port)
++{
++ int i;
++ struct usb_serial *serial = port->serial;
++ struct usb_wwan_port_private *portdata;
++ struct usb_wwan_intf_private *intfdata = port->serial->private;
++
++ dbg("%s", __func__);
++ portdata = usb_get_serial_port_data(port);
++
++ if (serial->dev) {
++ /* Stop reading/writing urbs */
++ spin_lock_irq(&intfdata->susp_lock);
++ portdata->opened = 0;
++ spin_unlock_irq(&intfdata->susp_lock);
++
++ for (i = 0; i < N_IN_URB; i++)
++ usb_kill_urb(portdata->in_urbs[i]);
++ for (i = 0; i < N_OUT_URB; i++)
++ usb_kill_urb(portdata->out_urbs[i]);
++ usb_autopm_get_interface(serial->interface);
++ serial->interface->needs_remote_wakeup = 0;
++ }
++}
++EXPORT_SYMBOL(usb_wwan_close);
++
++/* Helper functions used by usb_wwan_setup_urbs */
++static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
++ int dir, void *ctx, char *buf, int len,
++ void (*callback) (struct urb *))
++{
++ struct urb *urb;
++
++ if (endpoint == -1)
++ return NULL; /* endpoint not needed */
++
++ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
++ if (urb == NULL) {
++ dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
++ return NULL;
++ }
++
++ /* Fill URB using supplied data. */
++ usb_fill_bulk_urb(urb, serial->dev,
++ usb_sndbulkpipe(serial->dev, endpoint) | dir,
++ buf, len, callback, ctx);
++
++ return urb;
++}
++
++/* Setup urbs */
++static void usb_wwan_setup_urbs(struct usb_serial *serial)
++{
++ int i, j;
++ struct usb_serial_port *port;
++ struct usb_wwan_port_private *portdata;
++
++ dbg("%s", __func__);
++
++ for (i = 0; i < serial->num_ports; i++) {
++ port = serial->port[i];
++ portdata = usb_get_serial_port_data(port);
++
++ /* Do indat endpoints first */
++ for (j = 0; j < N_IN_URB; ++j) {
++ portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
++ port->
++ bulk_in_endpointAddress,
++ USB_DIR_IN,
++ port,
++ portdata->
++ in_buffer[j],
++ IN_BUFLEN,
++ usb_wwan_indat_callback);
++ }
++
++ /* outdat endpoints */
++ for (j = 0; j < N_OUT_URB; ++j) {
++ portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
++ port->
++ bulk_out_endpointAddress,
++ USB_DIR_OUT,
++ port,
++ portdata->
++ out_buffer
++ [j],
++ OUT_BUFLEN,
++ usb_wwan_outdat_callback);
++ }
++ }
++}
++
++int usb_wwan_startup(struct usb_serial *serial)
++{
++ int i, j, err;
++ struct usb_serial_port *port;
++ struct usb_wwan_port_private *portdata;
++ u8 *buffer;
++
++ dbg("%s", __func__);
++
++ /* Now setup per port private data */
++ for (i = 0; i < serial->num_ports; i++) {
++ port = serial->port[i];
++ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
++ if (!portdata) {
++ dbg("%s: kmalloc for usb_wwan_port_private (%d) failed!.",
++ __func__, i);
++ return 1;
++ }
++ init_usb_anchor(&portdata->delayed);
++
++ for (j = 0; j < N_IN_URB; j++) {
++ buffer = (u8 *) __get_free_page(GFP_KERNEL);
++ if (!buffer)
++ goto bail_out_error;
++ portdata->in_buffer[j] = buffer;
++ }
++
++ for (j = 0; j < N_OUT_URB; j++) {
++ buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
++ if (!buffer)
++ goto bail_out_error2;
++ portdata->out_buffer[j] = buffer;
++ }
++
++ usb_set_serial_port_data(port, portdata);
++
++ if (!port->interrupt_in_urb)
++ continue;
++ err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
++ if (err)
++ dbg("%s: submit irq_in urb failed %d", __func__, err);
++ }
++ usb_wwan_setup_urbs(serial);
++ return 0;
++
++bail_out_error2:
++ for (j = 0; j < N_OUT_URB; j++)
++ kfree(portdata->out_buffer[j]);
++bail_out_error:
++ for (j = 0; j < N_IN_URB; j++)
++ if (portdata->in_buffer[j])
++ free_page((unsigned long)portdata->in_buffer[j]);
++ kfree(portdata);
++ return 1;
++}
++EXPORT_SYMBOL(usb_wwan_startup);
++
++static void stop_read_write_urbs(struct usb_serial *serial)
++{
++ int i, j;
++ struct usb_serial_port *port;
++ struct usb_wwan_port_private *portdata;
++
++ /* Stop reading/writing urbs */
++ for (i = 0; i < serial->num_ports; ++i) {
++ port = serial->port[i];
++ portdata = usb_get_serial_port_data(port);
++ for (j = 0; j < N_IN_URB; j++)
++ usb_kill_urb(portdata->in_urbs[j]);
++ for (j = 0; j < N_OUT_URB; j++)
++ usb_kill_urb(portdata->out_urbs[j]);
++ }
++}
++
++void usb_wwan_disconnect(struct usb_serial *serial)
++{
++ dbg("%s", __func__);
++
++ stop_read_write_urbs(serial);
++}
++EXPORT_SYMBOL(usb_wwan_disconnect);
++
++void usb_wwan_release(struct usb_serial *serial)
++{
++ int i, j;
++ struct usb_serial_port *port;
++ struct usb_wwan_port_private *portdata;
++
++ dbg("%s", __func__);
++
++ /* Now free them */
++ for (i = 0; i < serial->num_ports; ++i) {
++ port = serial->port[i];
++ portdata = usb_get_serial_port_data(port);
++
++ for (j = 0; j < N_IN_URB; j++) {
++ usb_free_urb(portdata->in_urbs[j]);
++ free_page((unsigned long)
++ portdata->in_buffer[j]);
++ portdata->in_urbs[j] = NULL;
++ }
++ for (j = 0; j < N_OUT_URB; j++) {
++ usb_free_urb(portdata->out_urbs[j]);
++ kfree(portdata->out_buffer[j]);
++ portdata->out_urbs[j] = NULL;
++ }
++ }
++
++ /* Now free per port private data */
++ for (i = 0; i < serial->num_ports; i++) {
++ port = serial->port[i];
++ kfree(usb_get_serial_port_data(port));
++ }
++}
++EXPORT_SYMBOL(usb_wwan_release);
++
++#ifdef CONFIG_PM
++int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
++{
++ struct usb_wwan_intf_private *intfdata = serial->private;
++ int b;
++
++ dbg("%s entered", __func__);
++
++ if (message.event & PM_EVENT_AUTO) {
++ spin_lock_irq(&intfdata->susp_lock);
++ b = intfdata->in_flight;
++ spin_unlock_irq(&intfdata->susp_lock);
++
++ if (b)
++ return -EBUSY;
++ }
++
++ spin_lock_irq(&intfdata->susp_lock);
++ intfdata->suspended = 1;
++ spin_unlock_irq(&intfdata->susp_lock);
++ stop_read_write_urbs(serial);
++
++ return 0;
++}
++EXPORT_SYMBOL(usb_wwan_suspend);
++
++static void play_delayed(struct usb_serial_port *port)
++{
++ struct usb_wwan_intf_private *data;
++ struct usb_wwan_port_private *portdata;
++ struct urb *urb;
++ int err;
++
++ portdata = usb_get_serial_port_data(port);
++ data = port->serial->private;
++ while ((urb = usb_get_from_anchor(&portdata->delayed))) {
++ err = usb_submit_urb(urb, GFP_ATOMIC);
++ if (!err)
++ data->in_flight++;
++ }
++}
++
++int usb_wwan_resume(struct usb_serial *serial)
++{
++ int i, j;
++ struct usb_serial_port *port;
++ struct usb_wwan_intf_private *intfdata = serial->private;
++ struct usb_wwan_port_private *portdata;
++ struct urb *urb;
++ int err = 0;
++
++ dbg("%s entered", __func__);
++ /* get the interrupt URBs resubmitted unconditionally */
++ for (i = 0; i < serial->num_ports; i++) {
++ port = serial->port[i];
++ if (!port->interrupt_in_urb) {
++ dbg("%s: No interrupt URB for port %d", __func__, i);
++ continue;
++ }
++ err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
++ dbg("Submitted interrupt URB for port %d (result %d)", i, err);
++ if (err < 0) {
++ err("%s: Error %d for interrupt URB of port%d",
++ __func__, err, i);
++ goto err_out;
++ }
++ }
++
++ for (i = 0; i < serial->num_ports; i++) {
++ /* walk all ports */
++ port = serial->port[i];
++ portdata = usb_get_serial_port_data(port);
++
++ /* skip closed ports */
++ spin_lock_irq(&intfdata->susp_lock);
++ if (!portdata->opened) {
++ spin_unlock_irq(&intfdata->susp_lock);
++ continue;
++ }
++
++ for (j = 0; j < N_IN_URB; j++) {
++ urb = portdata->in_urbs[j];
++ err = usb_submit_urb(urb, GFP_ATOMIC);
++ if (err < 0) {
++ err("%s: Error %d for bulk URB %d",
++ __func__, err, i);
++ spin_unlock_irq(&intfdata->susp_lock);
++ goto err_out;
++ }
++ }
++ play_delayed(port);
++ spin_unlock_irq(&intfdata->susp_lock);
++ }
++ spin_lock_irq(&intfdata->susp_lock);
++ intfdata->suspended = 0;
++ spin_unlock_irq(&intfdata->susp_lock);
++err_out:
++ return err;
++}
++EXPORT_SYMBOL(usb_wwan_resume);
++#endif
++
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/usb/usb-storage-remove-unneeded-sl11r-unusual_devs-entry.patch b/usb/usb-storage-remove-unneeded-sl11r-unusual_devs-entry.patch
new file mode 100644
index 00000000000000..ccb4affd3e75b8
--- /dev/null
+++ b/usb/usb-storage-remove-unneeded-sl11r-unusual_devs-entry.patch
@@ -0,0 +1,42 @@
+From phil@ipom.com Thu Apr 29 13:00:25 2010
+From: Phil Dibowitz <phil@ipom.com>
+Date: Sun, 04 Apr 2010 14:21:01 +0200
+Subject: USB: storage: Remove unneeded SL11R unusual_devs entry
+To: Greg KH <greg@kroah.com>
+Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>, USB Dev <linux-usb@vger.kernel.org>, USB Storage list <usb-storage@lists.one-eyed-alien.net>
+Message-ID: <4BB8842D.5090304@ipom.com>
+
+
+It seems unlikely that this entry is needed anymore since the kernel
+has logic to handle devices that poorly respond to INQUIRY. Since we
+now have another entry with the same VID/PID but different flags, it's
+a good time to attempt to clean this up.
+
+The original submitter's email no longer works, so we'll keep an eye
+out for any regression reports.
+
+Signed-off-by: Phil Dibowitz <phil@ipom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/storage/unusual_devs.h | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -365,15 +365,6 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x
+ "FinePix 1400Zoom",
+ US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
+
+-/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
+- * The device needs the flags only.
+- */
+-UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
+- "ScanLogic",
+- "SL11R-IDE",
+- US_SC_DEVICE, US_PR_DEVICE, NULL,
+- US_FL_FIX_INQUIRY),
+-
+ /* Reported by Ondrej Zary <linux@rainbow-software.org>
+ * The device reports one sector more and breaks when that sector is accessed
+ */
diff --git a/usb/usb-support-for-allocating-usb-3.0-streams.patch b/usb/usb-support-for-allocating-usb-3.0-streams.patch
new file mode 100644
index 00000000000000..24ffbd0f1eb7f1
--- /dev/null
+++ b/usb/usb-support-for-allocating-usb-3.0-streams.patch
@@ -0,0 +1,248 @@
+From sarah.a.sharp@linux.intel.com Thu Apr 29 12:59:59 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 5 Apr 2010 10:55:58 -0700
+Subject: USB: Support for allocating USB 3.0 streams.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Alan Stern <stern@rowland.harvard.edu>, usb-storage@lists.one-eyed-alien.net, Hrant Dalalyan <Hrant.Dalalyan@synopsys.com>, Paul Zimmerman <Paul.Zimmerman@synopsys.com>, Ashot Madatyan <Ashot.Madatyan@synopsys.com>
+Message-ID: <20100405175558.GA11643@xanatos>
+Content-Disposition: inline
+
+
+Bulk endpoint streams were added in the USB 3.0 specification. Streams
+allow a device driver to overload a bulk endpoint so that multiple
+transfers can be queued at once.
+
+The device then decides which transfer it wants to work on first, and can
+queue part of a transfer before it switches to a new stream. All this
+switching is invisible to the device driver, which just gets a completion
+for the URB. Drivers that use streams must be able to handle URBs
+completing in a different order than they were submitted to the endpoint.
+
+This requires adding new API to set up xHCI data structures to support
+multiple queues ("stream rings") per endpoint. Drivers will allocate a
+number of stream IDs before enqueueing URBs to the bulk endpoints of the
+device, and free the stream IDs in their disconnect function. See
+Documentation/usb/bulk-streams.txt for details.
+
+The new mass storage device class, USB Attached SCSI Protocol (UASP), uses
+these streams API.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/bulk-streams.txt | 78 +++++++++++++++++++++++++++++++++++++
+ drivers/usb/core/hcd.c | 69 ++++++++++++++++++++++++++++++++
+ drivers/usb/core/hcd.h | 10 ++++
+ drivers/usb/host/xhci-pci.c | 2
+ include/linux/usb.h | 10 ++++
+ 5 files changed, 169 insertions(+)
+
+--- /dev/null
++++ b/Documentation/usb/bulk-streams.txt
+@@ -0,0 +1,78 @@
++Background
++==========
++
++Bulk endpoint streams were added in the USB 3.0 specification. Streams allow a
++device driver to overload a bulk endpoint so that multiple transfers can be
++queued at once.
++
++Streams are defined in sections 4.4.6.4 and 8.12.1.4 of the Universal Serial Bus
++3.0 specification at http://www.usb.org/developers/docs/ The USB Attached SCSI
++Protocol, which uses streams to queue multiple SCSI commands, can be found on
++the T10 website (http://t10.org/).
++
++
++Device-side implications
++========================
++
++Once a buffer has been queued to a stream ring, the device is notified (through
++an out-of-band mechanism on another endpoint) that data is ready for that stream
++ID. The device then tells the host which "stream" it wants to start. The host
++can also initiate a transfer on a stream without the device asking, but the
++device can refuse that transfer. Devices can switch between streams at any
++time.
++
++
++Driver implications
++===================
++
++int usb_alloc_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags);
++
++Device drivers will call this API to request that the host controller driver
++allocate memory so the driver can use up to num_streams stream IDs. They must
++pass an array of usb_host_endpoints that need to be setup with similar stream
++IDs. This is to ensure that a UASP driver will be able to use the same stream
++ID for the bulk IN and OUT endpoints used in a Bi-directional command sequence.
++
++The return value is an error condition (if one of the endpoints doesn't support
++streams, or the xHCI driver ran out of memory), or the number of streams the
++host controller allocated for this endpoint. The xHCI host controller hardware
++declares how many stream IDs it can support, and each bulk endpoint on a
++SuperSpeed device will say how many stream IDs it can handle. Therefore,
++drivers should be able to deal with being allocated less stream IDs than they
++requested.
++
++Do NOT call this function if you have URBs enqueued for any of the endpoints
++passed in as arguments. Do not call this function to request less than two
++streams.
++
++Drivers will only be allowed to call this API once for the same endpoint
++without calling usb_free_streams(). This is a simplification for the xHCI host
++controller driver, and may change in the future.
++
++
++Picking new Stream IDs to use
++============================
++
++Stream ID 0 is reserved, and should not be used to communicate with devices. If
++usb_alloc_streams() returns with a value of N, you may use streams 1 though N.
++To queue an URB for a specific stream, set the urb->stream_id value. If the
++endpoint does not support streams, an error will be returned.
++
++Note that new API to choose the next stream ID will have to be added if the xHCI
++driver supports secondary stream IDs.
++
++
++Clean up
++========
++
++If a driver wishes to stop using streams to communicate with the device, it
++should call
++
++void usb_free_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags);
++
++All stream IDs will be deallocated when the driver releases the interface, to
++ensure that drivers that don't support streams will be able to use the endpoint.
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1815,6 +1815,75 @@ void usb_hcd_reset_endpoint(struct usb_d
+ }
+ }
+
++/**
++ * usb_alloc_streams - allocate bulk endpoint stream IDs.
++ * @interface: alternate setting that includes all endpoints.
++ * @eps: array of endpoints that need streams.
++ * @num_eps: number of endpoints in the array.
++ * @num_streams: number of streams to allocate.
++ * @mem_flags: flags hcd should use to allocate memory.
++ *
++ * Sets up a group of bulk endpoints to have num_streams stream IDs available.
++ * Drivers may queue multiple transfers to different stream IDs, which may
++ * complete in a different order than they were queued.
++ */
++int usb_alloc_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags)
++{
++ struct usb_hcd *hcd;
++ struct usb_device *dev;
++ int i;
++
++ dev = interface_to_usbdev(interface);
++ hcd = bus_to_hcd(dev->bus);
++ if (!hcd->driver->alloc_streams || !hcd->driver->free_streams)
++ return -EINVAL;
++ if (dev->speed != USB_SPEED_SUPER)
++ return -EINVAL;
++
++ /* Streams only apply to bulk endpoints. */
++ for (i = 0; i < num_eps; i++)
++ if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
++ return -EINVAL;
++
++ return hcd->driver->alloc_streams(hcd, dev, eps, num_eps,
++ num_streams, mem_flags);
++}
++EXPORT_SYMBOL_GPL(usb_alloc_streams);
++
++/**
++ * usb_free_streams - free bulk endpoint stream IDs.
++ * @interface: alternate setting that includes all endpoints.
++ * @eps: array of endpoints to remove streams from.
++ * @num_eps: number of endpoints in the array.
++ * @mem_flags: flags hcd should use to allocate memory.
++ *
++ * Reverts a group of bulk endpoints back to not using stream IDs.
++ * Can fail if we are given bad arguments, or HCD is broken.
++ */
++void usb_free_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags)
++{
++ struct usb_hcd *hcd;
++ struct usb_device *dev;
++ int i;
++
++ dev = interface_to_usbdev(interface);
++ hcd = bus_to_hcd(dev->bus);
++ if (dev->speed != USB_SPEED_SUPER)
++ return;
++
++ /* Streams only apply to bulk endpoints. */
++ for (i = 0; i < num_eps; i++)
++ if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
++ return;
++
++ hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
++}
++EXPORT_SYMBOL_GPL(usb_free_streams);
++
+ /* Protect against drivers that try to unlink URBs after the device
+ * is gone, by waiting until all unlinks for @udev are finished.
+ * Since we don't currently track URBs by device, simply wait until
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -250,6 +250,16 @@ struct hc_driver {
+ int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
+ /* Called by usb_disconnect to free HC device structures */
+ void (*free_dev)(struct usb_hcd *, struct usb_device *);
++ /* Change a group of bulk endpoints to support multiple stream IDs */
++ int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags);
++ /* Reverts a group of bulk endpoints back to not using stream IDs.
++ * Can fail if we run out of memory.
++ */
++ int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags);
+
+ /* Bandwidth computation functions */
+ /* Note that add_endpoint() can only be called once per endpoint before
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -132,6 +132,8 @@ static const struct hc_driver xhci_pci_h
+ .urb_dequeue = xhci_urb_dequeue,
+ .alloc_dev = xhci_alloc_dev,
+ .free_dev = xhci_free_dev,
++ .alloc_streams = xhci_alloc_streams,
++ .free_streams = xhci_free_streams,
+ .add_endpoint = xhci_add_endpoint,
+ .drop_endpoint = xhci_drop_endpoint,
+ .endpoint_reset = xhci_endpoint_reset,
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -570,6 +570,16 @@ static inline void usb_mark_last_busy(st
+ /* for drivers using iso endpoints */
+ extern int usb_get_current_frame_number(struct usb_device *usb_dev);
+
++/* Sets up a group of bulk endpoints to support multiple stream IDs. */
++extern int usb_alloc_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags);
++
++/* Reverts a group of bulk endpoints back to not using stream IDs. */
++extern void usb_free_streams(struct usb_interface *interface,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags);
++
+ /* used these for multi-interface device registration */
+ extern int usb_driver_claim_interface(struct usb_driver *driver,
+ struct usb_interface *iface, void *priv);
diff --git a/usb/usb-ueagle-fix-coding-styles.patch b/usb/usb-ueagle-fix-coding-styles.patch
new file mode 100644
index 00000000000000..a2cf57c1548093
--- /dev/null
+++ b/usb/usb-ueagle-fix-coding-styles.patch
@@ -0,0 +1,745 @@
+From jblanco@neurowork.net Thu Apr 29 13:08:59 2010
+From: "Javier Blanco de Torres (Neurowork)" <jblanco@neurowork.net>
+Date: Mon, 12 Apr 2010 09:21:13 +0200
+Subject: USB: ueagle: fix Coding Styles
+To: "Greg KH" <gregkh@suse.de>
+Message-ID: <92b3d0e7b27bfa13ae50672e2ea5473d.squirrel@neurowork.net>
+
+
+Fixed coding styles in the ueagle usb driver.
+
+Signed-off-by: Javier Blanco de Torres <jblanco@neurowork.net>
+Signed-off-by: Alejandro S�nchez Acosta <asanchez@neurowork.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/ueagle-atm.c | 347 +++++++++++++++++++++++++------------------
+ 1 file changed, 207 insertions(+), 140 deletions(-)
+
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -94,19 +94,19 @@
+ } while (0)
+
+ #define uea_enters(usb_dev) \
+- uea_vdbg(usb_dev, "entering %s\n", __func__)
++ uea_vdbg(usb_dev, "entering %s\n" , __func__)
+
+ #define uea_leaves(usb_dev) \
+- uea_vdbg(usb_dev, "leaving %s\n", __func__)
++ uea_vdbg(usb_dev, "leaving %s\n" , __func__)
+
+-#define uea_err(usb_dev, format,args...) \
+- dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
++#define uea_err(usb_dev, format, args...) \
++ dev_err(&(usb_dev)->dev , "[UEAGLE-ATM] " format , ##args)
+
+-#define uea_warn(usb_dev, format,args...) \
+- dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
++#define uea_warn(usb_dev, format, args...) \
++ dev_warn(&(usb_dev)->dev , "[Ueagle-atm] " format, ##args)
+
+-#define uea_info(usb_dev, format,args...) \
+- dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
++#define uea_info(usb_dev, format, args...) \
++ dev_info(&(usb_dev)->dev , "[ueagle-atm] " format, ##args)
+
+ struct intr_pkt;
+
+@@ -289,7 +289,7 @@ enum {
+ #define IS_ISDN(x) \
+ ((x)->annex & ANNEXB)
+
+-#define INS_TO_USBDEV(ins) ins->usb_dev
++#define INS_TO_USBDEV(ins) (ins->usb_dev)
+
+ #define GET_STATUS(data) \
+ ((data >> 8) & 0xf)
+@@ -304,7 +304,7 @@ enum {
+ * The FW_GET_BYTE() macro is provided only for consistency.
+ */
+
+-#define FW_GET_BYTE(p) *((__u8 *) (p))
++#define FW_GET_BYTE(p) (*((__u8 *) (p)))
+
+ #define FW_DIR "ueagle-atm/"
+ #define UEA_FW_NAME_MAX 30
+@@ -315,7 +315,7 @@ enum {
+
+ #define ACK_TIMEOUT msecs_to_jiffies(3000)
+
+-#define UEA_INTR_IFACE_NO 0
++#define UEA_INTR_IFACE_NO 0
+ #define UEA_US_IFACE_NO 1
+ #define UEA_DS_IFACE_NO 2
+
+@@ -326,9 +326,9 @@ enum {
+ #define UEA_INTR_PIPE 0x04
+ #define UEA_ISO_DATA_PIPE 0x08
+
+-#define UEA_E1_SET_BLOCK 0x0001
++#define UEA_E1_SET_BLOCK 0x0001
+ #define UEA_E4_SET_BLOCK 0x002c
+-#define UEA_SET_MODE 0x0003
++#define UEA_SET_MODE 0x0003
+ #define UEA_SET_2183_DATA 0x0004
+ #define UEA_SET_TIMEOUT 0x0011
+
+@@ -366,7 +366,7 @@ struct l1_code {
+ u8 string_header[E4_L1_STRING_HEADER];
+ u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
+ struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
+- u8 code [0];
++ u8 code[0];
+ } __attribute__ ((packed));
+
+ /* structures describing a block within a DSP page */
+@@ -428,7 +428,8 @@ struct block_info_e4 {
+ #define E4_MODEMREADY 0x1
+
+ #define E1_MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
+-#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | ((st) & 0xf) << 4 | ((s) & 0xf))
++#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | \
++ ((st) & 0xf) << 4 | ((s) & 0xf))
+
+ #define E1_MAKESA(a, b, c, d) \
+ (((c) & 0xff) << 24 | \
+@@ -473,7 +474,7 @@ struct cmv_e4 {
+ __be16 wFunction;
+ __be16 wOffset;
+ __be16 wAddress;
+- __be32 dwData [6];
++ __be32 dwData[6];
+ } __attribute__ ((packed));
+
+ /* structures representing swap information */
+@@ -534,11 +535,13 @@ struct intr_pkt {
+
+ static struct usb_driver uea_driver;
+ static DEFINE_MUTEX(uea_mutex);
+-static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
++static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
++ "Eagle IV"};
+
+ static int modem_index;
+ static unsigned int debug;
+-static unsigned int altsetting[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
++static unsigned int altsetting[NB_MODEM] = {
++ [0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
+ static int sync_wait[NB_MODEM];
+ static char *cmv_file[NB_MODEM];
+ static int annex[NB_MODEM];
+@@ -555,7 +558,7 @@ MODULE_PARM_DESC(cmv_file,
+ "file name with configuration and management variables");
+ module_param_array(annex, uint, NULL, 0644);
+ MODULE_PARM_DESC(annex,
+- "manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
++ "manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
+
+ #define uea_wait(sc, cond, timeo) \
+ ({ \
+@@ -602,7 +605,8 @@ static int uea_send_modem_cmd(struct usb
+ return (ret == size) ? 0 : -EIO;
+ }
+
+-static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
++static void uea_upload_pre_firmware(const struct firmware *fw_entry,
++ void *context)
+ {
+ struct usb_device *usb = context;
+ const u8 *pfw;
+@@ -707,7 +711,8 @@ static int uea_load_firmware(struct usb_
+ }
+
+ ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
+- GFP_KERNEL, usb, uea_upload_pre_firmware);
++ GFP_KERNEL, usb,
++ uea_upload_pre_firmware);
+ if (ret)
+ uea_err(usb, "firmware %s is not available\n", fw_name);
+ else
+@@ -876,7 +881,7 @@ static int request_dsp(struct uea_softc
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "requesting firmware %s failed with error %d\n",
+- dsp_name, ret);
++ dsp_name, ret);
+ return ret;
+ }
+
+@@ -994,14 +999,17 @@ static void __uea_load_page_e4(struct ue
+
+ blockidx = &p->page_header[blockno];
+ blocksize = E4_PAGE_BYTES(blockidx->PageSize);
+- blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset);
++ blockoffset = sc->dsp_firm->data + le32_to_cpu(
++ blockidx->PageOffset);
+
+ bi.dwSize = cpu_to_be32(blocksize);
+ bi.dwAddress = cpu_to_be32(le32_to_cpu(blockidx->PageAddress));
+
+ uea_dbg(INS_TO_USBDEV(sc),
+- "sending block %u for DSP page %u size %u address %x\n",
+- blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
++ "sending block %u for DSP page "
++ "%u size %u address %x\n",
++ blockno, pageno, blocksize,
++ le32_to_cpu(blockidx->PageAddress));
+
+ /* send block info through the IDMA pipe */
+ if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE))
+@@ -1042,7 +1050,8 @@ static void uea_load_page_e4(struct work
+
+ p = (struct l1_code *) sc->dsp_firm->data;
+ if (pageno >= le16_to_cpu(p->page_header[0].PageNumber)) {
+- uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
++ uea_err(INS_TO_USBDEV(sc), "invalid DSP "
++ "page %u requested\n", pageno);
+ return;
+ }
+
+@@ -1059,7 +1068,7 @@ static void uea_load_page_e4(struct work
+ __uea_load_page_e4(sc, i, 1);
+ }
+
+- uea_dbg(INS_TO_USBDEV(sc),"sending start bi\n");
++ uea_dbg(INS_TO_USBDEV(sc) , "sending start bi\n");
+
+ bi.wHdr = cpu_to_be16(UEA_BIHDR);
+ bi.bBootPage = 0;
+@@ -1139,8 +1148,10 @@ static int uea_cmv_e1(struct uea_softc *
+ uea_enters(INS_TO_USBDEV(sc));
+ uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+ "offset : 0x%04x, data : 0x%08x\n",
+- E1_FUNCTION_TYPE(function), E1_FUNCTION_SUBTYPE(function),
+- E1_GETSA1(address), E1_GETSA2(address), E1_GETSA3(address),
++ E1_FUNCTION_TYPE(function),
++ E1_FUNCTION_SUBTYPE(function),
++ E1_GETSA1(address), E1_GETSA2(address),
++ E1_GETSA3(address),
+ E1_GETSA4(address), offset, data);
+
+ /* we send a request, but we expect a reply */
+@@ -1157,7 +1168,8 @@ static int uea_cmv_e1(struct uea_softc *
+ cmv.wOffsetAddress = cpu_to_le16(offset);
+ put_unaligned_le32(data >> 16 | data << 16, &cmv.dwData);
+
+- ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
++ ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START,
++ sizeof(cmv), &cmv);
+ if (ret < 0)
+ return ret;
+ ret = wait_cmv_ack(sc);
+@@ -1191,7 +1203,8 @@ static int uea_cmv_e4(struct uea_softc *
+ cmv.wOffset = cpu_to_be16(offset);
+ cmv.dwData[0] = cpu_to_be32(data);
+
+- ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
++ ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START,
++ sizeof(cmv), &cmv);
+ if (ret < 0)
+ return ret;
+ ret = wait_cmv_ack(sc);
+@@ -1208,7 +1221,7 @@ static inline int uea_read_cmv_e1(struct
+ uea_err(INS_TO_USBDEV(sc),
+ "reading cmv failed with error %d\n", ret);
+ else
+- *data = sc->data;
++ *data = sc->data;
+
+ return ret;
+ }
+@@ -1216,13 +1229,14 @@ static inline int uea_read_cmv_e1(struct
+ static inline int uea_read_cmv_e4(struct uea_softc *sc,
+ u8 size, u16 group, u16 address, u16 offset, u32 *data)
+ {
+- int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTREAD, size),
++ int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
++ E4_REQUESTREAD, size),
+ group, address, offset, 0);
+ if (ret < 0)
+ uea_err(INS_TO_USBDEV(sc),
+ "reading cmv failed with error %d\n", ret);
+ else {
+- *data = sc->data;
++ *data = sc->data;
+ /* size is in 16-bit word quantities */
+ if (size > 2)
+ *(data + 1) = sc->data1;
+@@ -1245,7 +1259,8 @@ static inline int uea_write_cmv_e1(struc
+ static inline int uea_write_cmv_e4(struct uea_softc *sc,
+ u8 size, u16 group, u16 address, u16 offset, u32 data)
+ {
+- int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTWRITE, size),
++ int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
++ E4_REQUESTWRITE, size),
+ group, address, offset, data);
+ if (ret < 0)
+ uea_err(INS_TO_USBDEV(sc),
+@@ -1442,27 +1457,29 @@ static int uea_stat_e4(struct uea_softc
+ return ret;
+
+ switch (sc->stats.phy.state) {
+- case 0x0: /* not yet synchronized */
+- case 0x1:
+- case 0x3:
+- case 0x4:
+- uea_dbg(INS_TO_USBDEV(sc), "modem not yet synchronized\n");
+- return 0;
+- case 0x5: /* initialization */
+- case 0x6:
+- case 0x9:
+- case 0xa:
+- uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
+- return 0;
+- case 0x2: /* fail ... */
+- uea_info(INS_TO_USBDEV(sc), "modem synchronization failed"
+- " (may be try other cmv/dsp)\n");
+- return -EAGAIN;
+- case 0x7: /* operational */
+- break;
+- default:
+- uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n", sc->stats.phy.state);
+- return 0;
++ case 0x0: /* not yet synchronized */
++ case 0x1:
++ case 0x3:
++ case 0x4:
++ uea_dbg(INS_TO_USBDEV(sc), "modem not yet "
++ "synchronized\n");
++ return 0;
++ case 0x5: /* initialization */
++ case 0x6:
++ case 0x9:
++ case 0xa:
++ uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
++ return 0;
++ case 0x2: /* fail ... */
++ uea_info(INS_TO_USBDEV(sc), "modem synchronization "
++ "failed (may be try other cmv/dsp)\n");
++ return -EAGAIN;
++ case 0x7: /* operational */
++ break;
++ default:
++ uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n",
++ sc->stats.phy.state);
++ return 0;
+ }
+
+ if (data != 7) {
+@@ -1502,9 +1519,9 @@ static int uea_stat_e4(struct uea_softc
+ if (sc->stats.phy.flags) {
+ uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
+ sc->stats.phy.flags);
+- if (sc->stats.phy.flags & 1) //delineation LOSS
++ if (sc->stats.phy.flags & 1) /* delineation LOSS */
+ return -EAGAIN;
+- if (sc->stats.phy.flags & 0x4000) //Reset Flag
++ if (sc->stats.phy.flags & 0x4000) /* Reset Flag */
+ return -EAGAIN;
+ return 0;
+ }
+@@ -1618,7 +1635,8 @@ static int request_cmvs(struct uea_softc
+ if (ret < 0) {
+ /* if caller can handle old version, try to provide it */
+ if (*ver == 1) {
+- uea_warn(INS_TO_USBDEV(sc), "requesting firmware %s failed, "
++ uea_warn(INS_TO_USBDEV(sc), "requesting "
++ "firmware %s failed, "
+ "try to get older cmvs\n", cmv_name);
+ return request_cmvs_old(sc, cmvs, fw);
+ }
+@@ -1632,8 +1650,8 @@ static int request_cmvs(struct uea_softc
+ data = (u8 *) (*fw)->data;
+ if (size < 4 || strncmp(data, "cmv2", 4) != 0) {
+ if (*ver == 1) {
+- uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted, "
+- "try to get older cmvs\n", cmv_name);
++ uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted,"
++ " try to get older cmvs\n", cmv_name);
+ release_firmware(*fw);
+ return request_cmvs_old(sc, cmvs, fw);
+ }
+@@ -1670,7 +1688,7 @@ static int uea_send_cmvs_e1(struct uea_s
+ int i, ret, len;
+ void *cmvs_ptr;
+ const struct firmware *cmvs_fw;
+- int ver = 1; // we can handle v1 cmv firmware version;
++ int ver = 1; /* we can handle v1 cmv firmware version; */
+
+ /* Enter in R-IDLE (cmv) until instructed otherwise */
+ ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 1);
+@@ -1685,7 +1703,7 @@ static int uea_send_cmvs_e1(struct uea_s
+ sc->stats.phy.firmid);
+
+ /* get options */
+- ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
++ ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
+ if (ret < 0)
+ return ret;
+
+@@ -1697,9 +1715,10 @@ static int uea_send_cmvs_e1(struct uea_s
+ "please update your firmware\n");
+
+ for (i = 0; i < len; i++) {
+- ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v1[i].address),
+- get_unaligned_le16(&cmvs_v1[i].offset),
+- get_unaligned_le32(&cmvs_v1[i].data));
++ ret = uea_write_cmv_e1(sc,
++ get_unaligned_le32(&cmvs_v1[i].address),
++ get_unaligned_le16(&cmvs_v1[i].offset),
++ get_unaligned_le32(&cmvs_v1[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1707,9 +1726,10 @@ static int uea_send_cmvs_e1(struct uea_s
+ struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr;
+
+ for (i = 0; i < len; i++) {
+- ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v2[i].address),
+- (u16) get_unaligned_le32(&cmvs_v2[i].offset),
+- get_unaligned_le32(&cmvs_v2[i].data));
++ ret = uea_write_cmv_e1(sc,
++ get_unaligned_le32(&cmvs_v2[i].address),
++ (u16) get_unaligned_le32(&cmvs_v2[i].offset),
++ get_unaligned_le32(&cmvs_v2[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1722,7 +1742,8 @@ static int uea_send_cmvs_e1(struct uea_s
+ /* Enter in R-ACT-REQ */
+ ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 2);
+ uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
+- uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
++ uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
++ "synchronization...\n");
+ out:
+ release_firmware(cmvs_fw);
+ return ret;
+@@ -1733,7 +1754,7 @@ static int uea_send_cmvs_e4(struct uea_s
+ int i, ret, len;
+ void *cmvs_ptr;
+ const struct firmware *cmvs_fw;
+- int ver = 2; // we can only handle v2 cmv firmware version;
++ int ver = 2; /* we can only handle v2 cmv firmware version; */
+
+ /* Enter in R-IDLE (cmv) until instructed otherwise */
+ ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 1);
+@@ -1750,7 +1771,7 @@ static int uea_send_cmvs_e4(struct uea_s
+
+
+ /* get options */
+- ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
++ ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
+ if (ret < 0)
+ return ret;
+
+@@ -1760,10 +1781,10 @@ static int uea_send_cmvs_e4(struct uea_s
+
+ for (i = 0; i < len; i++) {
+ ret = uea_write_cmv_e4(sc, 1,
+- get_unaligned_le32(&cmvs_v2[i].group),
+- get_unaligned_le32(&cmvs_v2[i].address),
+- get_unaligned_le32(&cmvs_v2[i].offset),
+- get_unaligned_le32(&cmvs_v2[i].data));
++ get_unaligned_le32(&cmvs_v2[i].group),
++ get_unaligned_le32(&cmvs_v2[i].address),
++ get_unaligned_le32(&cmvs_v2[i].offset),
++ get_unaligned_le32(&cmvs_v2[i].data));
+ if (ret < 0)
+ goto out;
+ }
+@@ -1776,7 +1797,8 @@ static int uea_send_cmvs_e4(struct uea_s
+ /* Enter in R-ACT-REQ */
+ ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 2);
+ uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
+- uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
++ uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
++ "synchronization...\n");
+ out:
+ release_firmware(cmvs_fw);
+ return ret;
+@@ -1812,7 +1834,7 @@ static int uea_start_reset(struct uea_so
+ uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+ uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
+
+- /* enter reset mode */
++ /* enter reset mode */
+ uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
+
+ /* original driver use 200ms, but windows driver use 100ms */
+@@ -1824,7 +1846,7 @@ static int uea_start_reset(struct uea_so
+ uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
+
+ if (UEA_CHIP_VERSION(sc) != EAGLE_IV) {
+- /* clear tx and rx mailboxes */
++ /* clear tx and rx mailboxes */
+ uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
+ uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
+ uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
+@@ -1835,9 +1857,11 @@ static int uea_start_reset(struct uea_so
+ return ret;
+
+ if (UEA_CHIP_VERSION(sc) == EAGLE_IV)
+- sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1);
++ sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
++ E4_MODEMREADY, 1);
+ else
+- sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY);
++ sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
++ E1_MODEMREADY);
+
+ /* demask interrupt */
+ sc->booting = 0;
+@@ -1937,7 +1961,8 @@ static int load_XILINX_firmware(struct u
+ value = 0;
+ ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
+ if (ret < 0)
+- uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
++ uea_err(sc->usb_dev, "elsa de-assert failed with error"
++ " %d\n", ret);
+
+ err1:
+ release_firmware(fw_entry);
+@@ -1966,13 +1991,15 @@ static void uea_dispatch_cmv_e1(struct u
+ if (UEA_CHIP_VERSION(sc) == ADI930
+ && cmv->bFunction == E1_MAKEFUNCTION(2, 2)) {
+ cmv->wIndex = cpu_to_le16(dsc->idx);
+- put_unaligned_le32(dsc->address, &cmv->dwSymbolicAddress);
++ put_unaligned_le32(dsc->address,
++ &cmv->dwSymbolicAddress);
+ cmv->wOffsetAddress = cpu_to_le16(dsc->offset);
+ } else
+ goto bad2;
+ }
+
+- if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY)) {
++ if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
++ E1_MODEMREADY)) {
+ wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
+ return;
+@@ -2021,7 +2048,8 @@ static void uea_dispatch_cmv_e4(struct u
+ if (be16_to_cpu(cmv->wFunction) != dsc->function)
+ goto bad2;
+
+- if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1)) {
++ if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
++ E4_MODEMREADY, 1)) {
+ wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
+ return;
+@@ -2048,14 +2076,16 @@ bad2:
+ return;
+ }
+
+-static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *intr)
++static void uea_schedule_load_page_e1(struct uea_softc *sc,
++ struct intr_pkt *intr)
+ {
+ sc->pageno = intr->e1_bSwapPageNo;
+ sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4;
+ queue_work(sc->work_q, &sc->task);
+ }
+
+-static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr)
++static void uea_schedule_load_page_e4(struct uea_softc *sc,
++ struct intr_pkt *intr)
+ {
+ sc->pageno = intr->e4_bSwapPageNo;
+ queue_work(sc->work_q, &sc->task);
+@@ -2263,8 +2293,8 @@ out:
+
+ static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+
+-static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
+- char *buf)
++static ssize_t read_human_status(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ int ret = -ENODEV;
+ int modem_state;
+@@ -2289,7 +2319,7 @@ static ssize_t read_human_status(struct
+ case 0xa:
+ modem_state = 1;
+ break;
+- case 0x7: /* operational */
++ case 0x7: /* operational */
+ modem_state = 2;
+ break;
+ case 0x2: /* fail ... */
+@@ -2324,7 +2354,8 @@ out:
+ return ret;
+ }
+
+-static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
++static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO,
++ read_human_status, NULL);
+
+ static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
+ char *buf)
+@@ -2358,25 +2389,25 @@ out:
+
+ static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+
+-#define UEA_ATTR(name, reset) \
++#define UEA_ATTR(name, reset) \
+ \
+-static ssize_t read_##name(struct device *dev, \
++static ssize_t read_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+-{ \
+- int ret = -ENODEV; \
+- struct uea_softc *sc; \
+- \
+- mutex_lock(&uea_mutex); \
++{ \
++ int ret = -ENODEV; \
++ struct uea_softc *sc; \
++ \
++ mutex_lock(&uea_mutex); \
+ sc = dev_to_uea(dev); \
+- if (!sc) \
+- goto out; \
++ if (!sc) \
++ goto out; \
+ ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name); \
+ if (reset) \
+ sc->stats.phy.name = 0; \
+-out: \
+- mutex_unlock(&uea_mutex); \
+- return ret; \
+-} \
++out: \
++ mutex_unlock(&uea_mutex); \
++ return ret; \
++} \
+ \
+ static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
+
+@@ -2527,12 +2558,14 @@ static int uea_bind(struct usbatm_data *
+ else if (sc->driver_info & AUTO_ANNEX_B)
+ sc->annex = ANNEXB;
+ else
+- sc->annex = (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)?ANNEXB:ANNEXA;
++ sc->annex = (le16_to_cpu
++ (sc->usb_dev->descriptor.bcdDevice) & 0x80) ? ANNEXB : ANNEXA;
+
+ alt = altsetting[sc->modem_index];
+ /* ADI930 don't support iso */
+ if (UEA_CHIP_VERSION(id) != ADI930 && alt > 0) {
+- if (alt <= 8 && usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
++ if (alt <= 8 &&
++ usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
+ uea_dbg(usb, "set alternate %u for 2 interface\n", alt);
+ uea_info(usb, "using iso mode\n");
+ usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
+@@ -2621,40 +2654,74 @@ static void uea_disconnect(struct usb_in
+ * List of supported VID/PID
+ */
+ static const struct usb_device_id uea_ids[] = {
+- {USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM), .driver_info = EAGLE_IV | PREFIRM},
+- {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM), .driver_info = EAGLE_IV | PSTFIRM},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+- {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM), .driver_info = ADI930 | PREFIRM},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM), .driver_info = ADI930 | PREFIRM},
+- {USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
+- {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
+- {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
+- {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
+- {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+- {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
++ {USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM),
++ .driver_info = ADI930 | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM),
++ .driver_info = ADI930 | PSTFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM),
++ .driver_info = EAGLE_II | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM),
++ .driver_info = EAGLE_II | PSTFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM),
++ .driver_info = EAGLE_II | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM),
++ .driver_info = EAGLE_II | PSTFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM),
++ .driver_info = EAGLE_III | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM),
++ .driver_info = EAGLE_III | PSTFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM),
++ .driver_info = EAGLE_IV | PREFIRM},
++ {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM),
++ .driver_info = EAGLE_IV | PSTFIRM},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM),
++ .driver_info = EAGLE_II | PREFIRM},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM),
++ .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM),
++ .driver_info = EAGLE_II | PREFIRM},
++ {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM),
++ .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM),
++ .driver_info = ADI930 | PREFIRM},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM),
++ .driver_info = ADI930 | PSTFIRM},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM),
++ .driver_info = ADI930 | PREFIRM},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM),
++ .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM),
++ .driver_info = ADI930 | PREFIRM},
++ {USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM),
++ .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
++ {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
++ {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
++ {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
++ {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),
++ .driver_info = EAGLE_I | PREFIRM},
++ {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),
++ .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
+ {}
+ };
+
diff --git a/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch b/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch
new file mode 100644
index 00000000000000..13593136a77ce6
--- /dev/null
+++ b/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch
@@ -0,0 +1,138 @@
+From stern@rowland.harvard.edu Thu Apr 29 12:51:52 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 2 Apr 2010 13:22:09 -0400 (EDT)
+Subject: USB: use PM core routines to enable/disable autosuspend
+To: Greg KH <greg@kroah.com>
+Message-ID: <Pine.LNX.4.44L0.1004021312150.1324-100000@iolanthe.rowland.org>
+
+
+This patch (as1366) replaces the private routines
+usb_enable_autosuspend() and usb_disable_autosuspend() with calls to
+the standard pm_runtime_allow() and pm_runtime_forbid() functions in
+the runtime PM framework. They do the same thing.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/driver.c | 21 +++++----------------
+ drivers/usb/core/sysfs.c | 10 +++++-----
+ include/linux/usb.h | 6 ++----
+ 3 files changed, 12 insertions(+), 25 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1355,13 +1355,9 @@ int usb_resume(struct device *dev, pm_me
+ *
+ * The caller must hold @udev's device lock.
+ */
+-int usb_enable_autosuspend(struct usb_device *udev)
++void usb_enable_autosuspend(struct usb_device *udev)
+ {
+- if (udev->autosuspend_disabled) {
+- udev->autosuspend_disabled = 0;
+- usb_autosuspend_device(udev);
+- }
+- return 0;
++ pm_runtime_allow(&udev->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
+
+@@ -1374,16 +1370,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend
+ *
+ * The caller must hold @udev's device lock.
+ */
+-int usb_disable_autosuspend(struct usb_device *udev)
++void usb_disable_autosuspend(struct usb_device *udev)
+ {
+- int rc = 0;
+-
+- if (!udev->autosuspend_disabled) {
+- rc = usb_autoresume_device(udev);
+- if (rc == 0)
+- udev->autosuspend_disabled = 1;
+- }
+- return rc;
++ pm_runtime_forbid(&udev->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
+
+@@ -1527,7 +1516,7 @@ void usb_autopm_put_interface_async(stru
+ atomic_dec(&intf->pm_usage_cnt);
+ pm_runtime_put_noidle(&intf->dev);
+
+- if (!udev->autosuspend_disabled) {
++ if (udev->dev.power.runtime_auto) {
+ /* Optimization: Don't schedule a delayed autosuspend if
+ * the timer is already running and the expiration time
+ * wouldn't change.
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -389,7 +389,7 @@ show_level(struct device *dev, struct de
+ struct usb_device *udev = to_usb_device(dev);
+ const char *p = auto_string;
+
+- if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
++ if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
+ p = on_string;
+ return sprintf(buf, "%s\n", p);
+ }
+@@ -401,7 +401,7 @@ set_level(struct device *dev, struct dev
+ struct usb_device *udev = to_usb_device(dev);
+ int len = count;
+ char *cp;
+- int rc;
++ int rc = count;
+
+ cp = memchr(buf, '\n', count);
+ if (cp)
+@@ -411,17 +411,17 @@ set_level(struct device *dev, struct dev
+
+ if (len == sizeof on_string - 1 &&
+ strncmp(buf, on_string, len) == 0)
+- rc = usb_disable_autosuspend(udev);
++ usb_disable_autosuspend(udev);
+
+ else if (len == sizeof auto_string - 1 &&
+ strncmp(buf, auto_string, len) == 0)
+- rc = usb_enable_autosuspend(udev);
++ usb_enable_autosuspend(udev);
+
+ else
+ rc = -EINVAL;
+
+ usb_unlock_device(udev);
+- return (rc < 0 ? rc : count);
++ return rc;
+ }
+
+ static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -425,7 +425,6 @@ struct usb_tt;
+ * @connect_time: time device was first connected
+ * @do_remote_wakeup: remote wakeup should be enabled
+ * @reset_resume: needs reset instead of resume
+- * @autosuspend_disabled: autosuspend disabled by the user
+ * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+ * specific data for the device.
+ * @slot_id: Slot ID assigned by xHCI
+@@ -501,7 +500,6 @@ struct usb_device {
+
+ unsigned do_remote_wakeup:1;
+ unsigned reset_resume:1;
+- unsigned autosuspend_disabled:1;
+ #endif
+ struct wusb_dev *wusb_dev;
+ int slot_id;
+@@ -526,8 +524,8 @@ extern struct usb_device *usb_find_devic
+
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
+-extern int usb_enable_autosuspend(struct usb_device *udev);
+-extern int usb_disable_autosuspend(struct usb_device *udev);
++extern void usb_enable_autosuspend(struct usb_device *udev);
++extern void usb_disable_autosuspend(struct usb_device *udev);
+
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
diff --git a/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch b/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch
new file mode 100644
index 00000000000000..4d105b56152851
--- /dev/null
+++ b/usb/usb-xhci-correct-assumptions-about-number-of-rings-per-endpoint.patch
@@ -0,0 +1,802 @@
+From sarah.a.sharp@linux.intel.com Thu Apr 29 12:59:23 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 2 Apr 2010 15:34:43 -0700
+Subject: USB: xhci: Correct assumptions about number of rings per endpoint.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, usb-storage@lists.one-eyed-alien.net, Hrant Dalalyan <Hrant.Dalalyan@synopsys.com>, Alan Stern <stern@rowland.harvard.edu>, Paul Zimmerman <Paul.Zimmerman@synopsys.com>, Ashot Madatyan <Ashot.Madatyan@synopsys.com>
+Message-ID: <20100402223443.GA1354@xanatos>
+Content-Disposition: inline
+
+
+Much of the xHCI driver code assumes that endpoints only have one ring.
+Now an endpoint can have one ring per enabled stream ID, so correct that
+assumption. Use functions that translate the stream_id field in the URB
+or the DMA address of a TRB into the correct stream ring.
+
+Correct the polling loop to print out all enabled stream rings. Make the
+URB cancellation routine find the correct stream ring if the URB has
+stream_id set. Make sure the URB enqueueing routine does the same. Also
+correct the code that handles stalled/halted endpoints.
+
+Check that commands and registers that can take stream IDs handle them
+properly. That includes ringing an endpoint doorbell, resetting a
+stalled/halted endpoint, and setting a transfer ring dequeue pointer
+(since that command can set the dequeue pointer in a stream context or an
+endpoint context).
+
+Correct the transfer event handler to translate a TRB DMA address into the
+stream ring it was enqueued to. Make the code to allocate and prepare TD
+structures adds the TD to the right td_list for the stream ring. Make
+sure the code to give the first TRB in a TD to the hardware manipulates
+the correct stream ring.
+
+When an endpoint stalls, store the stream ID of the stream ring that
+stalled in the xhci_virt_ep structure. Use that instead of the stream ID
+in the URB, since an URB may be re-used after it is given back after a
+non-control endpoint stall.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-dbg.c | 24 +++++
+ drivers/usb/host/xhci-mem.c | 74 ++++++++++++++++
+ drivers/usb/host/xhci-ring.c | 192 ++++++++++++++++++++++++++++++++-----------
+ drivers/usb/host/xhci.c | 19 ++--
+ drivers/usb/host/xhci.h | 26 +++++
+ 5 files changed, 280 insertions(+), 55 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -364,6 +364,30 @@ void xhci_debug_ring(struct xhci_hcd *xh
+ xhci_debug_segment(xhci, seg);
+ }
+
++void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
++ unsigned int slot_id, unsigned int ep_index,
++ struct xhci_virt_ep *ep)
++{
++ int i;
++ struct xhci_ring *ring;
++
++ if (ep->ep_state & EP_HAS_STREAMS) {
++ for (i = 1; i < ep->stream_info->num_streams; i++) {
++ ring = ep->stream_info->stream_rings[i];
++ xhci_dbg(xhci, "Dev %d endpoint %d stream ID %d:\n",
++ slot_id, ep_index, i);
++ xhci_debug_segment(xhci, ring->deq_seg);
++ }
++ } else {
++ ring = ep->ring;
++ if (!ring)
++ return;
++ xhci_dbg(xhci, "Dev %d endpoint ring %d:\n",
++ slot_id, ep_index);
++ xhci_debug_segment(xhci, ring->deq_seg);
++ }
++}
++
+ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
+ {
+ u32 addr = (u32) erst->erst_dma_addr;
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -353,8 +353,19 @@ struct xhci_stream_ctx *xhci_alloc_strea
+ mem_flags, dma);
+ }
+
++struct xhci_ring *xhci_dma_to_transfer_ring(
++ struct xhci_virt_ep *ep,
++ u64 address)
++{
++ if (ep->ep_state & EP_HAS_STREAMS)
++ return radix_tree_lookup(&ep->stream_info->trb_address_map,
++ address >> SEGMENT_SHIFT);
++ return ep->ring;
++}
++
++/* Only use this when you know stream_info is valid */
+ #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+-struct xhci_ring *dma_to_stream_ring(
++static struct xhci_ring *dma_to_stream_ring(
+ struct xhci_stream_info *stream_info,
+ u64 address)
+ {
+@@ -363,6 +374,66 @@ struct xhci_ring *dma_to_stream_ring(
+ }
+ #endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
+
++struct xhci_ring *xhci_stream_id_to_ring(
++ struct xhci_virt_device *dev,
++ unsigned int ep_index,
++ unsigned int stream_id)
++{
++ struct xhci_virt_ep *ep = &dev->eps[ep_index];
++
++ if (stream_id == 0)
++ return ep->ring;
++ if (!ep->stream_info)
++ return NULL;
++
++ if (stream_id > ep->stream_info->num_streams)
++ return NULL;
++ return ep->stream_info->stream_rings[stream_id];
++}
++
++struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci,
++ unsigned int slot_id, unsigned int ep_index,
++ unsigned int stream_id)
++{
++ struct xhci_virt_ep *ep;
++
++ ep = &xhci->devs[slot_id]->eps[ep_index];
++ /* Common case: no streams */
++ if (!(ep->ep_state & EP_HAS_STREAMS))
++ return ep->ring;
++
++ if (stream_id == 0) {
++ xhci_warn(xhci,
++ "WARN: Slot ID %u, ep index %u has streams, "
++ "but URB has no stream ID.\n",
++ slot_id, ep_index);
++ return NULL;
++ }
++
++ if (stream_id < ep->stream_info->num_streams)
++ return ep->stream_info->stream_rings[stream_id];
++
++ xhci_warn(xhci,
++ "WARN: Slot ID %u, ep index %u has "
++ "stream IDs 1 to %u allocated, "
++ "but stream ID %u is requested.\n",
++ slot_id, ep_index,
++ ep->stream_info->num_streams - 1,
++ stream_id);
++ return NULL;
++}
++
++/* Get the right ring for the given URB.
++ * If the endpoint supports streams, boundary check the URB's stream ID.
++ * If the endpoint doesn't support streams, return the singular endpoint ring.
++ */
++struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
++ struct urb *urb)
++{
++ return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id,
++ xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id);
++}
++
+ #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+ static int xhci_test_radix_tree(struct xhci_hcd *xhci,
+ unsigned int num_streams,
+@@ -515,6 +586,7 @@ struct xhci_stream_info *xhci_alloc_stre
+ cur_ring = stream_info->stream_rings[cur_stream];
+ if (!cur_ring)
+ goto cleanup_rings;
++ cur_ring->stream_id = cur_stream;
+ /* Set deq ptr, cycle bit, and stream context type */
+ addr = cur_ring->first_seg->dma |
+ SCT_FOR_CTX(SCT_PRI_TR) |
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -295,7 +295,8 @@ void xhci_ring_cmd_db(struct xhci_hcd *x
+
+ static void ring_ep_doorbell(struct xhci_hcd *xhci,
+ unsigned int slot_id,
+- unsigned int ep_index)
++ unsigned int ep_index,
++ unsigned int stream_id)
+ {
+ struct xhci_virt_ep *ep;
+ unsigned int ep_state;
+@@ -314,7 +315,8 @@ static void ring_ep_doorbell(struct xhci
+ if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
+ && !(ep_state & EP_HALTED)) {
+ field = xhci_readl(xhci, db_addr) & DB_MASK;
+- xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
++ field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id);
++ xhci_writel(xhci, field, db_addr);
+ /* Flush PCI posted writes - FIXME Matthew Wilcox says this
+ * isn't time-critical and we shouldn't make the CPU wait for
+ * the flush.
+@@ -323,6 +325,31 @@ static void ring_ep_doorbell(struct xhci
+ }
+ }
+
++/* Ring the doorbell for any rings with pending URBs */
++static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
++ unsigned int slot_id,
++ unsigned int ep_index)
++{
++ unsigned int stream_id;
++ struct xhci_virt_ep *ep;
++
++ ep = &xhci->devs[slot_id]->eps[ep_index];
++
++ /* A ring has pending URBs if its TD list is not empty */
++ if (!(ep->ep_state & EP_HAS_STREAMS)) {
++ if (!(list_empty(&ep->ring->td_list)))
++ ring_ep_doorbell(xhci, slot_id, ep_index, 0);
++ return;
++ }
++
++ for (stream_id = 1; stream_id < ep->stream_info->num_streams;
++ stream_id++) {
++ struct xhci_stream_info *stream_info = ep->stream_info;
++ if (!list_empty(&stream_info->stream_rings[stream_id]->td_list))
++ ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
++ }
++}
++
+ /*
+ * Find the segment that trb is in. Start searching in start_seg.
+ * If we must move past a segment that has a link TRB with a toggle cycle state
+@@ -365,14 +392,23 @@ static struct xhci_segment *find_trb_seg
+ */
+ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+- struct xhci_td *cur_td, struct xhci_dequeue_state *state)
++ unsigned int stream_id, struct xhci_td *cur_td,
++ struct xhci_dequeue_state *state)
+ {
+ struct xhci_virt_device *dev = xhci->devs[slot_id];
+- struct xhci_ring *ep_ring = dev->eps[ep_index].ring;
++ struct xhci_ring *ep_ring;
+ struct xhci_generic_trb *trb;
+ struct xhci_ep_ctx *ep_ctx;
+ dma_addr_t addr;
+
++ ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
++ ep_index, stream_id);
++ if (!ep_ring) {
++ xhci_warn(xhci, "WARN can't find new dequeue state "
++ "for invalid stream ID %u.\n",
++ stream_id);
++ return;
++ }
+ state->new_cycle_state = 0;
+ xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
+ state->new_deq_seg = find_trb_seg(cur_td->start_seg,
+@@ -452,11 +488,13 @@ static void td_to_noop(struct xhci_hcd *
+ }
+
+ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
+- unsigned int ep_index, struct xhci_segment *deq_seg,
++ unsigned int ep_index, unsigned int stream_id,
++ struct xhci_segment *deq_seg,
+ union xhci_trb *deq_ptr, u32 cycle_state);
+
+ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
++ unsigned int stream_id,
+ struct xhci_dequeue_state *deq_state)
+ {
+ struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+@@ -468,7 +506,7 @@ void xhci_queue_new_dequeue_state(struct
+ deq_state->new_deq_ptr,
+ (unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
+ deq_state->new_cycle_state);
+- queue_set_tr_deq(xhci, slot_id, ep_index,
++ queue_set_tr_deq(xhci, slot_id, ep_index, stream_id,
+ deq_state->new_deq_seg,
+ deq_state->new_deq_ptr,
+ (u32) deq_state->new_cycle_state);
+@@ -536,11 +574,10 @@ static void handle_stopped_endpoint(stru
+ slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+ ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ ep = &xhci->devs[slot_id]->eps[ep_index];
+- ep_ring = ep->ring;
+
+ if (list_empty(&ep->cancelled_td_list)) {
+ xhci_stop_watchdog_timer_in_irq(xhci, ep);
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ return;
+ }
+
+@@ -554,15 +591,36 @@ static void handle_stopped_endpoint(stru
+ xhci_dbg(xhci, "Cancelling TD starting at %p, 0x%llx (dma).\n",
+ cur_td->first_trb,
+ (unsigned long long)xhci_trb_virt_to_dma(cur_td->start_seg, cur_td->first_trb));
++ ep_ring = xhci_urb_to_transfer_ring(xhci, cur_td->urb);
++ if (!ep_ring) {
++ /* This shouldn't happen unless a driver is mucking
++ * with the stream ID after submission. This will
++ * leave the TD on the hardware ring, and the hardware
++ * will try to execute it, and may access a buffer
++ * that has already been freed. In the best case, the
++ * hardware will execute it, and the event handler will
++ * ignore the completion event for that TD, since it was
++ * removed from the td_list for that endpoint. In
++ * short, don't muck with the stream ID after
++ * submission.
++ */
++ xhci_warn(xhci, "WARN Cancelled URB %p "
++ "has invalid stream ID %u.\n",
++ cur_td->urb,
++ cur_td->urb->stream_id);
++ goto remove_finished_td;
++ }
+ /*
+ * If we stopped on the TD we need to cancel, then we have to
+ * move the xHC endpoint ring dequeue pointer past this TD.
+ */
+ if (cur_td == ep->stopped_td)
+- xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
+- &deq_state);
++ xhci_find_new_dequeue_state(xhci, slot_id, ep_index,
++ cur_td->urb->stream_id,
++ cur_td, &deq_state);
+ else
+ td_to_noop(xhci, ep_ring, cur_td);
++remove_finished_td:
+ /*
+ * The event handler won't see a completion for this TD anymore,
+ * so remove it from the endpoint ring's TD list. Keep it in
+@@ -576,11 +634,13 @@ static void handle_stopped_endpoint(stru
+ /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
+ if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
+ xhci_queue_new_dequeue_state(xhci,
+- slot_id, ep_index, &deq_state);
++ slot_id, ep_index,
++ ep->stopped_td->urb->stream_id,
++ &deq_state);
+ xhci_ring_cmd_db(xhci);
+ } else {
+- /* Otherwise just ring the doorbell to restart the ring */
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ /* Otherwise ring the doorbell(s) to restart queued transfers */
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ }
+
+ /*
+@@ -738,6 +798,7 @@ static void handle_set_deq_completion(st
+ {
+ unsigned int slot_id;
+ unsigned int ep_index;
++ unsigned int stream_id;
+ struct xhci_ring *ep_ring;
+ struct xhci_virt_device *dev;
+ struct xhci_ep_ctx *ep_ctx;
+@@ -745,8 +806,19 @@ static void handle_set_deq_completion(st
+
+ slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+ ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
++ stream_id = TRB_TO_STREAM_ID(trb->generic.field[2]);
+ dev = xhci->devs[slot_id];
+- ep_ring = dev->eps[ep_index].ring;
++
++ ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
++ if (!ep_ring) {
++ xhci_warn(xhci, "WARN Set TR deq ptr command for "
++ "freed stream ID %u\n",
++ stream_id);
++ /* XXX: Harmless??? */
++ dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
++ return;
++ }
++
+ ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
+ slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
+
+@@ -791,7 +863,8 @@ static void handle_set_deq_completion(st
+ }
+
+ dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ /* Restart any rings with pending URBs */
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ }
+
+ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
+@@ -800,11 +873,9 @@ static void handle_reset_ep_completion(s
+ {
+ int slot_id;
+ unsigned int ep_index;
+- struct xhci_ring *ep_ring;
+
+ slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+ ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+- ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
+ /* This command will only fail if the endpoint wasn't halted,
+ * but we don't care.
+ */
+@@ -822,9 +893,9 @@ static void handle_reset_ep_completion(s
+ false);
+ xhci_ring_cmd_db(xhci);
+ } else {
+- /* Clear our internal halted state and restart the ring */
++ /* Clear our internal halted state and restart the ring(s) */
+ xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ }
+ }
+
+@@ -910,8 +981,10 @@ static void handle_cmd_completion(struct
+ /* Input ctx add_flags are the endpoint index plus one */
+ ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
+ /* A usb_set_interface() call directly after clearing a halted
+- * condition may race on this quirky hardware.
+- * Not worth worrying about, since this is prototype hardware.
++ * condition may race on this quirky hardware. Not worth
++ * worrying about, since this is prototype hardware. Not sure
++ * if this will work for streams, but streams support was
++ * untested on this prototype.
+ */
+ if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
+ ep_index != (unsigned int) -1 &&
+@@ -924,10 +997,10 @@ static void handle_cmd_completion(struct
+ xhci_dbg(xhci, "Completed config ep cmd - "
+ "last ep index = %d, state = %d\n",
+ ep_index, ep_state);
+- /* Clear our internal halted state and restart ring */
++ /* Clear internal halted state and restart ring(s) */
+ xhci->devs[slot_id]->eps[ep_index].ep_state &=
+ ~EP_HALTED;
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ break;
+ }
+ bandwidth_change:
+@@ -1060,12 +1133,14 @@ struct xhci_segment *trb_in_td(struct xh
+
+ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
++ unsigned int stream_id,
+ struct xhci_td *td, union xhci_trb *event_trb)
+ {
+ struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+ ep->ep_state |= EP_HALTED;
+ ep->stopped_td = td;
+ ep->stopped_trb = event_trb;
++ ep->stopped_stream = stream_id;
+ xhci_queue_reset_ep(xhci, slot_id, ep_index);
+ xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
+ xhci_ring_cmd_db(xhci);
+@@ -1145,10 +1220,11 @@ static int handle_tx_event(struct xhci_h
+ ep_index = TRB_TO_EP_ID(event->flags) - 1;
+ xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
+ ep = &xdev->eps[ep_index];
+- ep_ring = ep->ring;
++ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+ if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+- xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
++ xhci_err(xhci, "ERROR Transfer event for disabled endpoint "
++ "or incorrect stream ring\n");
+ return -ENODEV;
+ }
+
+@@ -1279,7 +1355,7 @@ static int handle_tx_event(struct xhci_h
+ td->urb->actual_length = 0;
+
+ xhci_cleanup_halted_endpoint(xhci,
+- slot_id, ep_index, td, event_trb);
++ slot_id, ep_index, 0, td, event_trb);
+ goto td_cleanup;
+ }
+ /*
+@@ -1428,6 +1504,7 @@ static int handle_tx_event(struct xhci_h
+ */
+ ep->stopped_td = td;
+ ep->stopped_trb = event_trb;
++ ep->stopped_stream = ep_ring->stream_id;
+ } else if (xhci_requires_manual_halt_cleanup(xhci,
+ ep_ctx, trb_comp_code)) {
+ /* Other types of errors halt the endpoint, but the
+@@ -1436,7 +1513,7 @@ static int handle_tx_event(struct xhci_h
+ * xHCI hardware manually.
+ */
+ xhci_cleanup_halted_endpoint(xhci,
+- slot_id, ep_index, td, event_trb);
++ slot_id, ep_index, ep_ring->stream_id, td, event_trb);
+ } else {
+ /* Update ring dequeue pointer */
+ while (ep_ring->dequeue != td->last_trb)
+@@ -1632,14 +1709,24 @@ static int prepare_ring(struct xhci_hcd
+ static int prepare_transfer(struct xhci_hcd *xhci,
+ struct xhci_virt_device *xdev,
+ unsigned int ep_index,
++ unsigned int stream_id,
+ unsigned int num_trbs,
+ struct urb *urb,
+ struct xhci_td **td,
+ gfp_t mem_flags)
+ {
+ int ret;
++ struct xhci_ring *ep_ring;
+ struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+- ret = prepare_ring(xhci, xdev->eps[ep_index].ring,
++
++ ep_ring = xhci_stream_id_to_ring(xdev, ep_index, stream_id);
++ if (!ep_ring) {
++ xhci_dbg(xhci, "Can't prepare ring for bad stream ID %u\n",
++ stream_id);
++ return -EINVAL;
++ }
++
++ ret = prepare_ring(xhci, ep_ring,
+ ep_ctx->ep_info & EP_STATE_MASK,
+ num_trbs, mem_flags);
+ if (ret)
+@@ -1659,9 +1746,9 @@ static int prepare_transfer(struct xhci_
+ (*td)->urb = urb;
+ urb->hcpriv = (void *) (*td);
+ /* Add this TD to the tail of the endpoint ring's TD list */
+- list_add_tail(&(*td)->td_list, &xdev->eps[ep_index].ring->td_list);
+- (*td)->start_seg = xdev->eps[ep_index].ring->enq_seg;
+- (*td)->first_trb = xdev->eps[ep_index].ring->enqueue;
++ list_add_tail(&(*td)->td_list, &ep_ring->td_list);
++ (*td)->start_seg = ep_ring->enq_seg;
++ (*td)->first_trb = ep_ring->enqueue;
+
+ return 0;
+ }
+@@ -1727,7 +1814,7 @@ static void check_trb_math(struct urb *u
+ }
+
+ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
+- unsigned int ep_index, int start_cycle,
++ unsigned int ep_index, unsigned int stream_id, int start_cycle,
+ struct xhci_generic_trb *start_trb, struct xhci_td *td)
+ {
+ /*
+@@ -1736,7 +1823,7 @@ static void giveback_first_trb(struct xh
+ */
+ wmb();
+ start_trb->field[3] |= start_cycle;
+- ring_ep_doorbell(xhci, slot_id, ep_index);
++ ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+ }
+
+ /*
+@@ -1810,12 +1897,16 @@ static int queue_bulk_sg_tx(struct xhci_
+ struct xhci_generic_trb *start_trb;
+ int start_cycle;
+
+- ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
++ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
++ if (!ep_ring)
++ return -EINVAL;
++
+ num_trbs = count_sg_trbs_needed(xhci, urb);
+ num_sgs = urb->num_sgs;
+
+ trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+- ep_index, num_trbs, urb, &td, mem_flags);
++ ep_index, urb->stream_id,
++ num_trbs, urb, &td, mem_flags);
+ if (trb_buff_len < 0)
+ return trb_buff_len;
+ /*
+@@ -1924,7 +2015,8 @@ static int queue_bulk_sg_tx(struct xhci_
+ } while (running_total < urb->transfer_buffer_length);
+
+ check_trb_math(urb, num_trbs, running_total);
+- giveback_first_trb(xhci, slot_id, ep_index, start_cycle, start_trb, td);
++ giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
++ start_cycle, start_trb, td);
+ return 0;
+ }
+
+@@ -1946,7 +2038,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ if (urb->num_sgs)
+ return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
+
+- ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
++ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
++ if (!ep_ring)
++ return -EINVAL;
+
+ num_trbs = 0;
+ /* How much data is (potentially) left before the 64KB boundary? */
+@@ -1973,7 +2067,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ (unsigned long long)urb->transfer_dma,
+ num_trbs);
+
+- ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
++ ret = prepare_transfer(xhci, xhci->devs[slot_id],
++ ep_index, urb->stream_id,
+ num_trbs, urb, &td, mem_flags);
+ if (ret < 0)
+ return ret;
+@@ -2043,7 +2138,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ } while (running_total < urb->transfer_buffer_length);
+
+ check_trb_math(urb, num_trbs, running_total);
+- giveback_first_trb(xhci, slot_id, ep_index, start_cycle, start_trb, td);
++ giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
++ start_cycle, start_trb, td);
+ return 0;
+ }
+
+@@ -2060,7 +2156,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ u32 field, length_field;
+ struct xhci_td *td;
+
+- ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
++ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
++ if (!ep_ring)
++ return -EINVAL;
+
+ /*
+ * Need to copy setup packet into setup TRB, so we can't use the setup
+@@ -2081,8 +2179,9 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ */
+ if (urb->transfer_buffer_length > 0)
+ num_trbs++;
+- ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, num_trbs,
+- urb, &td, mem_flags);
++ ret = prepare_transfer(xhci, xhci->devs[slot_id],
++ ep_index, urb->stream_id,
++ num_trbs, urb, &td, mem_flags);
+ if (ret < 0)
+ return ret;
+
+@@ -2137,7 +2236,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ /* Event on completion */
+ field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state);
+
+- giveback_first_trb(xhci, slot_id, ep_index, start_cycle, start_trb, td);
++ giveback_first_trb(xhci, slot_id, ep_index, 0,
++ start_cycle, start_trb, td);
+ return 0;
+ }
+
+@@ -2249,12 +2349,14 @@ int xhci_queue_stop_endpoint(struct xhci
+ * This should not be used for endpoints that have streams enabled.
+ */
+ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
+- unsigned int ep_index, struct xhci_segment *deq_seg,
++ unsigned int ep_index, unsigned int stream_id,
++ struct xhci_segment *deq_seg,
+ union xhci_trb *deq_ptr, u32 cycle_state)
+ {
+ dma_addr_t addr;
+ u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
+ u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
++ u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
+ u32 type = TRB_TYPE(TRB_SET_DEQ);
+
+ addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
+@@ -2265,7 +2367,7 @@ static int queue_set_tr_deq(struct xhci_
+ return 0;
+ }
+ return queue_command(xhci, lower_32_bits(addr) | cycle_state,
+- upper_32_bits(addr), 0,
++ upper_32_bits(addr), trb_stream_id,
+ trb_slot_id | trb_ep_index | type, false);
+ }
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -353,11 +353,7 @@ void xhci_event_ring_work(unsigned long
+ if (!xhci->devs[i])
+ continue;
+ for (j = 0; j < 31; ++j) {
+- struct xhci_ring *ring = xhci->devs[i]->eps[j].ring;
+- if (!ring)
+- continue;
+- xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j);
+- xhci_debug_segment(xhci, ring->deq_seg);
++ xhci_dbg_ep_rings(xhci, i, j, &xhci->devs[i]->eps[j]);
+ }
+ }
+
+@@ -839,7 +835,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+ xhci_debug_ring(xhci, xhci->event_ring);
+ ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+ ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
+- ep_ring = ep->ring;
++ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
++ if (!ep_ring) {
++ ret = -EINVAL;
++ goto done;
++ }
++
+ xhci_dbg(xhci, "Endpoint ring:\n");
+ xhci_debug_ring(xhci, ep_ring);
+ td = (struct xhci_td *) urb->hcpriv;
+@@ -1383,7 +1384,7 @@ void xhci_cleanup_stalled_ring(struct xh
+ * or it will attempt to resend it on the next doorbell ring.
+ */
+ xhci_find_new_dequeue_state(xhci, udev->slot_id,
+- ep_index, ep->stopped_td,
++ ep_index, ep->stopped_stream, ep->stopped_td,
+ &deq_state);
+
+ /* HW with the reset endpoint quirk will use the saved dequeue state to
+@@ -1392,10 +1393,12 @@ void xhci_cleanup_stalled_ring(struct xh
+ if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
+ xhci_dbg(xhci, "Queueing new dequeue state\n");
+ xhci_queue_new_dequeue_state(xhci, udev->slot_id,
+- ep_index, &deq_state);
++ ep_index, ep->stopped_stream, &deq_state);
+ } else {
+ /* Better hope no one uses the input context between now and the
+ * reset endpoint completion!
++ * XXX: No idea how this hardware will react when stream rings
++ * are enabled.
+ */
+ xhci_dbg(xhci, "Setting up input context for "
+ "configure endpoint command\n");
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -444,6 +444,7 @@ struct xhci_doorbell_array {
+
+ /* Endpoint Target - bits 0:7 */
+ #define EPI_TO_DB(p) (((p) + 1) & 0xff)
++#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16)
+
+
+ /**
+@@ -714,6 +715,7 @@ struct xhci_virt_ep {
+ /* The TRB that was last reported in a stopped endpoint ring */
+ union xhci_trb *stopped_trb;
+ struct xhci_td *stopped_td;
++ unsigned int stopped_stream;
+ /* Watchdog timer for stop endpoint command to cancel URBs */
+ struct timer_list stop_cmd_timer;
+ int stop_cmds_pending;
+@@ -871,6 +873,10 @@ struct xhci_event_cmd {
+ #define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1)
+ #define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16)
+
++/* Set TR Dequeue Pointer command TRB fields */
++#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16))
++#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16)
++
+
+ /* Port Status Change Event TRB fields */
+ /* Port ID - bits 31:24 */
+@@ -1040,6 +1046,7 @@ struct xhci_ring {
+ * if we own the TRB (if we are the consumer). See section 4.9.1.
+ */
+ u32 cycle_state;
++ unsigned int stream_id;
+ };
+
+ struct xhci_erst_entry {
+@@ -1265,6 +1272,9 @@ void xhci_dbg_ring_ptrs(struct xhci_hcd
+ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
+ char *xhci_get_slot_state(struct xhci_hcd *xhci,
+ struct xhci_container_ctx *ctx);
++void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
++ unsigned int slot_id, unsigned int ep_index,
++ struct xhci_virt_ep *ep);
+
+ /* xHCI memory management */
+ void xhci_mem_cleanup(struct xhci_hcd *xhci);
+@@ -1302,6 +1312,18 @@ void xhci_setup_streams_ep_input_ctx(str
+ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
+ struct xhci_ep_ctx *ep_ctx,
+ struct xhci_virt_ep *ep);
++struct xhci_ring *xhci_dma_to_transfer_ring(
++ struct xhci_virt_ep *ep,
++ u64 address);
++struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
++ struct urb *urb);
++struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci,
++ unsigned int slot_id, unsigned int ep_index,
++ unsigned int stream_id);
++struct xhci_ring *xhci_stream_id_to_ring(
++ struct xhci_virt_device *dev,
++ unsigned int ep_index,
++ unsigned int stream_id);
+ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
+ bool allocate_in_ctx, bool allocate_completion,
+ gfp_t mem_flags);
+@@ -1374,9 +1396,11 @@ int xhci_queue_reset_ep(struct xhci_hcd
+ int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
+ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+- struct xhci_td *cur_td, struct xhci_dequeue_state *state);
++ unsigned int stream_id, struct xhci_td *cur_td,
++ struct xhci_dequeue_state *state);
+ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
++ unsigned int stream_id,
+ struct xhci_dequeue_state *deq_state);
+ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+ struct usb_device *udev, unsigned int ep_index);
diff --git a/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch b/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch
new file mode 100644
index 00000000000000..ff63b742ffc749
--- /dev/null
+++ b/usb/xhci-add-memory-allocation-for-usb3-bulk-streams.patch
@@ -0,0 +1,1086 @@
+From sarah.a.sharp@linux.intel.com Thu Apr 29 12:59:13 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 2 Apr 2010 15:34:16 -0700
+Subject: USB: xhci: Add memory allocation for USB3 bulk streams.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, usb-storage@lists.one-eyed-alien.net, Hrant Dalalyan <Hrant.Dalalyan@synopsys.com>, Alan Stern <stern@rowland.harvard.edu>, Paul Zimmerman <Paul.Zimmerman@synopsys.com>, Ashot Madatyan <Ashot.Madatyan@synopsys.com>
+Message-ID: <20100402223416.GA1318@xanatos>
+Content-Disposition: inline
+
+
+Add support for allocating streams for USB 3.0 bulk endpoints. See
+Documentation/usb/bulk-streams.txt for more information about how and why
+you would use streams.
+
+When an endpoint has streams enabled, instead of having one ring where all
+transfers are enqueued to the hardware, it has several rings. The ring
+dequeue pointer in the endpoint context is changed to point to a "Stream
+Context Array". This is basically an array of pointers to transfer rings,
+one for each stream ID that the driver wants to use.
+
+The Stream Context Array size must be a power of two, and host controllers
+can place a limit on the size of the array (4 to 2^16 entries). These
+two facts make calculating the size of the Stream Context Array and the
+number of entries actually used by the driver a bit tricky.
+
+Besides the Stream Context Array and rings for all the stream IDs, we need
+one more data structure. The xHCI hardware will not tell us which stream
+ID a transfer event was for, but it will give us the slot ID, endpoint
+index, and physical address for the TRB that caused the event. For every
+endpoint on a device, add a radix tree to map physical TRB addresses to
+virtual segments within a stream ring.
+
+Keep track of whether an endpoint is transitioning to using streams, and
+don't enqueue any URBs while that's taking place. Refuse to transition an
+endpoint to streams if there are already URBs enqueued for that endpoint.
+
+We need to make sure that freeing streams does not fail, since a driver's
+disconnect() function may attempt to do this, and it cannot fail.
+Pre-allocate the command structure used to issue the Configure Endpoint
+command, and reserve space on the command ring for each stream endpoint.
+This may be a bit overkill, but it is permissible for the driver to
+allocate all streams in one call and free them in multiple calls. (It is
+not advised, however, since it is a waste of resources and time.)
+
+Even with the memory and ring room pre-allocated, freeing streams can
+still fail because the xHC rejects the configure endpoint command. It is
+valid (by the xHCI 0.96 spec) to return a "Bandwidth Error" or a "Resource
+Error" for a configure endpoint command. We should never see a Bandwidth
+Error, since bulk endpoints do not effect the reserved bandwidth. The
+host controller can still return a Resource Error, but it's improbable
+since the xHC would be going from a more resource-intensive configuration
+(streams) to a less resource-intensive configuration (no streams).
+
+If the xHC returns a Resource Error, the endpoint will be stuck with
+streams and will be unusable for drivers. It's an unavoidable consequence
+of broken host controller hardware.
+
+Includes bug fixes from the original patch, contributed by
+John Youn <John.Youn@synopsys.com> and Andy Green <AGreen@PLXTech.com>
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 379 ++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci-ring.c | 9
+ drivers/usb/host/xhci.c | 399 ++++++++++++++++++++++++++++++++++++++++++-
+ drivers/usb/host/xhci.h | 84 ++++++++-
+ 4 files changed, 857 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -304,6 +304,350 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(stru
+ (ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params)));
+ }
+
++
++/***************** Streams structures manipulation *************************/
++
++void xhci_free_stream_ctx(struct xhci_hcd *xhci,
++ unsigned int num_stream_ctxs,
++ struct xhci_stream_ctx *stream_ctx, dma_addr_t dma)
++{
++ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++
++ if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE)
++ pci_free_consistent(pdev,
++ sizeof(struct xhci_stream_ctx)*num_stream_ctxs,
++ stream_ctx, dma);
++ else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE)
++ return dma_pool_free(xhci->small_streams_pool,
++ stream_ctx, dma);
++ else
++ return dma_pool_free(xhci->medium_streams_pool,
++ stream_ctx, dma);
++}
++
++/*
++ * The stream context array for each endpoint with bulk streams enabled can
++ * vary in size, based on:
++ * - how many streams the endpoint supports,
++ * - the maximum primary stream array size the host controller supports,
++ * - and how many streams the device driver asks for.
++ *
++ * The stream context array must be a power of 2, and can be as small as
++ * 64 bytes or as large as 1MB.
++ */
++struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci,
++ unsigned int num_stream_ctxs, dma_addr_t *dma,
++ gfp_t mem_flags)
++{
++ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++
++ if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE)
++ return pci_alloc_consistent(pdev,
++ sizeof(struct xhci_stream_ctx)*num_stream_ctxs,
++ dma);
++ else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE)
++ return dma_pool_alloc(xhci->small_streams_pool,
++ mem_flags, dma);
++ else
++ return dma_pool_alloc(xhci->medium_streams_pool,
++ mem_flags, dma);
++}
++
++#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
++struct xhci_ring *dma_to_stream_ring(
++ struct xhci_stream_info *stream_info,
++ u64 address)
++{
++ return radix_tree_lookup(&stream_info->trb_address_map,
++ address >> SEGMENT_SHIFT);
++}
++#endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
++
++#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
++static int xhci_test_radix_tree(struct xhci_hcd *xhci,
++ unsigned int num_streams,
++ struct xhci_stream_info *stream_info)
++{
++ u32 cur_stream;
++ struct xhci_ring *cur_ring;
++ u64 addr;
++
++ for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
++ struct xhci_ring *mapped_ring;
++ int trb_size = sizeof(union xhci_trb);
++
++ cur_ring = stream_info->stream_rings[cur_stream];
++ for (addr = cur_ring->first_seg->dma;
++ addr < cur_ring->first_seg->dma + SEGMENT_SIZE;
++ addr += trb_size) {
++ mapped_ring = dma_to_stream_ring(stream_info, addr);
++ if (cur_ring != mapped_ring) {
++ xhci_warn(xhci, "WARN: DMA address 0x%08llx "
++ "didn't map to stream ID %u; "
++ "mapped to ring %p\n",
++ (unsigned long long) addr,
++ cur_stream,
++ mapped_ring);
++ return -EINVAL;
++ }
++ }
++ /* One TRB after the end of the ring segment shouldn't return a
++ * pointer to the current ring (although it may be a part of a
++ * different ring).
++ */
++ mapped_ring = dma_to_stream_ring(stream_info, addr);
++ if (mapped_ring != cur_ring) {
++ /* One TRB before should also fail */
++ addr = cur_ring->first_seg->dma - trb_size;
++ mapped_ring = dma_to_stream_ring(stream_info, addr);
++ }
++ if (mapped_ring == cur_ring) {
++ xhci_warn(xhci, "WARN: Bad DMA address 0x%08llx "
++ "mapped to valid stream ID %u; "
++ "mapped ring = %p\n",
++ (unsigned long long) addr,
++ cur_stream,
++ mapped_ring);
++ return -EINVAL;
++ }
++ }
++ return 0;
++}
++#endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
++
++/*
++ * Change an endpoint's internal structure so it supports stream IDs. The
++ * number of requested streams includes stream 0, which cannot be used by device
++ * drivers.
++ *
++ * The number of stream contexts in the stream context array may be bigger than
++ * the number of streams the driver wants to use. This is because the number of
++ * stream context array entries must be a power of two.
++ *
++ * We need a radix tree for mapping physical addresses of TRBs to which stream
++ * ID they belong to. We need to do this because the host controller won't tell
++ * us which stream ring the TRB came from. We could store the stream ID in an
++ * event data TRB, but that doesn't help us for the cancellation case, since the
++ * endpoint may stop before it reaches that event data TRB.
++ *
++ * The radix tree maps the upper portion of the TRB DMA address to a ring
++ * segment that has the same upper portion of DMA addresses. For example, say I
++ * have segments of size 1KB, that are always 64-byte aligned. A segment may
++ * start at 0x10c91000 and end at 0x10c913f0. If I use the upper 10 bits, the
++ * key to the stream ID is 0x43244. I can use the DMA address of the TRB to
++ * pass the radix tree a key to get the right stream ID:
++ *
++ * 0x10c90fff >> 10 = 0x43243
++ * 0x10c912c0 >> 10 = 0x43244
++ * 0x10c91400 >> 10 = 0x43245
++ *
++ * Obviously, only those TRBs with DMA addresses that are within the segment
++ * will make the radix tree return the stream ID for that ring.
++ *
++ * Caveats for the radix tree:
++ *
++ * The radix tree uses an unsigned long as a key pair. On 32-bit systems, an
++ * unsigned long will be 32-bits; on a 64-bit system an unsigned long will be
++ * 64-bits. Since we only request 32-bit DMA addresses, we can use that as the
++ * key on 32-bit or 64-bit systems (it would also be fine if we asked for 64-bit
++ * PCI DMA addresses on a 64-bit system). There might be a problem on 32-bit
++ * extended systems (where the DMA address can be bigger than 32-bits),
++ * if we allow the PCI dma mask to be bigger than 32-bits. So don't do that.
++ */
++struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
++ unsigned int num_stream_ctxs,
++ unsigned int num_streams, gfp_t mem_flags)
++{
++ struct xhci_stream_info *stream_info;
++ u32 cur_stream;
++ struct xhci_ring *cur_ring;
++ unsigned long key;
++ u64 addr;
++ int ret;
++
++ xhci_dbg(xhci, "Allocating %u streams and %u "
++ "stream context array entries.\n",
++ num_streams, num_stream_ctxs);
++ if (xhci->cmd_ring_reserved_trbs == MAX_RSVD_CMD_TRBS) {
++ xhci_dbg(xhci, "Command ring has no reserved TRBs available\n");
++ return NULL;
++ }
++ xhci->cmd_ring_reserved_trbs++;
++
++ stream_info = kzalloc(sizeof(struct xhci_stream_info), mem_flags);
++ if (!stream_info)
++ goto cleanup_trbs;
++
++ stream_info->num_streams = num_streams;
++ stream_info->num_stream_ctxs = num_stream_ctxs;
++
++ /* Initialize the array of virtual pointers to stream rings. */
++ stream_info->stream_rings = kzalloc(
++ sizeof(struct xhci_ring *)*num_streams,
++ mem_flags);
++ if (!stream_info->stream_rings)
++ goto cleanup_info;
++
++ /* Initialize the array of DMA addresses for stream rings for the HW. */
++ stream_info->stream_ctx_array = xhci_alloc_stream_ctx(xhci,
++ num_stream_ctxs, &stream_info->ctx_array_dma,
++ mem_flags);
++ if (!stream_info->stream_ctx_array)
++ goto cleanup_ctx;
++ memset(stream_info->stream_ctx_array, 0,
++ sizeof(struct xhci_stream_ctx)*num_stream_ctxs);
++
++ /* Allocate everything needed to free the stream rings later */
++ stream_info->free_streams_command =
++ xhci_alloc_command(xhci, true, true, mem_flags);
++ if (!stream_info->free_streams_command)
++ goto cleanup_ctx;
++
++ INIT_RADIX_TREE(&stream_info->trb_address_map, GFP_ATOMIC);
++
++ /* Allocate rings for all the streams that the driver will use,
++ * and add their segment DMA addresses to the radix tree.
++ * Stream 0 is reserved.
++ */
++ for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
++ stream_info->stream_rings[cur_stream] =
++ xhci_ring_alloc(xhci, 1, true, mem_flags);
++ cur_ring = stream_info->stream_rings[cur_stream];
++ if (!cur_ring)
++ goto cleanup_rings;
++ /* Set deq ptr, cycle bit, and stream context type */
++ addr = cur_ring->first_seg->dma |
++ SCT_FOR_CTX(SCT_PRI_TR) |
++ cur_ring->cycle_state;
++ stream_info->stream_ctx_array[cur_stream].stream_ring = addr;
++ xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
++ cur_stream, (unsigned long long) addr);
++
++ key = (unsigned long)
++ (cur_ring->first_seg->dma >> SEGMENT_SHIFT);
++ ret = radix_tree_insert(&stream_info->trb_address_map,
++ key, cur_ring);
++ if (ret) {
++ xhci_ring_free(xhci, cur_ring);
++ stream_info->stream_rings[cur_stream] = NULL;
++ goto cleanup_rings;
++ }
++ }
++ /* Leave the other unused stream ring pointers in the stream context
++ * array initialized to zero. This will cause the xHC to give us an
++ * error if the device asks for a stream ID we don't have setup (if it
++ * was any other way, the host controller would assume the ring is
++ * "empty" and wait forever for data to be queued to that stream ID).
++ */
++#if XHCI_DEBUG
++ /* Do a little test on the radix tree to make sure it returns the
++ * correct values.
++ */
++ if (xhci_test_radix_tree(xhci, num_streams, stream_info))
++ goto cleanup_rings;
++#endif
++
++ return stream_info;
++
++cleanup_rings:
++ for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
++ cur_ring = stream_info->stream_rings[cur_stream];
++ if (cur_ring) {
++ addr = cur_ring->first_seg->dma;
++ radix_tree_delete(&stream_info->trb_address_map,
++ addr >> SEGMENT_SHIFT);
++ xhci_ring_free(xhci, cur_ring);
++ stream_info->stream_rings[cur_stream] = NULL;
++ }
++ }
++ xhci_free_command(xhci, stream_info->free_streams_command);
++cleanup_ctx:
++ kfree(stream_info->stream_rings);
++cleanup_info:
++ kfree(stream_info);
++cleanup_trbs:
++ xhci->cmd_ring_reserved_trbs--;
++ return NULL;
++}
++/*
++ * Sets the MaxPStreams field and the Linear Stream Array field.
++ * Sets the dequeue pointer to the stream context array.
++ */
++void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci,
++ struct xhci_ep_ctx *ep_ctx,
++ struct xhci_stream_info *stream_info)
++{
++ u32 max_primary_streams;
++ /* MaxPStreams is the number of stream context array entries, not the
++ * number we're actually using. Must be in 2^(MaxPstreams + 1) format.
++ * fls(0) = 0, fls(0x1) = 1, fls(0x10) = 2, fls(0x100) = 3, etc.
++ */
++ max_primary_streams = fls(stream_info->num_stream_ctxs) - 2;
++ xhci_dbg(xhci, "Setting number of stream ctx array entries to %u\n",
++ 1 << (max_primary_streams + 1));
++ ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
++ ep_ctx->ep_info |= EP_MAXPSTREAMS(max_primary_streams);
++ ep_ctx->ep_info |= EP_HAS_LSA;
++ ep_ctx->deq = stream_info->ctx_array_dma;
++}
++
++/*
++ * Sets the MaxPStreams field and the Linear Stream Array field to 0.
++ * Reinstalls the "normal" endpoint ring (at its previous dequeue mark,
++ * not at the beginning of the ring).
++ */
++void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
++ struct xhci_ep_ctx *ep_ctx,
++ struct xhci_virt_ep *ep)
++{
++ dma_addr_t addr;
++ ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
++ ep_ctx->ep_info &= ~EP_HAS_LSA;
++ addr = xhci_trb_virt_to_dma(ep->ring->deq_seg, ep->ring->dequeue);
++ ep_ctx->deq = addr | ep->ring->cycle_state;
++}
++
++/* Frees all stream contexts associated with the endpoint,
++ *
++ * Caller should fix the endpoint context streams fields.
++ */
++void xhci_free_stream_info(struct xhci_hcd *xhci,
++ struct xhci_stream_info *stream_info)
++{
++ int cur_stream;
++ struct xhci_ring *cur_ring;
++ dma_addr_t addr;
++
++ if (!stream_info)
++ return;
++
++ for (cur_stream = 1; cur_stream < stream_info->num_streams;
++ cur_stream++) {
++ cur_ring = stream_info->stream_rings[cur_stream];
++ if (cur_ring) {
++ addr = cur_ring->first_seg->dma;
++ radix_tree_delete(&stream_info->trb_address_map,
++ addr >> SEGMENT_SHIFT);
++ xhci_ring_free(xhci, cur_ring);
++ stream_info->stream_rings[cur_stream] = NULL;
++ }
++ }
++ xhci_free_command(xhci, stream_info->free_streams_command);
++ xhci->cmd_ring_reserved_trbs--;
++ if (stream_info->stream_ctx_array)
++ xhci_free_stream_ctx(xhci,
++ stream_info->num_stream_ctxs,
++ stream_info->stream_ctx_array,
++ stream_info->ctx_array_dma);
++
++ if (stream_info)
++ kfree(stream_info->stream_rings);
++ kfree(stream_info);
++}
++
++
++/***************** Device context manipulation *************************/
++
+ static void xhci_init_endpoint_timer(struct xhci_hcd *xhci,
+ struct xhci_virt_ep *ep)
+ {
+@@ -328,9 +672,13 @@ void xhci_free_virt_device(struct xhci_h
+ if (!dev)
+ return;
+
+- for (i = 0; i < 31; ++i)
++ for (i = 0; i < 31; ++i) {
+ if (dev->eps[i].ring)
+ xhci_ring_free(xhci, dev->eps[i].ring);
++ if (dev->eps[i].stream_info)
++ xhci_free_stream_info(xhci,
++ dev->eps[i].stream_info);
++ }
+
+ if (dev->ring_cache) {
+ for (i = 0; i < dev->num_rings_cached; i++)
+@@ -655,6 +1003,9 @@ static inline u32 xhci_get_max_esit_payl
+ return max_packet * (max_burst + 1);
+ }
+
++/* Set up an endpoint with one ring segment. Do not allocate stream rings.
++ * Drivers will have to call usb_alloc_streams() to do that.
++ */
+ int xhci_endpoint_init(struct xhci_hcd *xhci,
+ struct xhci_virt_device *virt_dev,
+ struct usb_device *udev,
+@@ -1003,6 +1354,16 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ xhci->device_pool = NULL;
+ xhci_dbg(xhci, "Freed device context pool\n");
+
++ if (xhci->small_streams_pool)
++ dma_pool_destroy(xhci->small_streams_pool);
++ xhci->small_streams_pool = NULL;
++ xhci_dbg(xhci, "Freed small stream array pool\n");
++
++ if (xhci->medium_streams_pool)
++ dma_pool_destroy(xhci->medium_streams_pool);
++ xhci->medium_streams_pool = NULL;
++ xhci_dbg(xhci, "Freed medium stream array pool\n");
++
+ xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
+ if (xhci->dcbaa)
+ pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
+@@ -1239,6 +1600,22 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ if (!xhci->segment_pool || !xhci->device_pool)
+ goto fail;
+
++ /* Linear stream context arrays don't have any boundary restrictions,
++ * and only need to be 16-byte aligned.
++ */
++ xhci->small_streams_pool =
++ dma_pool_create("xHCI 256 byte stream ctx arrays",
++ dev, SMALL_STREAM_ARRAY_SIZE, 16, 0);
++ xhci->medium_streams_pool =
++ dma_pool_create("xHCI 1KB stream ctx arrays",
++ dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0);
++ /* Any stream context array bigger than MEDIUM_STREAM_ARRAY_SIZE
++ * will be allocated with pci_alloc_consistent()
++ */
++
++ if (!xhci->small_streams_pool || !xhci->medium_streams_pool)
++ goto fail;
++
+ /* Set up the command ring to have one segments for now. */
+ xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, flags);
+ if (!xhci->cmd_ring)
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -306,6 +306,10 @@ static void ring_ep_doorbell(struct xhci
+ ep_state = ep->ep_state;
+ /* Don't ring the doorbell for this endpoint if there are pending
+ * cancellations because the we don't want to interrupt processing.
++ * We don't want to restart any stream rings if there's a set dequeue
++ * pointer command pending because the device can choose to start any
++ * stream once the endpoint is on the HW schedule.
++ * FIXME - check all the stream rings for pending cancellations.
+ */
+ if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
+ && !(ep_state & EP_HALTED)) {
+@@ -897,8 +901,9 @@ static void handle_cmd_completion(struct
+ * Configure endpoint commands can come from the USB core
+ * configuration or alt setting changes, or because the HW
+ * needed an extra configure endpoint command after a reset
+- * endpoint command. In the latter case, the xHCI driver is
+- * not waiting on the configure endpoint command.
++ * endpoint command or streams were being configured.
++ * If the command was for a halted endpoint, the xHCI driver
++ * is not waiting on the configure endpoint command.
+ */
+ ctrl_ctx = xhci_get_input_control_ctx(xhci,
+ virt_dev->in_ctx);
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -21,6 +21,7 @@
+ */
+
+ #include <linux/irq.h>
++#include <linux/log2.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/slab.h>
+@@ -726,8 +727,21 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ spin_lock_irqsave(&xhci->lock, flags);
+ if (xhci->xhc_state & XHCI_STATE_DYING)
+ goto dying;
+- ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
+- slot_id, ep_index);
++ if (xhci->devs[slot_id]->eps[ep_index].ep_state &
++ EP_GETTING_STREAMS) {
++ xhci_warn(xhci, "WARN: Can't enqueue URB while bulk ep "
++ "is transitioning to using streams.\n");
++ ret = -EINVAL;
++ } else if (xhci->devs[slot_id]->eps[ep_index].ep_state &
++ EP_GETTING_NO_STREAMS) {
++ xhci_warn(xhci, "WARN: Can't enqueue URB while bulk ep "
++ "is transitioning to "
++ "not having streams.\n");
++ ret = -EINVAL;
++ } else {
++ ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
++ slot_id, ep_index);
++ }
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
+ spin_lock_irqsave(&xhci->lock, flags);
+@@ -1444,6 +1458,387 @@ void xhci_endpoint_reset(struct usb_hcd
+ xhci_warn(xhci, "FIXME allocate a new ring segment\n");
+ }
+
++static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
++ struct usb_device *udev, struct usb_host_endpoint *ep,
++ unsigned int slot_id)
++{
++ int ret;
++ unsigned int ep_index;
++ unsigned int ep_state;
++
++ if (!ep)
++ return -EINVAL;
++ ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__);
++ if (ret <= 0)
++ return -EINVAL;
++ if (!ep->ss_ep_comp) {
++ xhci_warn(xhci, "WARN: No SuperSpeed Endpoint Companion"
++ " descriptor for ep 0x%x\n",
++ ep->desc.bEndpointAddress);
++ return -EINVAL;
++ }
++ if (ep->ss_ep_comp->desc.bmAttributes == 0) {
++ xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion"
++ " descriptor for ep 0x%x does not support streams\n",
++ ep->desc.bEndpointAddress);
++ return -EINVAL;
++ }
++
++ ep_index = xhci_get_endpoint_index(&ep->desc);
++ ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
++ if (ep_state & EP_HAS_STREAMS ||
++ ep_state & EP_GETTING_STREAMS) {
++ xhci_warn(xhci, "WARN: SuperSpeed bulk endpoint 0x%x "
++ "already has streams set up.\n",
++ ep->desc.bEndpointAddress);
++ xhci_warn(xhci, "Send email to xHCI maintainer and ask for "
++ "dynamic stream context array reallocation.\n");
++ return -EINVAL;
++ }
++ if (!list_empty(&xhci->devs[slot_id]->eps[ep_index].ring->td_list)) {
++ xhci_warn(xhci, "Cannot setup streams for SuperSpeed bulk "
++ "endpoint 0x%x; URBs are pending.\n",
++ ep->desc.bEndpointAddress);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void xhci_calculate_streams_entries(struct xhci_hcd *xhci,
++ unsigned int *num_streams, unsigned int *num_stream_ctxs)
++{
++ unsigned int max_streams;
++
++ /* The stream context array size must be a power of two */
++ *num_stream_ctxs = roundup_pow_of_two(*num_streams);
++ /*
++ * Find out how many primary stream array entries the host controller
++ * supports. Later we may use secondary stream arrays (similar to 2nd
++ * level page entries), but that's an optional feature for xHCI host
++ * controllers. xHCs must support at least 4 stream IDs.
++ */
++ max_streams = HCC_MAX_PSA(xhci->hcc_params);
++ if (*num_stream_ctxs > max_streams) {
++ xhci_dbg(xhci, "xHCI HW only supports %u stream ctx entries.\n",
++ max_streams);
++ *num_stream_ctxs = max_streams;
++ *num_streams = max_streams;
++ }
++}
++
++/* Returns an error code if one of the endpoint already has streams.
++ * This does not change any data structures, it only checks and gathers
++ * information.
++ */
++static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci,
++ struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int *num_streams, u32 *changed_ep_bitmask)
++{
++ struct usb_host_ss_ep_comp *ss_ep_comp;
++ unsigned int max_streams;
++ unsigned int endpoint_flag;
++ int i;
++ int ret;
++
++ for (i = 0; i < num_eps; i++) {
++ ret = xhci_check_streams_endpoint(xhci, udev,
++ eps[i], udev->slot_id);
++ if (ret < 0)
++ return ret;
++
++ ss_ep_comp = eps[i]->ss_ep_comp;
++ max_streams = USB_SS_MAX_STREAMS(ss_ep_comp->desc.bmAttributes);
++ if (max_streams < (*num_streams - 1)) {
++ xhci_dbg(xhci, "Ep 0x%x only supports %u stream IDs.\n",
++ eps[i]->desc.bEndpointAddress,
++ max_streams);
++ *num_streams = max_streams+1;
++ }
++
++ endpoint_flag = xhci_get_endpoint_flag(&eps[i]->desc);
++ if (*changed_ep_bitmask & endpoint_flag)
++ return -EINVAL;
++ *changed_ep_bitmask |= endpoint_flag;
++ }
++ return 0;
++}
++
++static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci,
++ struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps)
++{
++ u32 changed_ep_bitmask = 0;
++ unsigned int slot_id;
++ unsigned int ep_index;
++ unsigned int ep_state;
++ int i;
++
++ slot_id = udev->slot_id;
++ if (!xhci->devs[slot_id])
++ return 0;
++
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
++ /* Are streams already being freed for the endpoint? */
++ if (ep_state & EP_GETTING_NO_STREAMS) {
++ xhci_warn(xhci, "WARN Can't disable streams for "
++ "endpoint 0x%x\n, "
++ "streams are being disabled already.",
++ eps[i]->desc.bEndpointAddress);
++ return 0;
++ }
++ /* Are there actually any streams to free? */
++ if (!(ep_state & EP_HAS_STREAMS) &&
++ !(ep_state & EP_GETTING_STREAMS)) {
++ xhci_warn(xhci, "WARN Can't disable streams for "
++ "endpoint 0x%x\n, "
++ "streams are already disabled!",
++ eps[i]->desc.bEndpointAddress);
++ xhci_warn(xhci, "WARN xhci_free_streams() called "
++ "with non-streams endpoint\n");
++ return 0;
++ }
++ changed_ep_bitmask |= xhci_get_endpoint_flag(&eps[i]->desc);
++ }
++ return changed_ep_bitmask;
++}
++
++/*
++ * The USB device drivers use this function (though the HCD interface in USB
++ * core) to prepare a set of bulk endpoints to use streams. Streams are used to
++ * coordinate mass storage command queueing across multiple endpoints (basically
++ * a stream ID == a task ID).
++ *
++ * Setting up streams involves allocating the same size stream context array
++ * for each endpoint and issuing a configure endpoint command for all endpoints.
++ *
++ * Don't allow the call to succeed if one endpoint only supports one stream
++ * (which means it doesn't support streams at all).
++ *
++ * Drivers may get less stream IDs than they asked for, if the host controller
++ * hardware or endpoints claim they can't support the number of requested
++ * stream IDs.
++ */
++int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags)
++{
++ int i, ret;
++ struct xhci_hcd *xhci;
++ struct xhci_virt_device *vdev;
++ struct xhci_command *config_cmd;
++ unsigned int ep_index;
++ unsigned int num_stream_ctxs;
++ unsigned long flags;
++ u32 changed_ep_bitmask = 0;
++
++ if (!eps)
++ return -EINVAL;
++
++ /* Add one to the number of streams requested to account for
++ * stream 0 that is reserved for xHCI usage.
++ */
++ num_streams += 1;
++ xhci = hcd_to_xhci(hcd);
++ xhci_dbg(xhci, "Driver wants %u stream IDs (including stream 0).\n",
++ num_streams);
++
++ config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
++ if (!config_cmd) {
++ xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
++ return -ENOMEM;
++ }
++
++ /* Check to make sure all endpoints are not already configured for
++ * streams. While we're at it, find the maximum number of streams that
++ * all the endpoints will support and check for duplicate endpoints.
++ */
++ spin_lock_irqsave(&xhci->lock, flags);
++ ret = xhci_calculate_streams_and_bitmask(xhci, udev, eps,
++ num_eps, &num_streams, &changed_ep_bitmask);
++ if (ret < 0) {
++ xhci_free_command(xhci, config_cmd);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ return ret;
++ }
++ if (num_streams <= 1) {
++ xhci_warn(xhci, "WARN: endpoints can't handle "
++ "more than one stream.\n");
++ xhci_free_command(xhci, config_cmd);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ return -EINVAL;
++ }
++ vdev = xhci->devs[udev->slot_id];
++ /* Mark each endpoint as being in transistion, so
++ * xhci_urb_enqueue() will reject all URBs.
++ */
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ vdev->eps[ep_index].ep_state |= EP_GETTING_STREAMS;
++ }
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ /* Setup internal data structures and allocate HW data structures for
++ * streams (but don't install the HW structures in the input context
++ * until we're sure all memory allocation succeeded).
++ */
++ xhci_calculate_streams_entries(xhci, &num_streams, &num_stream_ctxs);
++ xhci_dbg(xhci, "Need %u stream ctx entries for %u stream IDs.\n",
++ num_stream_ctxs, num_streams);
++
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci,
++ num_stream_ctxs,
++ num_streams, mem_flags);
++ if (!vdev->eps[ep_index].stream_info)
++ goto cleanup;
++ /* Set maxPstreams in endpoint context and update deq ptr to
++ * point to stream context array. FIXME
++ */
++ }
++
++ /* Set up the input context for a configure endpoint command. */
++ for (i = 0; i < num_eps; i++) {
++ struct xhci_ep_ctx *ep_ctx;
++
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ ep_ctx = xhci_get_ep_ctx(xhci, config_cmd->in_ctx, ep_index);
++
++ xhci_endpoint_copy(xhci, config_cmd->in_ctx,
++ vdev->out_ctx, ep_index);
++ xhci_setup_streams_ep_input_ctx(xhci, ep_ctx,
++ vdev->eps[ep_index].stream_info);
++ }
++ /* Tell the HW to drop its old copy of the endpoint context info
++ * and add the updated copy from the input context.
++ */
++ xhci_setup_input_ctx_for_config_ep(xhci, config_cmd->in_ctx,
++ vdev->out_ctx, changed_ep_bitmask, changed_ep_bitmask);
++
++ /* Issue and wait for the configure endpoint command */
++ ret = xhci_configure_endpoint(xhci, udev, config_cmd,
++ false, false);
++
++ /* xHC rejected the configure endpoint command for some reason, so we
++ * leave the old ring intact and free our internal streams data
++ * structure.
++ */
++ if (ret < 0)
++ goto cleanup;
++
++ spin_lock_irqsave(&xhci->lock, flags);
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ vdev->eps[ep_index].ep_state &= ~EP_GETTING_STREAMS;
++ xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n",
++ udev->slot_id, ep_index);
++ vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS;
++ }
++ xhci_free_command(xhci, config_cmd);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ /* Subtract 1 for stream 0, which drivers can't use */
++ return num_streams - 1;
++
++cleanup:
++ /* If it didn't work, free the streams! */
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ xhci_free_stream_info(xhci, vdev->eps[ep_index].stream_info);
++ /* FIXME Unset maxPstreams in endpoint context and
++ * update deq ptr to point to normal string ring.
++ */
++ vdev->eps[ep_index].ep_state &= ~EP_GETTING_STREAMS;
++ vdev->eps[ep_index].ep_state &= ~EP_HAS_STREAMS;
++ xhci_endpoint_zero(xhci, vdev, eps[i]);
++ }
++ xhci_free_command(xhci, config_cmd);
++ return -ENOMEM;
++}
++
++/* Transition the endpoint from using streams to being a "normal" endpoint
++ * without streams.
++ *
++ * Modify the endpoint context state, submit a configure endpoint command,
++ * and free all endpoint rings for streams if that completes successfully.
++ */
++int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags)
++{
++ int i, ret;
++ struct xhci_hcd *xhci;
++ struct xhci_virt_device *vdev;
++ struct xhci_command *command;
++ unsigned int ep_index;
++ unsigned long flags;
++ u32 changed_ep_bitmask;
++
++ xhci = hcd_to_xhci(hcd);
++ vdev = xhci->devs[udev->slot_id];
++
++ /* Set up a configure endpoint command to remove the streams rings */
++ spin_lock_irqsave(&xhci->lock, flags);
++ changed_ep_bitmask = xhci_calculate_no_streams_bitmask(xhci,
++ udev, eps, num_eps);
++ if (changed_ep_bitmask == 0) {
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ return -EINVAL;
++ }
++
++ /* Use the xhci_command structure from the first endpoint. We may have
++ * allocated too many, but the driver may call xhci_free_streams() for
++ * each endpoint it grouped into one call to xhci_alloc_streams().
++ */
++ ep_index = xhci_get_endpoint_index(&eps[0]->desc);
++ command = vdev->eps[ep_index].stream_info->free_streams_command;
++ for (i = 0; i < num_eps; i++) {
++ struct xhci_ep_ctx *ep_ctx;
++
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index);
++ xhci->devs[udev->slot_id]->eps[ep_index].ep_state |=
++ EP_GETTING_NO_STREAMS;
++
++ xhci_endpoint_copy(xhci, command->in_ctx,
++ vdev->out_ctx, ep_index);
++ xhci_setup_no_streams_ep_input_ctx(xhci, ep_ctx,
++ &vdev->eps[ep_index]);
++ }
++ xhci_setup_input_ctx_for_config_ep(xhci, command->in_ctx,
++ vdev->out_ctx, changed_ep_bitmask, changed_ep_bitmask);
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ /* Issue and wait for the configure endpoint command,
++ * which must succeed.
++ */
++ ret = xhci_configure_endpoint(xhci, udev, command,
++ false, true);
++
++ /* xHC rejected the configure endpoint command for some reason, so we
++ * leave the streams rings intact.
++ */
++ if (ret < 0)
++ return ret;
++
++ spin_lock_irqsave(&xhci->lock, flags);
++ for (i = 0; i < num_eps; i++) {
++ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
++ xhci_free_stream_info(xhci, vdev->eps[ep_index].stream_info);
++ /* FIXME Unset maxPstreams in endpoint context and
++ * update deq ptr to point to normal string ring.
++ */
++ vdev->eps[ep_index].ep_state &= ~EP_GETTING_NO_STREAMS;
++ vdev->eps[ep_index].ep_state &= ~EP_HAS_STREAMS;
++ }
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ return 0;
++}
++
+ /*
+ * This submits a Reset Device Command, which will set the device state to 0,
+ * set the device address to 0, and disable all the endpoints except the default
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -117,7 +117,7 @@ struct xhci_cap_regs {
+ /* true: no secondary Stream ID Support */
+ #define HCC_NSS(p) ((p) & (1 << 7))
+ /* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
+-#define HCC_MAX_PSA (1 << ((((p) >> 12) & 0xf) + 1))
++#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1))
+ /* Extended Capabilities pointer from PCI base - section 5.3.6 */
+ #define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p)
+
+@@ -585,6 +585,10 @@ struct xhci_ep_ctx {
+ /* Interval - period between requests to an endpoint - 125u increments. */
+ #define EP_INTERVAL(p) ((p & 0xff) << 16)
+ #define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff))
++#define EP_MAXPSTREAMS_MASK (0x1f << 10)
++#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK)
++/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */
++#define EP_HAS_LSA (1 << 15)
+
+ /* ep_info2 bitmasks */
+ /*
+@@ -648,8 +652,50 @@ struct xhci_command {
+ /* add context bitmasks */
+ #define ADD_EP(x) (0x1 << x)
+
++struct xhci_stream_ctx {
++ /* 64-bit stream ring address, cycle state, and stream type */
++ u64 stream_ring;
++ /* offset 0x14 - 0x1f reserved for HC internal use */
++ u32 reserved[2];
++};
++
++/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
++#define SCT_FOR_CTX(p) (((p) << 1) & 0x7)
++/* Secondary stream array type, dequeue pointer is to a transfer ring */
++#define SCT_SEC_TR 0
++/* Primary stream array type, dequeue pointer is to a transfer ring */
++#define SCT_PRI_TR 1
++/* Dequeue pointer is for a secondary stream array (SSA) with 8 entries */
++#define SCT_SSA_8 2
++#define SCT_SSA_16 3
++#define SCT_SSA_32 4
++#define SCT_SSA_64 5
++#define SCT_SSA_128 6
++#define SCT_SSA_256 7
++
++/* Assume no secondary streams for now */
++struct xhci_stream_info {
++ struct xhci_ring **stream_rings;
++ /* Number of streams, including stream 0 (which drivers can't use) */
++ unsigned int num_streams;
++ /* The stream context array may be bigger than
++ * the number of streams the driver asked for
++ */
++ struct xhci_stream_ctx *stream_ctx_array;
++ unsigned int num_stream_ctxs;
++ dma_addr_t ctx_array_dma;
++ /* For mapping physical TRB addresses to segments in stream rings */
++ struct radix_tree_root trb_address_map;
++ struct xhci_command *free_streams_command;
++};
++
++#define SMALL_STREAM_ARRAY_SIZE 256
++#define MEDIUM_STREAM_ARRAY_SIZE 1024
++
+ struct xhci_virt_ep {
+ struct xhci_ring *ring;
++ /* Related to endpoints that are configured to use stream IDs only */
++ struct xhci_stream_info *stream_info;
+ /* Temporary storage in case the configure endpoint command fails and we
+ * have to restore the device state to the previous state
+ */
+@@ -658,6 +704,11 @@ struct xhci_virt_ep {
+ #define SET_DEQ_PENDING (1 << 0)
+ #define EP_HALTED (1 << 1) /* For stall handling */
+ #define EP_HALT_PENDING (1 << 2) /* For URB cancellation */
++/* Transitioning the endpoint to using streams, don't enqueue URBs */
++#define EP_GETTING_STREAMS (1 << 3)
++#define EP_HAS_STREAMS (1 << 4)
++/* Transitioning the endpoint to not using streams, don't enqueue URBs */
++#define EP_GETTING_NO_STREAMS (1 << 5)
+ /* ---- Related to URB cancellation ---- */
+ struct list_head cancelled_td_list;
+ /* The TRB that was last reported in a stopped endpoint ring */
+@@ -710,14 +761,6 @@ struct xhci_device_context_array {
+ */
+
+
+-struct xhci_stream_ctx {
+- /* 64-bit stream ring address, cycle state, and stream type */
+- u64 stream_ring;
+- /* offset 0x14 - 0x1f reserved for HC internal use */
+- u32 reserved[2];
+-};
+-
+-
+ struct xhci_transfer_event {
+ /* 64-bit buffer address, or immediate data */
+ u64 buffer;
+@@ -952,6 +995,10 @@ union xhci_trb {
+ /* Allow two commands + a link TRB, along with any reserved command TRBs */
+ #define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3)
+ #define SEGMENT_SIZE (TRBS_PER_SEGMENT*16)
++/* SEGMENT_SHIFT should be log2(SEGMENT_SIZE).
++ * Change this if you change TRBS_PER_SEGMENT!
++ */
++#define SEGMENT_SHIFT 10
+ /* TRB buffer pointers can't cross 64KB boundaries */
+ #define TRB_MAX_BUFF_SHIFT 16
+ #define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT)
+@@ -1088,6 +1135,8 @@ struct xhci_hcd {
+ /* DMA pools */
+ struct dma_pool *device_pool;
+ struct dma_pool *segment_pool;
++ struct dma_pool *small_streams_pool;
++ struct dma_pool *medium_streams_pool;
+
+ #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+ /* Poll the rings - for debugging */
+@@ -1242,6 +1291,17 @@ void xhci_ring_free(struct xhci_hcd *xhc
+ void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+ struct xhci_virt_device *virt_dev,
+ unsigned int ep_index);
++struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
++ unsigned int num_stream_ctxs,
++ unsigned int num_streams, gfp_t flags);
++void xhci_free_stream_info(struct xhci_hcd *xhci,
++ struct xhci_stream_info *stream_info);
++void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci,
++ struct xhci_ep_ctx *ep_ctx,
++ struct xhci_stream_info *stream_info);
++void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
++ struct xhci_ep_ctx *ep_ctx,
++ struct xhci_virt_ep *ep);
+ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
+ bool allocate_in_ctx, bool allocate_completion,
+ gfp_t mem_flags);
+@@ -1266,6 +1326,12 @@ int xhci_get_frame(struct usb_hcd *hcd);
+ irqreturn_t xhci_irq(struct usb_hcd *hcd);
+ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
+ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
++int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ unsigned int num_streams, gfp_t mem_flags);
++int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint **eps, unsigned int num_eps,
++ gfp_t mem_flags);
+ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
+ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+ struct usb_tt *tt, gfp_t mem_flags);