Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (148 commits)
  USB: serial: fix stalled writes
  USB: remove fake "address-of" expressions
  USB: fix thread-unsafe anchor utiliy routines
  USB: usbtest: support test device with only one iso-in or iso-out endpoint
  USB: usbtest: avoid to free coherent buffer in atomic context
  USB: xhci: Set DMA mask for host.
  USB: xhci: Don't flush doorbell writes.
  USB: xhci: Reduce reads and writes of interrupter registers.
  USB: xhci: Make xhci_set_hc_event_deq() static.
  USB: xhci: Minimize HW event ring dequeue pointer writes.
  USB: xhci: Make xhci_handle_event() static.
  USB: xhci: Remove unnecessary reads of IRQ_PENDING register.
  USB: xhci: Performance - move xhci_work() into xhci_irq()
  USB: xhci: Performance - move interrupt handlers into xhci-ring.c
  USB: xhci: Performance - move functions that find ep ring.
  USB:: fix linux/usb.h kernel-doc warnings
  USB: add USB serial ssu100 driver
  USB: usb-storage: implement autosuspend
  USB: ehci: fix remove of ehci debugfs dir
  USB: Add USB 2.0 to ssb ohci driver
  ...
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
index 3403402..d548eaa 100644
--- a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
+++ b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
@@ -7,3 +7,15 @@
 		0 -> resumed
 
 		(_UDC_ is the name of the USB Device Controller driver)
+
+What:           /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua
+Date:           July 2010
+Contact:        Andy Shevchenko <andy.shevchenko@gmail.com>
+Description:
+		Show or set the reaction on the FUA (Force Unit Access) bit in
+		the SCSI WRITE(10,12) commands when a gadget in USB Mass
+		Storage mode.
+
+		Possible values are:
+			1 -> ignore the FUA flag
+			0 -> obey the FUA flag
diff --git a/Documentation/usb/ehci.txt b/Documentation/usb/ehci.txt
index 1536b7e..9dcafa7 100644
--- a/Documentation/usb/ehci.txt
+++ b/Documentation/usb/ehci.txt
@@ -9,7 +9,7 @@
     - "Low Speed" 1.5 Mbit/sec
 
 USB 1.1 only addressed full speed and low speed.  High speed devices
-can be used on USB 1.1 systems, but they slow down to USB 1.1 speeds. 
+can be used on USB 1.1 systems, but they slow down to USB 1.1 speeds.
 
 USB 1.1 devices may also be used on USB 2.0 systems.  When plugged
 into an EHCI controller, they are given to a USB 1.1 "companion"
diff --git a/Documentation/usb/gadget_multi.txt b/Documentation/usb/gadget_multi.txt
new file mode 100644
index 0000000..80f4ef0
--- /dev/null
+++ b/Documentation/usb/gadget_multi.txt
@@ -0,0 +1,150 @@
+                                                             -*- org -*-
+
+* Overview
+
+The Multifunction Composite Gadget (or g_multi) is a composite gadget
+that makes extensive use of the composite framework to provide
+a... multifunction gadget.
+
+In it's standard configuration it provides a single USB configuration
+with RNDIS[1] (that is Ethernet), USB CDC[2] ACM (that is serial) and
+USB Mass Storage functions.
+
+A CDC ECM (Ethernet) function may be turned on via a Kconfig option
+and RNDIS can be turned off.  If they are both enabled the gadget will
+have two configurations -- one with RNDIS and another with CDC ECM[3].
+
+Please not that if you use non-standard configuration (that is enable
+CDC ECM) you may need to change vendor and/or product ID.
+
+* Host drivers
+
+To make use of the gadget one needs to make it work on host side --
+without that there's no hope of achieving anything with the gadget.
+As one might expect, things one need to do very from system to system.
+
+** Linux host drivers
+
+Since the gadget uses standard composite framework and appears as such
+to Linux host it does not need any additional drivers on Linux host
+side.  All the functions are handled by respective drivers developed
+for them.
+
+This is also true for two configuration set-up with RNDIS
+configuration being the first one.  Linux host will use the second
+configuration with CDC ECM which should work better under Linux.
+
+** Windows host drivers
+
+For the gadget two work under Windows two conditions have to be met:
+
+*** Detecting as composite gadget
+
+First of all, Windows need to detect the gadget as an USB composite
+gadget which on its own have some conditions[4].  If they are met,
+Windows lets USB Generic Parent Driver[5] handle the device which then
+tries to much drivers for each individual interface (sort of, don't
+get into too many details).
+
+The good news is: you do not have to worry about most of the
+conditions!
+
+The only thing to worry is that the gadget has to have a single
+configuration so a dual RNDIS and CDC ECM gadget won't work unless you
+create a proper INF -- and of course, if you do submit it!
+
+*** Installing drivers for each function
+
+The other, trickier thing is making Windows install drivers for each
+individual function.
+
+For mass storage it is trivial since Windows detect it's an interface
+implementing USB Mass Storage class and selects appropriate driver.
+
+Things are harder with RDNIS and CDC ACM.
+
+**** RNDIS
+
+To make Windows select RNDIS drivers for the first function in the
+gadget, one needs to use the [[file:linux.inf]] file provided with this
+document.  It "attaches" Window's RNDIS driver to the first interface
+of the gadget.
+
+Please note, that while testing we encountered some issues[6] when
+RNDIS was not the first interface.  You do not need to worry abut it
+unless you are trying to develop your own gadget in which case watch
+out for this bug.
+
+**** CDC ACM
+
+Similarly, [[file:linux-cdc-acm.inf]] is provided for CDC ACM.
+
+**** Customising the gadget
+
+If you intend to hack the g_multi gadget be advised that rearranging
+functions will obviously change interface numbers for each of the
+functionality.  As an effect provided INFs won't work since they have
+interface numbers hard-coded in them (it's not hard to change those
+though[7]).
+
+This also means, that after experimenting with g_multi and changing
+provided functions one should change gadget's vendor and/or product ID
+so there will be no collision with other customised gadgets or the
+original gadget.
+
+Failing to comply may cause brain damage after wondering for hours why
+things don't work as intended before realising Windows have cached
+some drivers information (changing USB port may sometimes help plus
+you might try using USBDeview[8] to remove the phantom device).
+
+**** INF testing
+
+Provided INF files have been tested on Windows XP SP3, Windows Vista
+and Windows 7, all 32-bit versions.  It should work on 64-bit versions
+as well.  It most likely won't work on Windows prior to Windows XP
+SP2.
+
+** Other systems
+
+At this moment, drivers for any other systems have not been tested.
+Knowing how MacOS is based on BSD and BSD is an Open Source it is
+believed that it should (read: "I have no idea whether it will") work
+out-of-the-box.
+
+For more exotic systems I have even less to say...
+
+Any testing and drivers *are* *welcome*!
+
+* Authors
+
+This document has been written by Michal Nazarewicz
+([[mailto:mina86@mina86.com]]).  INF files have been hacked with
+support of Marek Szyprowski ([[mailto:m.szyprowski@samsung.com]]) and
+Xiaofan Chen ([[mailto:xiaofanc@gmail.com]]) basing on the MS RNDIS
+template[9], Microchip's CDC ACM INF file and David Brownell's
+([[mailto:dbrownell@users.sourceforge.net]]) original INF files.
+
+* Footnotes
+
+[1] Remote Network Driver Interface Specification,
+[[http://msdn.microsoft.com/en-us/library/ee484414.aspx]].
+
+[2] Communications Device Class Abstract Control Model, spec for this
+and other USB classes can be found at
+[[http://www.usb.org/developers/devclass_docs/]].
+
+[3] CDC Ethernet Control Model.
+
+[4] [[http://msdn.microsoft.com/en-us/library/ff537109(v=VS.85).aspx]]
+
+[5] [[http://msdn.microsoft.com/en-us/library/ff539234(v=VS.85).aspx]]
+
+[6] To put it in some other nice words, Windows failed to respond to
+any user input.
+
+[7] You may find [[http://www.cygnal.org/ubb/Forum9/HTML/001050.html]]
+useful.
+
+[8] http://www.nirsoft.net/utils/usb_devices_view.html
+
+[9] [[http://msdn.microsoft.com/en-us/library/ff570620.aspx]]
diff --git a/Documentation/usb/gadget_serial.txt b/Documentation/usb/gadget_serial.txt
index eac7df9..61e67f6 100644
--- a/Documentation/usb/gadget_serial.txt
+++ b/Documentation/usb/gadget_serial.txt
@@ -151,88 +151,23 @@
 
 Installing the Windows Host ACM Driver
 --------------------------------------
-To use the Windows ACM driver you must have the files "gserial.inf"
-and "usbser.sys" together in a folder on the Windows machine.
-
-The "gserial.inf" file is given here.
-
--------------------- CUT HERE --------------------
-[Version]
-Signature="$Windows NT$"
-Class=Ports
-ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
-Provider=%LINUX%
-DriverVer=08/17/2004,0.0.2.0
-; Copyright (C) 2004 Al Borchers (alborchers@steinerpoint.com)
-
-[Manufacturer]
-%LINUX%=GSerialDeviceList
-
-[GSerialDeviceList]
-%GSERIAL%=GSerialInstall, USB\VID_0525&PID_A4A7
-
-[DestinationDirs]
-DefaultDestDir=10,System32\Drivers
-
-[GSerialInstall]
-CopyFiles=GSerialCopyFiles
-AddReg=GSerialAddReg
-
-[GSerialCopyFiles]
-usbser.sys
-
-[GSerialAddReg]
-HKR,,DevLoader,,*ntkern
-HKR,,NTMPDriver,,usbser.sys
-HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
-
-[GSerialInstall.Services]
-AddService = usbser,0x0002,GSerialService
-
-[GSerialService]
-DisplayName = %GSERIAL_DISPLAY_NAME%
-ServiceType = 1                  ; SERVICE_KERNEL_DRIVER
-StartType = 3                    ; SERVICE_DEMAND_START
-ErrorControl = 1                 ; SERVICE_ERROR_NORMAL
-ServiceBinary = %10%\System32\Drivers\usbser.sys
-LoadOrderGroup = Base
-
-[Strings]
-LINUX = "Linux"
-GSERIAL = "Gadget Serial"
-GSERIAL_DISPLAY_NAME = "USB Gadget Serial Driver"
--------------------- CUT HERE --------------------
-
-The "usbser.sys" file comes with various versions of Windows.
-For example, it can be found on Windows XP typically in
-
-  C:\WINDOWS\Driver Cache\i386\driver.cab
-
-Or it can be found on the Windows 98SE CD in the "win98" folder
-in the "DRIVER11.CAB" through "DRIVER20.CAB" cab files.  You will
-need the DOS "expand" program, the Cygwin "cabextract" program, or
-a similar program to unpack these cab files and extract "usbser.sys".
-
-For example, to extract "usbser.sys" into the current directory
-on Windows XP, open a DOS window and run a command like
-
-  expand C:\WINDOWS\Driver~1\i386\driver.cab -F:usbser.sys .
-
-(Thanks to Nishant Kamat for pointing out this DOS command.)
+To use the Windows ACM driver you must have the "linux-cdc-acm.inf"
+file (provided along this document) which supports all recent versions
+of Windows.
 
 When the gadget serial driver is loaded and the USB device connected
 to the Windows host with a USB cable, Windows should recognize the
 gadget serial device and ask for a driver.  Tell Windows to find the
-driver in the folder that contains "gserial.inf" and "usbser.sys".
+driver in the folder that contains the "linux-cdc-acm.inf" file.
 
 For example, on Windows XP, when the gadget serial device is first
 plugged in, the "Found New Hardware Wizard" starts up.  Select
-"Install from a list or specific location (Advanced)", then on
-the next screen select "Include this location in the search" and
-enter the path or browse to the folder containing "gserial.inf" and
-"usbser.sys".  Windows will complain that the Gadget Serial driver
-has not passed Windows Logo testing, but select "Continue anyway"
-and finish the driver installation.
+"Install from a list or specific location (Advanced)", then on the
+next screen select "Include this location in the search" and enter the
+path or browse to the folder containing the "linux-cdc-acm.inf" file.
+Windows will complain that the Gadget Serial driver has not passed
+Windows Logo testing, but select "Continue anyway" and finish the
+driver installation.
 
 On Windows XP, in the "Device Manager" (under "Control Panel",
 "System", "Hardware") expand the "Ports (COM & LPT)" entry and you
@@ -345,5 +280,3 @@
 side and host side systems.  Anything you type on the terminal
 window on the gadget side should appear in the terminal window on
 the host side and vice versa.
-
-
diff --git a/Documentation/usb/hotplug.txt b/Documentation/usb/hotplug.txt
index f531706..4c94571 100644
--- a/Documentation/usb/hotplug.txt
+++ b/Documentation/usb/hotplug.txt
@@ -10,7 +10,7 @@
 
     - Bind a driver to that device.  Bus frameworks do that using a
       device driver's probe() routine.
-    
+
     - Tell other subsystems to configure the new device.  Print
       queues may need to be enabled, networks brought up, disk
       partitions mounted, and so on.  In some cases these will
@@ -84,7 +84,7 @@
 Current versions of module-init-tools will create a "modules.usbmap" file
 which contains the entries from each driver's MODULE_DEVICE_TABLE.  Such
 files can be used by various user mode policy agents to make sure all the
-right driver modules get loaded, either at boot time or later. 
+right driver modules get loaded, either at boot time or later.
 
 See <linux/usb.h> for full information about such table entries; or look
 at existing drivers.  Each table entry describes one or more criteria to
diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf
new file mode 100644
index 0000000..612e722
--- /dev/null
+++ b/Documentation/usb/linux-cdc-acm.inf
@@ -0,0 +1,107 @@
+; Windows USB CDC ACM Setup File
+
+; Based on INF template which was:
+;     Copyright (c) 2000 Microsoft Corporation
+;     Copyright (c) 2007 Microchip Technology Inc.
+; likely to be covered by the MLPL as found at:
+;    <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.
+; For use only on Windows operating systems.
+
+[Version]
+Signature="$Windows NT$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=%Linux%
+DriverVer=11/15/2007,5.1.2600.0
+
+[Manufacturer]
+%Linux%=DeviceList, NTamd64
+
+[DestinationDirs]
+DefaultDestDir=12
+
+
+;------------------------------------------------------------------------------
+;  Windows 2000/XP/Vista-32bit Sections
+;------------------------------------------------------------------------------
+
+[DriverInstall.nt]
+include=mdmcpq.inf
+CopyFiles=DriverCopyFiles.nt
+AddReg=DriverInstall.nt.AddReg
+
+[DriverCopyFiles.nt]
+usbser.sys,,,0x20
+
+[DriverInstall.nt.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,USBSER.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[DriverInstall.nt.Services]
+AddService=usbser, 0x00000002, DriverService.nt
+
+[DriverService.nt]
+DisplayName=%SERVICE%
+ServiceType=1
+StartType=3
+ErrorControl=1
+ServiceBinary=%12%\USBSER.sys
+
+;------------------------------------------------------------------------------
+;  Vista-64bit Sections
+;------------------------------------------------------------------------------
+
+[DriverInstall.NTamd64]
+include=mdmcpq.inf
+CopyFiles=DriverCopyFiles.NTamd64
+AddReg=DriverInstall.NTamd64.AddReg
+
+[DriverCopyFiles.NTamd64]
+USBSER.sys,,,0x20
+
+[DriverInstall.NTamd64.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,USBSER.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[DriverInstall.NTamd64.Services]
+AddService=usbser, 0x00000002, DriverService.NTamd64
+
+[DriverService.NTamd64]
+DisplayName=%SERVICE%
+ServiceType=1
+StartType=3
+ErrorControl=1
+ServiceBinary=%12%\USBSER.sys
+
+
+;------------------------------------------------------------------------------
+;  Vendor and Product ID Definitions
+;------------------------------------------------------------------------------
+; When developing your USB device, the VID and PID used in the PC side
+; application program and the firmware on the microcontroller must match.
+; Modify the below line to use your VID and PID.  Use the format as shown
+; below.
+; Note: One INF file can be used for multiple devices with different
+;       VID and PIDs.  For each supported device, append
+;       ",USB\VID_xxxx&PID_yyyy" to the end of the line.
+;------------------------------------------------------------------------------
+[SourceDisksFiles]
+[SourceDisksNames]
+[DeviceList]
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
+
+[DeviceList.NTamd64]
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
+
+
+;------------------------------------------------------------------------------
+;  String Definitions
+;------------------------------------------------------------------------------
+;Modify these strings to customize your device
+;------------------------------------------------------------------------------
+[Strings]
+Linux               = "Linux Developer Community"
+DESCRIPTION         = "Gadget Serial"
+SERVICE             = "USB RS-232 Emulation Driver"
diff --git a/Documentation/usb/linux.inf b/Documentation/usb/linux.inf
index af71d87..4dee958 100644
--- a/Documentation/usb/linux.inf
+++ b/Documentation/usb/linux.inf
@@ -1,200 +1,66 @@
-; MS-Windows driver config matching some basic modes of the
-; Linux-USB Ethernet/RNDIS gadget firmware:
-;
-;  - RNDIS plus CDC Ethernet ... this may be familiar as a DOCSIS
-;    cable modem profile, and supports most non-Microsoft USB hosts
-;
-;  - RNDIS plus CDC Subset ... used by hardware that incapable of
-;    full CDC Ethernet support.
-;
-; Microsoft only directly supports RNDIS drivers, and bundled them into XP.
-; The Microsoft "Remote NDIS USB Driver Kit" is currently found at:
-;   http://www.microsoft.com/whdc/device/network/ndis/rmndis.mspx
-
+; Based on template INF file found at
+;    <http://msdn.microsoft.com/en-us/library/ff570620.aspx>
+; which was:
+;    Copyright (c) Microsoft Corporation
+; and released under the MLPL as found at:
+;    <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.
+; For use only on Windows operating systems.
 
 [Version]
-Signature           = "$CHICAGO$"
+Signature           = "$Windows NT$"
 Class               = Net
 ClassGUID           = {4d36e972-e325-11ce-bfc1-08002be10318}
 Provider            = %Linux%
-Compatible          = 1
-MillenniumPreferred = .ME
-DriverVer           = 03/30/2004,0.0.0.0
-; catalog file would be used by WHQL
-;CatalogFile         = Linux.cat
+DriverVer           = 06/21/2006,6.0.6000.16384
 
 [Manufacturer]
-%Linux%          = LinuxDevices,NT.5.1
+%Linux%             = LinuxDevices,NTx86,NTamd64,NTia64
 
-[LinuxDevices]
-; NetChip IDs, used by both firmware modes
-%LinuxDevice%    = RNDIS, USB\VID_0525&PID_a4a2
+; Decoration for x86 architecture
+[LinuxDevices.NTx86]
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
 
-[LinuxDevices.NT.5.1]
-%LinuxDevice%    = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2
+; Decoration for x64 architecture
+[LinuxDevices.NTamd64]
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
 
+; Decoration for ia64 architecture
+[LinuxDevices.NTia64]
+%LinuxDevice%       = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
+
+;@@@ This is the common setting for setup
 [ControlFlags]
 ExcludeFromSelect=*
 
-; Windows 98, Windows 98 Second Edition specific sections --------
-
-[RNDIS]
-DeviceID        = usb8023
-MaxInstance     = 512
-DriverVer           = 03/30/2004,0.0.0.0
-AddReg          = RNDIS_AddReg_98, RNDIS_AddReg_Common
-
-[RNDIS_AddReg_98]
-HKR, ,               DevLoader,        0, *ndis
-HKR, ,               DeviceVxDs,       0, usb8023.sys
-HKR, NDIS,           LogDriverName,    0, "usb8023"
-HKR, NDIS,           MajorNdisVersion, 1, 5
-HKR, NDIS,           MinorNdisVersion, 1, 0
-HKR, Ndi\Interfaces, DefUpper,         0, "ndis3,ndis4,ndis5"
-HKR, Ndi\Interfaces, DefLower,         0, "ethernet"
-HKR, Ndi\Interfaces, UpperRange,       0, "ndis3,ndis4,ndis5"
-HKR, Ndi\Interfaces, LowerRange,       0, "ethernet"
-HKR, Ndi\Install,    ndis3,            0, "RNDIS_Install_98"
-HKR, Ndi\Install,    ndis4,            0, "RNDIS_Install_98"
-HKR, Ndi\Install,    ndis5,            0, "RNDIS_Install_98"
-HKR, Ndi,            DeviceId,         0, "USB\VID_0525&PID_a4a2"
-
-[RNDIS_Install_98]
-CopyFiles=RNDIS_CopyFiles_98
-
-[RNDIS_CopyFiles_98]
-usb8023.sys, usb8023w.sys, , 0 
-rndismp.sys, rndismpw.sys, , 0 
-
-; Windows Millennium Edition specific sections --------------------
-
-[RNDIS.ME]
-DeviceID        = usb8023
-MaxInstance     = 512
-DriverVer           = 03/30/2004,0.0.0.0
-AddReg          = RNDIS_AddReg_ME, RNDIS_AddReg_Common
-Characteristics = 0x84   ; NCF_PHYSICAL + NCF_HAS_UI
-BusType         = 15
-
-[RNDIS_AddReg_ME]
-HKR, ,               DevLoader,        0, *ndis
-HKR, ,               DeviceVxDs,       0, usb8023.sys
-HKR, NDIS,           LogDriverName,    0, "usb8023"
-HKR, NDIS,           MajorNdisVersion, 1, 5
-HKR, NDIS,           MinorNdisVersion, 1, 0
-HKR, Ndi\Interfaces, DefUpper,         0, "ndis3,ndis4,ndis5"
-HKR, Ndi\Interfaces, DefLower,         0, "ethernet"
-HKR, Ndi\Interfaces, UpperRange,       0, "ndis3,ndis4,ndis5"
-HKR, Ndi\Interfaces, LowerRange,       0, "ethernet"
-HKR, Ndi\Install,    ndis3,            0, "RNDIS_Install_ME"
-HKR, Ndi\Install,    ndis4,            0, "RNDIS_Install_ME"
-HKR, Ndi\Install,    ndis5,            0, "RNDIS_Install_ME"
-HKR, Ndi,            DeviceId,         0, "USB\VID_0525&PID_a4a2"
-
-[RNDIS_Install_ME]
-CopyFiles=RNDIS_CopyFiles_ME
-
-[RNDIS_CopyFiles_ME]
-usb8023.sys, usb8023m.sys, , 0 
-rndismp.sys, rndismpm.sys, , 0 
-
-; Windows 2000 specific sections ---------------------------------
-
-[RNDIS.NT]
-Characteristics = 0x84   ; NCF_PHYSICAL + NCF_HAS_UI
-BusType         = 15
-DriverVer           = 03/30/2004,0.0.0.0
-AddReg          = RNDIS_AddReg_NT, RNDIS_AddReg_Common
-CopyFiles       = RNDIS_CopyFiles_NT
-
-[RNDIS.NT.Services]
-AddService = USB_RNDIS, 2, RNDIS_ServiceInst_NT, RNDIS_EventLog
-
-[RNDIS_CopyFiles_NT]
-; no rename of files on Windows 2000, use the 'k' names as is
-usb8023k.sys, , , 0 
-rndismpk.sys, , , 0 
-
-[RNDIS_ServiceInst_NT]
-DisplayName     = %ServiceDisplayName%
-ServiceType     = 1 
-StartType       = 3 
-ErrorControl    = 1 
-ServiceBinary   = %12%\usb8023k.sys    
-LoadOrderGroup  = NDIS
-AddReg          = RNDIS_WMI_AddReg_NT
-
-[RNDIS_WMI_AddReg_NT]
-HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismpk.sys"
-
-; Windows XP specific sections -----------------------------------
-
+; DDInstall section
+; References the in-build Netrndis.inf
 [RNDIS.NT.5.1]
-Characteristics = 0x84   ; NCF_PHYSICAL + NCF_HAS_UI
-BusType         = 15
-DriverVer           = 03/30/2004,0.0.0.0
-AddReg          = RNDIS_AddReg_NT, RNDIS_AddReg_Common
-; no copyfiles - the files are already in place
+Characteristics     = 0x84   ; NCF_PHYSICAL + NCF_HAS_UI
+BusType             = 15
+; NEVER REMOVE THE FOLLOWING REFERENCE FOR NETRNDIS.INF
+include             = netrndis.inf
+needs               = Usb_Rndis.ndi
+AddReg              = Rndis_AddReg_Vista
 
+; DDInstal.Services section
 [RNDIS.NT.5.1.Services]
-AddService      = USB_RNDIS, 2, RNDIS_ServiceInst_51, RNDIS_EventLog
+include             = netrndis.inf
+needs               = Usb_Rndis.ndi.Services
 
-[RNDIS_ServiceInst_51]
-DisplayName     = %ServiceDisplayName%
-ServiceType     = 1 
-StartType       = 3 
-ErrorControl    = 1 
-ServiceBinary   = %12%\usb8023.sys    
-LoadOrderGroup  = NDIS
-AddReg          = RNDIS_WMI_AddReg_51
+; Optional registry settings. You can modify as needed.
+[RNDIS_AddReg_Vista]
+HKR, NDI\params\VistaProperty, ParamDesc,  0, %Vista_Property%
+HKR, NDI\params\VistaProperty, type,       0, "edit"
+HKR, NDI\params\VistaProperty, LimitText,  0, "12"
+HKR, NDI\params\VistaProperty, UpperCase,  0, "1"
+HKR, NDI\params\VistaProperty, default,    0, " "
+HKR, NDI\params\VistaProperty, optional,   0, "1"
 
-[RNDIS_WMI_AddReg_51]
-HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismp.sys"
-
-; Windows 2000 and Windows XP common sections --------------------
-
-[RNDIS_AddReg_NT]
-HKR, Ndi,               Service,        0, "USB_RNDIS"
-HKR, Ndi\Interfaces,    UpperRange,     0, "ndis5" 
-HKR, Ndi\Interfaces,    LowerRange,     0, "ethernet"
-
-[RNDIS_EventLog]
-AddReg = RNDIS_EventLog_AddReg
-
-[RNDIS_EventLog_AddReg]
-HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll"
-HKR, , TypesSupported,   0x00010001, 7
-
-; Common Sections -------------------------------------------------
-
-[RNDIS_AddReg_Common]
-HKR, NDI\params\NetworkAddress, ParamDesc,  0, %NetworkAddress%
-HKR, NDI\params\NetworkAddress, type,       0, "edit"
-HKR, NDI\params\NetworkAddress, LimitText,  0, "12"
-HKR, NDI\params\NetworkAddress, UpperCase,  0, "1"
-HKR, NDI\params\NetworkAddress, default,    0, " "
-HKR, NDI\params\NetworkAddress, optional,   0, "1"
-
-[SourceDisksNames]
-1=%SourceDisk%,,1
-
-[SourceDisksFiles]
-usb8023m.sys=1
-rndismpm.sys=1
-usb8023w.sys=1
-rndismpw.sys=1
-usb8023k.sys=1
-rndismpk.sys=1
-
-[DestinationDirs]
-RNDIS_CopyFiles_98    = 10, system32/drivers
-RNDIS_CopyFiles_ME    = 10, system32/drivers
-RNDIS_CopyFiles_NT    = 12
+; No sys copyfiles - the sys files are already in-build
+; (part of the operating system).
+; We do not support XP SP1-, 2003 SP1-, ME, 9x.
 
 [Strings]
-ServiceDisplayName    = "USB Remote NDIS Network Device Driver"
-NetworkAddress        = "Network Address"
 Linux                 = "Linux Developer Community"
 LinuxDevice           = "Linux USB Ethernet/RNDIS Gadget"
-SourceDisk            = "Ethernet/RNDIS Gadget Driver Install Disk"
-
+Vista_Property        = "Optional Vista Property"
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index 96aadca..68879c9 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -551,9 +551,9 @@
 	/* USB */
 #if defined(CONFIG_USB_ULPI)
 	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	mxc_register_device(&mxc_otg_host, &usbotg_pdata);
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 8f66f65..7c37daa 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -245,9 +245,9 @@
 static void lilly1131_usb_init(void)
 {
 	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index da236c4..f66a957 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -256,7 +256,7 @@
 #if defined(CONFIG_USB_ULPI)
 	/* USB */
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 67776bc..7a075e8 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -412,7 +412,7 @@
 static int __init moboard_usbh2_init(void)
 {
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 }
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index 8a292dd..214de11 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -654,13 +654,13 @@
 #if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index 47f5311..28886f0 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -378,7 +378,7 @@
 #if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
 	}
diff --git a/arch/arm/mach-mx3/mx31moboard-smartbot.c b/arch/arm/mach-mx3/mx31moboard-smartbot.c
index 40c3e75..417757e 100644
--- a/arch/arm/mach-mx3/mx31moboard-smartbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-smartbot.c
@@ -134,7 +134,7 @@
 static int __init smartbot_otg_host_init(void)
 {
 	otg_host_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
 	return mxc_register_device(&mxc_otg_host, &otg_host_pdata);
 }
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
index 8d18d9d..dc90f5e 100644
--- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
+++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
@@ -226,6 +226,7 @@
 
 #define S3C_DIEPMSK				S3C_HSOTG_REG(0x810)
 
+#define S3C_DIEPMSK_TxFIFOEmpty			(1 << 7)
 #define S3C_DIEPMSK_INEPNakEffMsk		(1 << 6)
 #define S3C_DIEPMSK_INTknEPMisMsk		(1 << 5)
 #define S3C_DIEPMSK_INTknTXFEmpMsk		(1 << 4)
@@ -371,6 +372,7 @@
 
 #define S3C_DIEPDMA(_a)				S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
 #define S3C_DOEPDMA(_a)				S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
+#define S3C_DTXFSTS(_a)				S3C_HSOTG_REG(0x918 + ((_a) * 0x20))
 
 #define S3C_EPFIFO(_a)				S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
 
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index be5d8db..0574d84 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -215,7 +215,7 @@
 	vhci = hcd_to_vhci(hcd);
 
 	spin_lock_irqsave(&vhci->lock, flags);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		usbip_dbg_vhci_rh("hw accessible flag in on?\n");
 		goto done;
 	}
@@ -269,7 +269,7 @@
 
 	u32 prev_port_status[VHCI_NPORTS];
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		return -ETIMEDOUT;
 
 	/*
@@ -1041,7 +1041,7 @@
 	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&vhci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 	} else {
 		/* vhci->rh_state = DUMMY_RH_RUNNING;
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 80b4008..239f050 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -41,7 +41,7 @@
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB)		+= misc/
-obj-y				+= early/
+obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 101ffc9..593fc5e 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -564,7 +564,7 @@
 }
 
 static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
-				 int* actual_length)
+				 int *actual_length)
 {
 	struct timer_list timer;
 
@@ -952,7 +952,7 @@
 		put_unaligned(cpu_to_le32(addr), (__le32 *)(buf + offb));
 		offb += 4;
 		addr += l;
-		if(l)
+		if (l)
 			memcpy(buf + offb, data + offd, l);
 		if (l < stride)
 			memset(buf + offb + l, 0, stride - l);
@@ -967,7 +967,7 @@
 			}
 			offb = 0;
 		}
-	} while(offd < size);
+	} while (offd < size);
 	dbg("sent fw %#x", fw);
 
 	ret = 0;
@@ -1043,8 +1043,7 @@
 	if (instance->modem_type->boot_rom_patch) {
 		val = cpu_to_le32(BR_ADDR);
 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
-	}
-	else {
+	} else {
 		ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
 	}
 	if (ret) {
@@ -1068,7 +1067,7 @@
 }
 
 static int cxacru_find_firmware(struct cxacru_data *instance,
-				char* phase, const struct firmware **fw_p)
+				char *phase, const struct firmware **fw_p)
 {
 	struct usbatm_data *usbatm = instance->usbatm;
 	struct device *dev = &usbatm->usb_intf->dev;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 80f9617..4716e70 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -753,11 +753,13 @@
 	.id_table	= speedtch_usb_ids
 };
 
-static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) {
+static void speedtch_release_interfaces(struct usb_device *usb_dev,
+					int num_interfaces)
+{
 	struct usb_interface *cur_intf;
 	int i;
 
-	for(i = 0; i < num_interfaces; i++)
+	for (i = 0; i < num_interfaces; i++)
 		if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) {
 			usb_set_intfdata(cur_intf, NULL);
 			usb_driver_release_interface(&speedtch_usb_driver, cur_intf);
@@ -792,7 +794,7 @@
 
 	/* claim all interfaces */
 
-	for (i=0; i < num_interfaces; i++) {
+	for (i = 0; i < num_interfaces; i++) {
 		cur_intf = usb_ifnum_to_if(usb_dev, i);
 
 		if ((i != ifnum) && cur_intf) {
@@ -842,7 +844,7 @@
 
 		use_isoc = 0; /* fall back to bulk if endpoint not found */
 
-		for (i=0; i<desc->desc.bNumEndpoints; i++) {
+		for (i = 0; i < desc->desc.bNumEndpoints; i++) {
 			const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
 
 			if ((endpoint_desc->bEndpointAddress == target_address)) {
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index ebae944..5b3f555 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -67,6 +67,7 @@
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <linux/slab.h>
+#include <linux/kernel.h>
 
 #include <asm/unaligned.h>
 
@@ -2436,7 +2437,6 @@
 
 /* Retrieve the device End System Identifier (MAC) */
 
-#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10)
 static int uea_getesi(struct uea_softc *sc, u_char * esi)
 {
 	unsigned char mac_str[2 * ETH_ALEN + 1];
@@ -2447,7 +2447,8 @@
 		return 1;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]);
+		esi[i] = hex_to_bin(mac_str[2 * i]) * 16 +
+			 hex_to_bin(mac_str[2 * i + 1]);
 
 	return 0;
 }
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 9b53e8d..05bf5a2 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -84,8 +84,8 @@
 
 #ifdef VERBOSE_DEBUG
 static int usbatm_print_packet(const unsigned char *data, int len);
-#define PACKETDEBUG(arg...)	usbatm_print_packet (arg)
-#define vdbg(arg...)		dbg (arg)
+#define PACKETDEBUG(arg...)	usbatm_print_packet(arg)
+#define vdbg(arg...)		dbg(arg)
 #else
 #define PACKETDEBUG(arg...)
 #define vdbg(arg...)
@@ -273,8 +273,7 @@
 
 	if (unlikely(status) &&
 			(!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
-			 status != -EILSEQ ))
-	{
+			 status != -EILSEQ)) {
 		if (status == -ESHUTDOWN)
 			return;
 
@@ -494,7 +493,7 @@
 		ptr += data_len;
 		__skb_pull(skb, data_len);
 
-		if(!left)
+		if (!left)
 			continue;
 
 		memset(ptr, 0, left);
@@ -506,7 +505,7 @@
 			trailer[2] = ctrl->len >> 8;
 			trailer[3] = ctrl->len;
 
-			ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4);
+			ctrl->crc = ~crc32_be(ctrl->crc, ptr, left - 4);
 
 			trailer[4] = ctrl->crc >> 24;
 			trailer[5] = ctrl->crc >> 16;
@@ -516,8 +515,7 @@
 			target[3] |= 0x2;	/* adjust PTI */
 
 			ctrl->len = 0;		/* tag this skb finished */
-		}
-		else
+		} else
 			ctrl->crc = crc32_be(ctrl->crc, ptr, left);
 	}
 
@@ -1146,7 +1144,7 @@
 	instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);
 
 	/* tx buffer size must be a positive multiple of the stride */
-	instance->tx_channel.buf_size = max (instance->tx_channel.stride,
+	instance->tx_channel.buf_size = max(instance->tx_channel.stride,
 			snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
 
 	/* rx buffer size must be a positive multiple of the endpoint maxpacket */
@@ -1159,7 +1157,7 @@
 		goto fail_unbind;
 	}
 
-	num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
+	num_packets = max(1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
 
 	if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)
 		num_packets--;
@@ -1262,7 +1260,7 @@
 		usb_free_urb(instance->urbs[i]);
 	}
 
-	kfree (instance);
+	kfree(instance);
 
 	return error;
 }
@@ -1390,9 +1388,8 @@
 	for (i = 0; i < len;) {
 		buffer[0] = '\0';
 		sprintf(buffer, "%.3d :", i);
-		for (j = 0; (j < 16) && (i < len); j++, i++) {
+		for (j = 0; (j < 16) && (i < len); j++, i++)
 			sprintf(buffer, "%s %2.2x", buffer, data[i]);
-		}
 		dbg("%s", buffer);
 	}
 	return i;
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index 0863f85..5fc4894 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -48,7 +48,7 @@
 			dev_warn(&(instance)->usb_intf->dev,		\
 				 "failed assertion '%s' at line %d",	\
 				 __stringify(x), __LINE__);		\
-	} while(0)
+	} while (0)
 #endif
 
 #define usb_err(instance, format, arg...)	\
@@ -59,7 +59,7 @@
 	dev_warn(&(instance)->usb_intf->dev , format , ## arg)
 #ifdef DEBUG
 #define usb_dbg(instance, format, arg...)	\
-        dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
+	dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
 #else
 #define usb_dbg(instance, format, arg...)	\
 	do {} while (0)
@@ -104,21 +104,21 @@
 /*
 *  Assuming all methods exist and succeed, they are called in this order:
 *
-*  	bind, heavy_init, atm_start, ..., atm_stop, unbind
+*	bind, heavy_init, atm_start, ..., atm_stop, unbind
 */
 
 struct usbatm_driver {
 	const char *driver_name;
 
 	/* init device ... can sleep, or cause probe() failure */
-        int (*bind) (struct usbatm_data *, struct usb_interface *,
+	int (*bind) (struct usbatm_data *, struct usb_interface *,
 		     const struct usb_device_id *id);
 
 	/* additional device initialization that is too slow to be done in probe() */
-        int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
+	int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
 
 	/* cleanup device ... can sleep, but can't fail */
-        void (*unbind) (struct usbatm_data *, struct usb_interface *);
+	void (*unbind) (struct usbatm_data *, struct usb_interface *);
 
 	/* init ATM device ... can sleep, or cause ATM initialization failure */
 	int (*atm_start) (struct usbatm_data *, struct atm_dev *);
@@ -126,9 +126,9 @@
 	/* cleanup ATM device ... can sleep, but can't fail */
 	void (*atm_stop) (struct usbatm_data *, struct atm_dev *);
 
-        int bulk_in;	/* bulk rx endpoint */
-        int isoc_in;	/* isochronous rx endpoint */
-        int bulk_out;	/* bulk tx endpoint */
+	int bulk_in;	/* bulk rx endpoint */
+	int isoc_in;	/* isochronous rx endpoint */
+	int bulk_out;	/* bulk tx endpoint */
 
 	unsigned rx_padding;
 	unsigned tx_padding;
@@ -156,7 +156,7 @@
 struct usbatm_data {
 	/******************
 	*  public fields  *
-        ******************/
+	******************/
 
 	/* mini driver */
 	struct usbatm_driver *driver;
@@ -174,7 +174,7 @@
 
 	/********************************
 	*  private fields - do not use  *
-        ********************************/
+	********************************/
 
 	struct kref refcount;
 	struct mutex serialize;
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 17d167b..48ee0c5 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -49,13 +49,13 @@
 static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
 static struct usb_driver xusbatm_usb_driver;
 
-static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
+static struct usb_interface *xusbatm_find_intf(struct usb_device *usb_dev, int altsetting, u8 ep)
 {
 	struct usb_host_interface *alt;
 	struct usb_interface *intf;
 	int i, j;
 
-	for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
+	for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
 		if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
 			for (j = 0; j < alt->desc.bNumEndpoints; j++)
 				if (alt->endpoint[j].desc.bEndpointAddress == ep)
@@ -63,7 +63,7 @@
 	return NULL;
 }
 
-static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
+static int xusbatm_capture_intf(struct usbatm_data *usbatm, struct usb_device *usb_dev,
 		struct usb_interface *intf, int altsetting, int claim)
 {
 	int ifnum = intf->altsetting->desc.bInterfaceNumber;
@@ -80,7 +80,7 @@
 	return 0;
 }
 
-static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
+static void xusbatm_release_intf(struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
 {
 	if (claimed) {
 		usb_set_intfdata(intf, NULL);
@@ -147,7 +147,7 @@
 
 	usb_dbg(usbatm, "%s entered\n", __func__);
 
-	for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
+	for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
 		struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
 
 		if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c
index a22b887..d3e1356 100644
--- a/drivers/usb/c67x00/c67x00-hcd.c
+++ b/drivers/usb/c67x00/c67x00-hcd.c
@@ -264,7 +264,7 @@
 	if (unlikely(hcd->state == HC_STATE_HALT))
 		return;
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		return;
 
 	/* Handle Start of frame events */
@@ -282,7 +282,7 @@
 {
 	hcd->uses_new_polling = 1;
 	hcd->state = HC_STATE_RUNNING;
-	hcd->poll_rh = 1;
+	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
 	return 0;
 }
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 84f9e52..e325162 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -135,7 +135,7 @@
  * ->lock locks what interrupt accesses.
  */
 struct usblp {
-	struct usb_device 	*dev;			/* USB device */
+	struct usb_device	*dev;			/* USB device */
 	struct mutex		wmut;
 	struct mutex		mut;
 	spinlock_t		lock;		/* locks rcomplete, wcomplete */
@@ -169,7 +169,8 @@
 };
 
 #ifdef DEBUG
-static void usblp_dump(struct usblp *usblp) {
+static void usblp_dump(struct usblp *usblp)
+{
 	int p;
 
 	dbg("usblp=0x%p", usblp);
@@ -216,8 +217,8 @@
 	{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
 	{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
 	{ 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
-	{ 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */   
-	{ 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */   
+	{ 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */
+	{ 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */
 	{ 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
 	{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
 	{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
@@ -254,9 +255,8 @@
 	/* High byte has the interface index.
 	   Low byte has the alternate setting.
 	 */
-	if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) {
-	  index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting;
-	}
+	if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS))
+		index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting;
 
 	retval = usb_control_msg(usblp->dev,
 		dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
@@ -372,7 +372,7 @@
 	return newerr;
 }
 
-static int handle_bidir (struct usblp *usblp)
+static int handle_bidir(struct usblp *usblp)
 {
 	if (usblp->bidir && usblp->used) {
 		if (usblp_submit_read(usblp) < 0)
@@ -395,14 +395,13 @@
 	if (minor < 0)
 		return -ENODEV;
 
-	mutex_lock (&usblp_mutex);
+	mutex_lock(&usblp_mutex);
 
 	retval = -ENODEV;
 	intf = usb_find_interface(&usblp_driver, minor);
-	if (!intf) {
+	if (!intf)
 		goto out;
-	}
-	usblp = usb_get_intfdata (intf);
+	usblp = usb_get_intfdata(intf);
 	if (!usblp || !usblp->dev || !usblp->present)
 		goto out;
 
@@ -433,18 +432,18 @@
 		retval = -EIO;
 	}
 out:
-	mutex_unlock (&usblp_mutex);
+	mutex_unlock(&usblp_mutex);
 	return retval;
 }
 
-static void usblp_cleanup (struct usblp *usblp)
+static void usblp_cleanup(struct usblp *usblp)
 {
 	printk(KERN_INFO "usblp%d: removed\n", usblp->minor);
 
 	kfree(usblp->readbuf);
-	kfree (usblp->device_id_string);
-	kfree (usblp->statusbuf);
-	kfree (usblp);
+	kfree(usblp->device_id_string);
+	kfree(usblp->statusbuf);
+	kfree(usblp);
 }
 
 static void usblp_unlink_urbs(struct usblp *usblp)
@@ -458,14 +457,14 @@
 
 	usblp->flags &= ~LP_ABORT;
 
-	mutex_lock (&usblp_mutex);
+	mutex_lock(&usblp_mutex);
 	usblp->used = 0;
 	if (usblp->present) {
 		usblp_unlink_urbs(usblp);
 		usb_autopm_put_interface(usblp->intf);
-	} else 		/* finish cleanup from disconnect */
-		usblp_cleanup (usblp);
-	mutex_unlock (&usblp_mutex);
+	} else		/* finish cleanup from disconnect */
+		usblp_cleanup(usblp);
+	mutex_unlock(&usblp_mutex);
 	return 0;
 }
 
@@ -495,190 +494,190 @@
 	int twoints[2];
 	int retval = 0;
 
-	mutex_lock (&usblp->mut);
+	mutex_lock(&usblp->mut);
 	if (!usblp->present) {
 		retval = -ENODEV;
 		goto done;
 	}
 
 	dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
-		_IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
+		_IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd));
 
 	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */
 
 		switch (_IOC_NR(cmd)) {
 
-			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
-				if (_IOC_DIR(cmd) != _IOC_READ) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
+			if (_IOC_DIR(cmd) != _IOC_READ) {
+				retval = -EINVAL;
+				goto done;
+			}
 
-				length = usblp_cache_device_id_string(usblp);
-				if (length < 0) {
-					retval = length;
-					goto done;
-				}
-				if (length > _IOC_SIZE(cmd))
-					length = _IOC_SIZE(cmd); /* truncate */
+			length = usblp_cache_device_id_string(usblp);
+			if (length < 0) {
+				retval = length;
+				goto done;
+			}
+			if (length > _IOC_SIZE(cmd))
+				length = _IOC_SIZE(cmd); /* truncate */
 
-				if (copy_to_user((void __user *) arg,
-						usblp->device_id_string,
-						(unsigned long) length)) {
-					retval = -EFAULT;
-					goto done;
-				}
+			if (copy_to_user((void __user *) arg,
+					usblp->device_id_string,
+					(unsigned long) length)) {
+				retval = -EFAULT;
+				goto done;
+			}
 
-				break;
+			break;
 
-			case IOCNR_GET_PROTOCOLS:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_GET_PROTOCOLS:
+			if (_IOC_DIR(cmd) != _IOC_READ ||
+			    _IOC_SIZE(cmd) < sizeof(twoints)) {
+				retval = -EINVAL;
+				goto done;
+			}
 
-				twoints[0] = usblp->current_protocol;
-				twoints[1] = 0;
-				for (i = USBLP_FIRST_PROTOCOL;
-				     i <= USBLP_LAST_PROTOCOL; i++) {
-					if (usblp->protocol[i].alt_setting >= 0)
-						twoints[1] |= (1<<i);
-				}
+			twoints[0] = usblp->current_protocol;
+			twoints[1] = 0;
+			for (i = USBLP_FIRST_PROTOCOL;
+			     i <= USBLP_LAST_PROTOCOL; i++) {
+				if (usblp->protocol[i].alt_setting >= 0)
+					twoints[1] |= (1<<i);
+			}
 
-				if (copy_to_user((void __user *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
+			if (copy_to_user((void __user *)arg,
+					(unsigned char *)twoints,
+					sizeof(twoints))) {
+				retval = -EFAULT;
+				goto done;
+			}
 
-				break;
+			break;
 
-			case IOCNR_SET_PROTOCOL:
-				if (_IOC_DIR(cmd) != _IOC_WRITE) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_SET_PROTOCOL:
+			if (_IOC_DIR(cmd) != _IOC_WRITE) {
+				retval = -EINVAL;
+				goto done;
+			}
 
 #ifdef DEBUG
-				if (arg == -10) {
-					usblp_dump(usblp);
-					break;
-				}
+			if (arg == -10) {
+				usblp_dump(usblp);
+				break;
+			}
 #endif
 
-				usblp_unlink_urbs(usblp);
-				retval = usblp_set_protocol(usblp, arg);
-				if (retval < 0) {
-					usblp_set_protocol(usblp,
-						usblp->current_protocol);
-				}
-				break;
+			usblp_unlink_urbs(usblp);
+			retval = usblp_set_protocol(usblp, arg);
+			if (retval < 0) {
+				usblp_set_protocol(usblp,
+					usblp->current_protocol);
+			}
+			break;
 
-			case IOCNR_HP_SET_CHANNEL:
-				if (_IOC_DIR(cmd) != _IOC_WRITE ||
-				    le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 ||
-				    usblp->quirks & USBLP_QUIRK_BIDIR) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_HP_SET_CHANNEL:
+			if (_IOC_DIR(cmd) != _IOC_WRITE ||
+			    le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 ||
+			    usblp->quirks & USBLP_QUIRK_BIDIR) {
+				retval = -EINVAL;
+				goto done;
+			}
 
-				err = usblp_hp_channel_change_request(usblp,
-					arg, &newChannel);
-				if (err < 0) {
-					dev_err(&usblp->dev->dev,
-						"usblp%d: error = %d setting "
-						"HP channel\n",
-						usblp->minor, err);
-					retval = -EIO;
-					goto done;
-				}
+			err = usblp_hp_channel_change_request(usblp,
+				arg, &newChannel);
+			if (err < 0) {
+				dev_err(&usblp->dev->dev,
+					"usblp%d: error = %d setting "
+					"HP channel\n",
+					usblp->minor, err);
+				retval = -EIO;
+				goto done;
+			}
 
-				dbg("usblp%d requested/got HP channel %ld/%d",
-					usblp->minor, arg, newChannel);
-				break;
+			dbg("usblp%d requested/got HP channel %ld/%d",
+				usblp->minor, arg, newChannel);
+			break;
 
-			case IOCNR_GET_BUS_ADDRESS:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_GET_BUS_ADDRESS:
+			if (_IOC_DIR(cmd) != _IOC_READ ||
+			    _IOC_SIZE(cmd) < sizeof(twoints)) {
+				retval = -EINVAL;
+				goto done;
+			}
 
-				twoints[0] = usblp->dev->bus->busnum;
-				twoints[1] = usblp->dev->devnum;
-				if (copy_to_user((void __user *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
+			twoints[0] = usblp->dev->bus->busnum;
+			twoints[1] = usblp->dev->devnum;
+			if (copy_to_user((void __user *)arg,
+					(unsigned char *)twoints,
+					sizeof(twoints))) {
+				retval = -EFAULT;
+				goto done;
+			}
 
-				dbg("usblp%d is bus=%d, device=%d",
-					usblp->minor, twoints[0], twoints[1]);
-				break;
+			dbg("usblp%d is bus=%d, device=%d",
+				usblp->minor, twoints[0], twoints[1]);
+			break;
 
-			case IOCNR_GET_VID_PID:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
+		case IOCNR_GET_VID_PID:
+			if (_IOC_DIR(cmd) != _IOC_READ ||
+			    _IOC_SIZE(cmd) < sizeof(twoints)) {
+				retval = -EINVAL;
+				goto done;
+			}
 
-				twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor);
-				twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct);
-				if (copy_to_user((void __user *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
+			twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor);
+			twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct);
+			if (copy_to_user((void __user *)arg,
+					(unsigned char *)twoints,
+					sizeof(twoints))) {
+				retval = -EFAULT;
+				goto done;
+			}
 
-				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
-					usblp->minor, twoints[0], twoints[1]);
-				break;
+			dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+				usblp->minor, twoints[0], twoints[1]);
+			break;
 
-			case IOCNR_SOFT_RESET:
-				if (_IOC_DIR(cmd) != _IOC_NONE) {
-					retval = -EINVAL;
-					goto done;
-				}
-				retval = usblp_reset(usblp);
-				break;
-			default:
-				retval = -ENOTTY;
+		case IOCNR_SOFT_RESET:
+			if (_IOC_DIR(cmd) != _IOC_NONE) {
+				retval = -EINVAL;
+				goto done;
+			}
+			retval = usblp_reset(usblp);
+			break;
+		default:
+			retval = -ENOTTY;
 		}
 	else	/* old-style ioctl value */
 		switch (cmd) {
 
-			case LPGETSTATUS:
-				if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
-					if (printk_ratelimit())
-						printk(KERN_ERR "usblp%d:"
-						    "failed reading printer status (%d)\n",
-						    usblp->minor, retval);
-					retval = -EIO;
-					goto done;
-				}
-				status = *usblp->statusbuf;
-				if (copy_to_user ((void __user *)arg, &status, sizeof(int)))
-					retval = -EFAULT;
-				break;
+		case LPGETSTATUS:
+			if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
+				if (printk_ratelimit())
+					printk(KERN_ERR "usblp%d:"
+					    "failed reading printer status (%d)\n",
+					    usblp->minor, retval);
+				retval = -EIO;
+				goto done;
+			}
+			status = *usblp->statusbuf;
+			if (copy_to_user((void __user *)arg, &status, sizeof(int)))
+				retval = -EFAULT;
+			break;
 
-			case LPABORT:
-				if (arg)
-					usblp->flags |= LP_ABORT;
-				else
-					usblp->flags &= ~LP_ABORT;
-				break;
+		case LPABORT:
+			if (arg)
+				usblp->flags |= LP_ABORT;
+			else
+				usblp->flags &= ~LP_ABORT;
+			break;
 
-			default:
-				retval = -ENOTTY;
+		default:
+			retval = -ENOTTY;
 		}
 
 done:
-	mutex_unlock (&usblp->mut);
+	mutex_unlock(&usblp->mut);
 	return retval;
 }
 
@@ -840,7 +839,7 @@
 	}
 
 done:
-	mutex_unlock (&usblp->mut);
+	mutex_unlock(&usblp->mut);
 	return count;
 }
 
@@ -1023,7 +1022,7 @@
  * while you are sending print data, and you don't try to query the
  * printer status every couple of milliseconds, you will probably be OK.
  */
-static unsigned int usblp_quirks (__u16 vendor, __u16 product)
+static unsigned int usblp_quirks(__u16 vendor, __u16 product)
 {
 	int i;
 
@@ -1031,7 +1030,7 @@
 		if (vendor == quirk_printers[i].vendorId &&
 		    product == quirk_printers[i].productId)
 			return quirk_printers[i].quirks;
- 	}
+	}
 	return 0;
 }
 
@@ -1061,7 +1060,7 @@
 static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
-	struct usblp *usblp = usb_get_intfdata (intf);
+	struct usblp *usblp = usb_get_intfdata(intf);
 
 	if (usblp->device_id_string[0] == 0 &&
 	    usblp->device_id_string[1] == 0)
@@ -1075,7 +1074,7 @@
 static int usblp_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
-	struct usb_device *dev = interface_to_usbdev (intf);
+	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usblp *usblp;
 	int protocol;
 	int retval;
@@ -1089,7 +1088,7 @@
 	}
 	usblp->dev = dev;
 	mutex_init(&usblp->wmut);
-	mutex_init (&usblp->mut);
+	mutex_init(&usblp->mut);
 	spin_lock_init(&usblp->lock);
 	init_waitqueue_head(&usblp->rwait);
 	init_waitqueue_head(&usblp->wwait);
@@ -1153,7 +1152,7 @@
 	usblp_check_status(usblp, 0);
 #endif
 
-	usb_set_intfdata (intf, usblp);
+	usb_set_intfdata(intf, usblp);
 
 	usblp->present = 1;
 
@@ -1177,7 +1176,7 @@
 	return 0;
 
 abort_intfdata:
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
 	kfree(usblp->readbuf);
@@ -1340,35 +1339,35 @@
 
 static void usblp_disconnect(struct usb_interface *intf)
 {
-	struct usblp *usblp = usb_get_intfdata (intf);
+	struct usblp *usblp = usb_get_intfdata(intf);
 
 	usb_deregister_dev(intf, &usblp_class);
 
 	if (!usblp || !usblp->dev) {
 		dev_err(&intf->dev, "bogus disconnect\n");
-		BUG ();
+		BUG();
 	}
 
 	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 
-	mutex_lock (&usblp_mutex);
-	mutex_lock (&usblp->mut);
+	mutex_lock(&usblp_mutex);
+	mutex_lock(&usblp->mut);
 	usblp->present = 0;
 	wake_up(&usblp->wwait);
 	wake_up(&usblp->rwait);
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 
 	usblp_unlink_urbs(usblp);
-	mutex_unlock (&usblp->mut);
+	mutex_unlock(&usblp->mut);
 
 	if (!usblp->used)
-		usblp_cleanup (usblp);
-	mutex_unlock (&usblp_mutex);
+		usblp_cleanup(usblp);
+	mutex_unlock(&usblp_mutex);
 }
 
 static int usblp_suspend(struct usb_interface *intf, pm_message_t message)
 {
-	struct usblp *usblp = usb_get_intfdata (intf);
+	struct usblp *usblp = usb_get_intfdata(intf);
 
 	usblp_unlink_urbs(usblp);
 #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */
@@ -1382,10 +1381,10 @@
 
 static int usblp_resume(struct usb_interface *intf)
 {
-	struct usblp *usblp = usb_get_intfdata (intf);
+	struct usblp *usblp = usb_get_intfdata(intf);
 	int r;
 
-	r = handle_bidir (usblp);
+	r = handle_bidir(usblp);
 
 	return r;
 }
@@ -1401,7 +1400,7 @@
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, usblp_ids);
+MODULE_DEVICE_TABLE(usb, usblp_ids);
 
 static struct usb_driver usblp_driver = {
 	.name =		"usblp",
@@ -1426,8 +1425,8 @@
 module_init(usblp_init);
 module_exit(usblp_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 module_param(proto_bias, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index c2f62a3..f1aaff6 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1668,13 +1668,10 @@
 	default:
 		if (intf->dev.driver)
 			driver = to_usb_driver(intf->dev.driver);
-		if (driver == NULL || driver->ioctl == NULL) {
+		if (driver == NULL || driver->unlocked_ioctl == NULL) {
 			retval = -ENOTTY;
 		} else {
-			/* keep API that guarantees BKL */
-			lock_kernel();
-			retval = driver->ioctl(intf, ctl->ioctl_code, buf);
-			unlock_kernel();
+			retval = driver->unlocked_ioctl(intf, ctl->ioctl_code, buf);
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 		}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index a6bd53a..d7a4401 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1742,9 +1742,8 @@
 		}
 
 		/* Prevent the parent from suspending immediately after */
-		else if (udev->parent) {
+		else if (udev->parent)
 			udev->parent->last_busy = jiffies;
-		}
 	}
 
 	/* Runtime suspend for a USB interface doesn't mean anything. */
@@ -1786,21 +1785,19 @@
 	return 0;
 }
 
-static struct dev_pm_ops usb_bus_pm_ops = {
+static const struct dev_pm_ops usb_bus_pm_ops = {
 	.runtime_suspend =	usb_runtime_suspend,
 	.runtime_resume =	usb_runtime_resume,
 	.runtime_idle =		usb_runtime_idle,
 };
 
-#else
-
-#define usb_bus_pm_ops	(*(struct dev_pm_ops *) NULL)
-
 #endif /* CONFIG_USB_SUSPEND */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
 	.uevent =	usb_uevent,
+#ifdef CONFIG_USB_SUSPEND
 	.pm =		&usb_bus_pm_ops,
+#endif
 };
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 4f84a41..3788e73 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -96,16 +96,21 @@
 
 	switch (usb_endpoint_type(ep->desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
-		if (ep->udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
+		if (ep->udev->speed == USB_SPEED_HIGH)
+			/* uframes per NAK */
 			interval = ep->desc->bInterval;
 		break;
+
 	case USB_ENDPOINT_XFER_ISOC:
 		interval = 1 << (ep->desc->bInterval - 1);
 		break;
+
 	case USB_ENDPOINT_XFER_BULK:
-		if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+		if (ep->udev->speed == USB_SPEED_HIGH && !in)
+			/* uframes per NAK */
 			interval = ep->desc->bInterval;
 		break;
+
 	case USB_ENDPOINT_XFER_INT:
 		if (ep->udev->speed == USB_SPEED_HIGH)
 			interval = 1 << (ep->desc->bInterval - 1);
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 9a34ccb..69ecd3c 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -105,8 +105,10 @@
 		/* When the first config's first interface is one of Microsoft's
 		 * pet nonstandard Ethernet-over-USB protocols, ignore it unless
 		 * this kernel has enabled the necessary host side driver.
+		 * But: Don't ignore it if it's the only config.
 		 */
-		if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) {
+		if (i == 0 && num_configs > 1 && desc &&
+				(is_rndis(desc) || is_activesync(desc))) {
 #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
 			continue;
 #else
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 1cf2d1e..c3f9854 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -66,10 +66,7 @@
 	 * vice versa.
 	 */
 	companion = NULL;
-	for (;;) {
-		companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion);
-		if (!companion)
-			break;
+	for_each_pci_dev(companion) {
 		if (companion->bus != pdev->bus ||
 				PCI_SLOT(companion->devfn) != slot)
 			continue;
@@ -250,6 +247,9 @@
 	if (retval != 0)
 		goto err4;
 	set_hs_companion(dev, hcd);
+
+	if (pci_dev_run_wake(dev))
+		pm_runtime_put_noidle(&dev->dev);
 	return retval;
 
  err4:
@@ -292,6 +292,17 @@
 	if (!hcd)
 		return;
 
+	if (pci_dev_run_wake(dev))
+		pm_runtime_get_noresume(&dev->dev);
+
+	/* Fake an interrupt request in order to give the driver a chance
+	 * to test whether the controller hardware has been removed (e.g.,
+	 * cardbus physical eject).
+	 */
+	local_irq_disable();
+	usb_hcd_irq(0, hcd);
+	local_irq_enable();
+
 	usb_remove_hcd(hcd);
 	if (hcd->driver->flags & HCD_MEMORY) {
 		iounmap(hcd->regs);
@@ -317,12 +328,34 @@
 	if (!hcd)
 		return;
 
-	if (hcd->driver->shutdown)
+	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
+			hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
-#ifdef	CONFIG_PM_SLEEP
+#ifdef	CONFIG_PM_OPS
+
+#ifdef	CONFIG_PPC_PMAC
+static void powermac_set_asic(struct pci_dev *pci_dev, int enable)
+{
+	/* Enanble or disable ASIC clocks for USB */
+	if (machine_is(powermac)) {
+		struct device_node	*of_node;
+
+		of_node = pci_device_to_OF_node(pci_dev);
+		if (of_node)
+			pmac_call_feature(PMAC_FTR_USB_ENABLE,
+					of_node, 0, enable);
+	}
+}
+
+#else
+
+static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable)
+{}
+
+#endif	/* CONFIG_PPC_PMAC */
 
 static int check_root_hub_suspended(struct device *dev)
 {
@@ -337,7 +370,7 @@
 	return 0;
 }
 
-static int hcd_pci_suspend(struct device *dev)
+static int suspend_common(struct device *dev, bool do_wakeup)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
@@ -352,13 +385,21 @@
 	if (retval)
 		return retval;
 
-	/* We might already be suspended (runtime PM -- not yet written) */
-	if (pci_dev->current_state != PCI_D0)
-		return retval;
-
 	if (hcd->driver->pci_suspend) {
-		retval = hcd->driver->pci_suspend(hcd);
+		/* Optimization: Don't suspend if a root-hub wakeup is
+		 * pending and it would cause the HCD to wake up anyway.
+		 */
+		if (do_wakeup && HCD_WAKEUP_PENDING(hcd))
+			return -EBUSY;
+		retval = hcd->driver->pci_suspend(hcd, do_wakeup);
 		suspend_report_result(hcd->driver->pci_suspend, retval);
+
+		/* Check again in case wakeup raced with pci_suspend */
+		if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
+			if (hcd->driver->pci_resume)
+				hcd->driver->pci_resume(hcd, false);
+			retval = -EBUSY;
+		}
 		if (retval)
 			return retval;
 	}
@@ -374,6 +415,48 @@
 	return retval;
 }
 
+static int resume_common(struct device *dev, int event)
+{
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+	int			retval;
+
+	if (hcd->state != HC_STATE_SUSPENDED) {
+		dev_dbg(dev, "can't resume, not suspended!\n");
+		return 0;
+	}
+
+	retval = pci_enable_device(pci_dev);
+	if (retval < 0) {
+		dev_err(dev, "can't re-enable after resume, %d!\n", retval);
+		return retval;
+	}
+
+	pci_set_master(pci_dev);
+
+	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+
+	if (hcd->driver->pci_resume) {
+		if (event != PM_EVENT_AUTO_RESUME)
+			wait_for_companions(pci_dev, hcd);
+
+		retval = hcd->driver->pci_resume(hcd,
+				event == PM_EVENT_RESTORE);
+		if (retval) {
+			dev_err(dev, "PCI post-resume error %d!\n", retval);
+			usb_hc_died(hcd);
+		}
+	}
+	return retval;
+}
+
+#ifdef	CONFIG_PM_SLEEP
+
+static int hcd_pci_suspend(struct device *dev)
+{
+	return suspend_common(dev, device_may_wakeup(dev));
+}
+
 static int hcd_pci_suspend_noirq(struct device *dev)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
@@ -408,16 +491,7 @@
 		return retval;
 	}
 
-#ifdef CONFIG_PPC_PMAC
-	/* Disable ASIC clocks for USB */
-	if (machine_is(powermac)) {
-		struct device_node	*of_node;
-
-		of_node = pci_device_to_OF_node(pci_dev);
-		if (of_node)
-			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-	}
-#endif
+	powermac_set_asic(pci_dev, 0);
 	return retval;
 }
 
@@ -425,69 +499,63 @@
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
 
-#ifdef CONFIG_PPC_PMAC
-	/* Reenable ASIC clocks for USB */
-	if (machine_is(powermac)) {
-		struct device_node *of_node;
-
-		of_node = pci_device_to_OF_node(pci_dev);
-		if (of_node)
-			pmac_call_feature(PMAC_FTR_USB_ENABLE,
-						of_node, 0, 1);
-	}
-#endif
+	powermac_set_asic(pci_dev, 1);
 
 	/* Go back to D0 and disable remote wakeup */
 	pci_back_from_sleep(pci_dev);
 	return 0;
 }
 
-static int resume_common(struct device *dev, bool hibernated)
-{
-	struct pci_dev		*pci_dev = to_pci_dev(dev);
-	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
-	int			retval;
-
-	if (hcd->state != HC_STATE_SUSPENDED) {
-		dev_dbg(dev, "can't resume, not suspended!\n");
-		return 0;
-	}
-
-	retval = pci_enable_device(pci_dev);
-	if (retval < 0) {
-		dev_err(dev, "can't re-enable after resume, %d!\n", retval);
-		return retval;
-	}
-
-	pci_set_master(pci_dev);
-
-	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
-
-	if (hcd->driver->pci_resume) {
-		/* This call should be made only during system resume,
-		 * not during runtime resume.
-		 */
-		wait_for_companions(pci_dev, hcd);
-
-		retval = hcd->driver->pci_resume(hcd, hibernated);
-		if (retval) {
-			dev_err(dev, "PCI post-resume error %d!\n", retval);
-			usb_hc_died(hcd);
-		}
-	}
-	return retval;
-}
-
 static int hcd_pci_resume(struct device *dev)
 {
-	return resume_common(dev, false);
+	return resume_common(dev, PM_EVENT_RESUME);
 }
 
 static int hcd_pci_restore(struct device *dev)
 {
-	return resume_common(dev, true);
+	return resume_common(dev, PM_EVENT_RESTORE);
 }
 
+#else
+
+#define hcd_pci_suspend		NULL
+#define hcd_pci_suspend_noirq	NULL
+#define hcd_pci_resume_noirq	NULL
+#define hcd_pci_resume		NULL
+#define hcd_pci_restore		NULL
+
+#endif	/* CONFIG_PM_SLEEP */
+
+#ifdef	CONFIG_PM_RUNTIME
+
+static int hcd_pci_runtime_suspend(struct device *dev)
+{
+	int	retval;
+
+	retval = suspend_common(dev, true);
+	if (retval == 0)
+		powermac_set_asic(to_pci_dev(dev), 0);
+	dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval);
+	return retval;
+}
+
+static int hcd_pci_runtime_resume(struct device *dev)
+{
+	int	retval;
+
+	powermac_set_asic(to_pci_dev(dev), 1);
+	retval = resume_common(dev, PM_EVENT_AUTO_RESUME);
+	dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval);
+	return retval;
+}
+
+#else
+
+#define hcd_pci_runtime_suspend	NULL
+#define hcd_pci_runtime_resume	NULL
+
+#endif	/* CONFIG_PM_RUNTIME */
+
 const struct dev_pm_ops usb_hcd_pci_pm_ops = {
 	.suspend	= hcd_pci_suspend,
 	.suspend_noirq	= hcd_pci_suspend_noirq,
@@ -501,7 +569,9 @@
 	.poweroff_noirq	= hcd_pci_suspend_noirq,
 	.restore_noirq	= hcd_pci_resume_noirq,
 	.restore	= hcd_pci_restore,
+	.runtime_suspend = hcd_pci_runtime_suspend,
+	.runtime_resume	= hcd_pci_runtime_resume,
 };
 EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops);
 
-#endif	/* CONFIG_PM_SLEEP */
+#endif	/* CONFIG_PM_OPS */
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12742f1..5cca00a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -667,7 +667,7 @@
 	unsigned long	flags;
 	char		buffer[6];	/* Any root hubs with > 31 ports? */
 
-	if (unlikely(!hcd->rh_registered))
+	if (unlikely(!hcd->rh_pollable))
 		return;
 	if (!hcd->uses_new_polling && !hcd->status_urb)
 		return;
@@ -679,7 +679,7 @@
 		spin_lock_irqsave(&hcd_root_hub_lock, flags);
 		urb = hcd->status_urb;
 		if (urb) {
-			hcd->poll_pending = 0;
+			clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
 			hcd->status_urb = NULL;
 			urb->actual_length = length;
 			memcpy(urb->transfer_buffer, buffer, length);
@@ -690,7 +690,7 @@
 			spin_lock(&hcd_root_hub_lock);
 		} else {
 			length = 0;
-			hcd->poll_pending = 1;
+			set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
 		}
 		spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
 	}
@@ -699,7 +699,7 @@
 	 * exceed that limit if HZ is 100. The math is more clunky than
 	 * maybe expected, this is to make sure that all timers for USB devices
 	 * fire at the same time to give the CPU a break inbetween */
-	if (hcd->uses_new_polling ? hcd->poll_rh :
+	if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
 			(length == 0 && hcd->status_urb != NULL))
 		mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
 }
@@ -736,7 +736,7 @@
 		mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
 
 	/* If a status change has already occurred, report it ASAP */
-	else if (hcd->poll_pending)
+	else if (HCD_POLL_PENDING(hcd))
 		mod_timer(&hcd->rh_timer, jiffies);
 	retval = 0;
  done:
@@ -1150,8 +1150,7 @@
 	 * finish unlinking the initial failed usb_set_address()
 	 * or device descriptor fetch.
 	 */
-	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
-			!is_root_hub(urb->dev)) {
+	if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
 		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
 			"Controller is probably using the wrong IRQ.\n");
 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
@@ -1219,6 +1218,11 @@
 {
 	unsigned char *vaddr;
 
+	if (*vaddr_handle == NULL) {
+		WARN_ON_ONCE(1);
+		return -EFAULT;
+	}
+
 	vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr),
 				 mem_flags, dma_handle);
 	if (!vaddr)
@@ -1941,6 +1945,7 @@
 
 	dev_dbg(&rhdev->dev, "usb %s%s\n",
 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
 	if (!hcd->driver->bus_resume)
 		return -ENOENT;
 	if (hcd->state == HC_STATE_RUNNING)
@@ -1994,8 +1999,10 @@
 	unsigned long flags;
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
-	if (hcd->rh_registered)
+	if (hcd->rh_registered) {
+		set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
 		queue_work(pm_wq, &hcd->wakeup_work);
+	}
 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
@@ -2063,8 +2070,7 @@
 	 */
 	local_irq_save(flags);
 
-	if (unlikely(hcd->state == HC_STATE_HALT ||
-		     !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
 		rc = IRQ_NONE;
 	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
 		rc = IRQ_NONE;
@@ -2079,6 +2085,7 @@
 	local_irq_restore(flags);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(usb_hcd_irq);
 
 /*-------------------------------------------------------------------------*/
 
@@ -2098,7 +2105,7 @@
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
 	if (hcd->rh_registered) {
-		hcd->poll_rh = 0;
+		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
 		/* make khubd clean up old urbs and devices */
 		usb_set_device_state (hcd->self.root_hub,
@@ -2217,6 +2224,7 @@
 		retval = -ENOMEM;
 		goto err_allocate_root_hub;
 	}
+	hcd->self.root_hub = rhdev;
 
 	switch (hcd->driver->flags & HCD_MASK) {
 	case HCD_USB11:
@@ -2229,9 +2237,8 @@
 		rhdev->speed = USB_SPEED_SUPER;
 		break;
 	default:
-		goto err_allocate_root_hub;
+		goto err_set_rh_speed;
 	}
-	hcd->self.root_hub = rhdev;
 
 	/* wakeup flag init defaults to "everything works" for root hubs,
 	 * but drivers can override it in reset() if needed, along with
@@ -2246,6 +2253,7 @@
 		dev_err(hcd->self.controller, "can't setup\n");
 		goto err_hcd_driver_setup;
 	}
+	hcd->rh_pollable = 1;
 
 	/* NOTE: root hub and controller capabilities may not be the same */
 	if (device_can_wakeup(hcd->self.controller)
@@ -2300,23 +2308,38 @@
 		       retval);
 		goto error_create_attr_group;
 	}
-	if (hcd->uses_new_polling && hcd->poll_rh)
+	if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
 		usb_hcd_poll_rh_status(hcd);
 	return retval;
 
 error_create_attr_group:
+	if (HC_IS_RUNNING(hcd->state))
+		hcd->state = HC_STATE_QUIESCING;
+	spin_lock_irq(&hcd_root_hub_lock);
+	hcd->rh_registered = 0;
+	spin_unlock_irq(&hcd_root_hub_lock);
+
+#ifdef CONFIG_USB_SUSPEND
+	cancel_work_sync(&hcd->wakeup_work);
+#endif
 	mutex_lock(&usb_bus_list_lock);
-	usb_disconnect(&hcd->self.root_hub);
+	usb_disconnect(&rhdev);		/* Sets rhdev to NULL */
 	mutex_unlock(&usb_bus_list_lock);
 err_register_root_hub:
+	hcd->rh_pollable = 0;
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	del_timer_sync(&hcd->rh_timer);
 	hcd->driver->stop(hcd);
+	hcd->state = HC_STATE_HALT;
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	del_timer_sync(&hcd->rh_timer);
 err_hcd_driver_start:
 	if (hcd->irq >= 0)
 		free_irq(irqnum, hcd);
 err_request_irq:
 err_hcd_driver_setup:
-	hcd->self.root_hub = NULL;
-	usb_put_dev(rhdev);
+err_set_rh_speed:
+	usb_put_dev(hcd->self.root_hub);
 err_allocate_root_hub:
 	usb_deregister_bus(&hcd->self);
 err_register_bus:
@@ -2335,8 +2358,13 @@
  */
 void usb_remove_hcd(struct usb_hcd *hcd)
 {
+	struct usb_device *rhdev = hcd->self.root_hub;
+
 	dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
 
+	usb_get_dev(rhdev);
+	sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
+
 	if (HC_IS_RUNNING (hcd->state))
 		hcd->state = HC_STATE_QUIESCING;
 
@@ -2349,19 +2377,30 @@
 	cancel_work_sync(&hcd->wakeup_work);
 #endif
 
-	sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
 	mutex_lock(&usb_bus_list_lock);
-	usb_disconnect(&hcd->self.root_hub);
+	usb_disconnect(&rhdev);		/* Sets rhdev to NULL */
 	mutex_unlock(&usb_bus_list_lock);
 
+	/* Prevent any more root-hub status calls from the timer.
+	 * The HCD might still restart the timer (if a port status change
+	 * interrupt occurs), but usb_hcd_poll_rh_status() won't invoke
+	 * the hub_status_data() callback.
+	 */
+	hcd->rh_pollable = 0;
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	del_timer_sync(&hcd->rh_timer);
+
 	hcd->driver->stop(hcd);
 	hcd->state = HC_STATE_HALT;
 
-	hcd->poll_rh = 0;
+	/* In case the HCD restarted the timer, stop it again. */
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	del_timer_sync(&hcd->rh_timer);
 
 	if (hcd->irq >= 0)
 		free_irq(hcd->irq, hcd);
+
+	usb_put_dev(hcd->self.root_hub);
 	usb_deregister_bus(&hcd->self);
 	hcd_buffer_destroy(hcd);
 }
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 70cccc7..84c18971 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -20,6 +20,7 @@
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/usb/hcd.h>
+#include <linux/usb/quirks.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
@@ -1294,6 +1295,7 @@
 	return -ENODEV;
 }
 
+/* No BKL needed */
 static int
 hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 {
@@ -1801,7 +1803,6 @@
 	pm_runtime_set_active(&udev->dev);
 	pm_runtime_enable(&udev->dev);
 
-	usb_detect_quirks(udev);
 	err = usb_enumerate_device(udev);	/* Read descriptors */
 	if (err < 0)
 		goto fail;
@@ -2880,7 +2881,9 @@
 	}
 
 	retval = 0;
-
+	/* notify HCD that we have a device connected and addressed */
+	if (hcd->driver->update_device)
+		hcd->driver->update_device(hcd, udev);
 fail:
 	if (retval) {
 		hub_port_disable(hub, port1, 0);
@@ -3111,6 +3114,10 @@
 		if (status < 0)
 			goto loop;
 
+		usb_detect_quirks(udev);
+		if (udev->quirks & USB_QUIRK_DELAY_INIT)
+			msleep(1000);
+
 		/* consecutive bus-powered hubs aren't reliable; they can
 		 * violate the voltage drop budget.  if the new child has
 		 * a "powered" LED, users should notice we didn't enable it
@@ -3463,7 +3470,7 @@
 	.reset_resume =	hub_reset_resume,
 	.pre_reset =	hub_pre_reset,
 	.post_reset =	hub_post_reset,
-	.ioctl =	hub_ioctl,
+	.unlocked_ioctl = hub_ioctl,
 	.id_table =	hub_id_table,
 	.supports_autosuspend =	1,
 };
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 1a27618..095fa53 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -265,13 +265,9 @@
 		return -EINVAL;
 	}
 
-	lock_kernel();
-
 	if (usbfs_mount && usbfs_mount->mnt_sb)
 		update_sb(usbfs_mount->mnt_sb);
 
-	unlock_kernel();
-
 	return 0;
 }
 
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index db99c08..25719da 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -38,6 +38,9 @@
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Logitech Harmony 700-series */
+	{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
+
 	/* Philips PSC805 audio device */
 	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
 
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 7c05555..419e6b3 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -137,6 +137,16 @@
 }
 EXPORT_SYMBOL_GPL(usb_anchor_urb);
 
+/* Callers must hold anchor->lock */
+static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
+{
+	urb->anchor = NULL;
+	list_del(&urb->anchor_list);
+	usb_put_urb(urb);
+	if (list_empty(&anchor->urb_list))
+		wake_up(&anchor->wait);
+}
+
 /**
  * usb_unanchor_urb - unanchors an URB
  * @urb: pointer to the urb to anchor
@@ -156,17 +166,14 @@
 		return;
 
 	spin_lock_irqsave(&anchor->lock, flags);
-	if (unlikely(anchor != urb->anchor)) {
-		/* we've lost the race to another thread */
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		return;
-	}
-	urb->anchor = NULL;
-	list_del(&urb->anchor_list);
+	/*
+	 * At this point, we could be competing with another thread which
+	 * has the same intention. To protect the urb from being unanchored
+	 * twice, only the winner of the race gets the job.
+	 */
+	if (likely(anchor == urb->anchor))
+		__usb_unanchor_urb(urb, anchor);
 	spin_unlock_irqrestore(&anchor->lock, flags);
-	usb_put_urb(urb);
-	if (list_empty(&anchor->urb_list))
-		wake_up(&anchor->wait);
 }
 EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
@@ -749,20 +756,11 @@
 void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
 {
 	struct urb *victim;
-	unsigned long flags;
 
-	spin_lock_irqsave(&anchor->lock, flags);
-	while (!list_empty(&anchor->urb_list)) {
-		victim = list_entry(anchor->urb_list.prev, struct urb,
-				    anchor_list);
-		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		/* this will unanchor the URB */
+	while ((victim = usb_get_from_anchor(anchor)) != NULL) {
 		usb_unlink_urb(victim);
 		usb_put_urb(victim);
-		spin_lock_irqsave(&anchor->lock, flags);
 	}
-	spin_unlock_irqrestore(&anchor->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
 
@@ -799,12 +797,11 @@
 		victim = list_entry(anchor->urb_list.next, struct urb,
 				    anchor_list);
 		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		usb_unanchor_urb(victim);
+		__usb_unanchor_urb(victim, anchor);
 	} else {
-		spin_unlock_irqrestore(&anchor->lock, flags);
 		victim = NULL;
 	}
+	spin_unlock_irqrestore(&anchor->lock, flags);
 
 	return victim;
 }
@@ -826,12 +823,7 @@
 	while (!list_empty(&anchor->urb_list)) {
 		victim = list_entry(anchor->urb_list.prev, struct urb,
 				    anchor_list);
-		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		/* this may free the URB */
-		usb_unanchor_urb(victim);
-		usb_put_urb(victim);
-		spin_lock_irqsave(&anchor->lock, flags);
+		__usb_unanchor_urb(victim, anchor);
 	}
 	spin_unlock_irqrestore(&anchor->lock, flags);
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 5ae14f6..fdd4130 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -317,10 +317,6 @@
 	.restore =	usb_dev_restore,
 };
 
-#else
-
-#define usb_device_pm_ops	(*(struct dev_pm_ops *) NULL)
-
 #endif	/* CONFIG_PM */
 
 
@@ -338,7 +334,9 @@
 	.release =	usb_release_dev,
 	.uevent =	usb_dev_uevent,
 	.devnode = 	usb_devnode,
+#ifdef CONFIG_PM
 	.pm =		&usb_device_pm_ops,
+#endif
 };
 
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 591ae9f..cd27f9b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -714,6 +714,7 @@
 config USB_FUNCTIONFS
 	tristate "Function Filesystem (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
 	help
 	  The Function Filesystem (FunctioFS) lets one create USB
 	  composite functions in user space in the same way as GadgetFS
@@ -722,31 +723,31 @@
 	  implemented in kernel space (for instance Ethernet, serial or
 	  mass storage) and other are implemented in user space.
 
+	  If you say "y" or "m" here you will be able what kind of
+	  configurations the gadget will provide.
+
 	  Say "y" to link the driver statically, or "m" to build
 	  a dynamically linked module called "g_ffs".
 
 config USB_FUNCTIONFS_ETH
-	bool "Include CDC ECM (Ethernet) function"
+	bool "Include configuration with CDC ECM (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion)
-	  Filesystem.  If you also say "y" to the RNDIS query below the
-	  gadget will have two configurations.
+	  Include a configuration with CDC ECM funcion (Ethernet) and the
+	  Funcion Filesystem.
 
 config USB_FUNCTIONFS_RNDIS
-	bool "Include RNDIS (Ethernet) function"
+	bool "Include configuration with RNDIS (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include an RNDIS (Ethernet) funcion in the Funcion Filesystem.
-	  If you also say "y" to the CDC ECM query above the gadget will
-	  have two configurations.
+	  Include a configuration with RNDIS funcion (Ethernet) and the Filesystem.
 
 config USB_FUNCTIONFS_GENERIC
 	bool "Include 'pure' configuration"
-	depends on USB_FUNCTIONFS && (USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
+	depends on USB_FUNCTIONFS
 	help
-	  Include a configuration with FunctionFS and no Ethernet
-	  configuration.
+	  Include a configuration with the Function Filesystem alone with
+	  no Ethernet interface.
 
 config USB_FILE_STORAGE
 	tristate "File-backed Storage Gadget"
@@ -863,6 +864,7 @@
 config USB_G_MULTI
 	tristate "Multifunction Composite Gadget (EXPERIMENTAL)"
 	depends on BLOCK && NET
+	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
 	help
 	  The Multifunction Composite Gadget provides Ethernet (RNDIS
 	  and/or CDC Ethernet), mass storage and ACM serial link
@@ -913,6 +915,34 @@
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_hid".
 
+config USB_G_DBGP
+	tristate "EHCI Debug Device Gadget"
+	help
+	  This gadget emulates an EHCI Debug device. This is useful when you want
+	  to interact with an EHCI Debug Port.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_dbgp".
+
+if USB_G_DBGP
+choice
+	prompt "EHCI Debug Device mode"
+	default USB_G_DBGP_SERIAL
+
+config USB_G_DBGP_PRINTK
+	depends on USB_G_DBGP
+	bool "printk"
+	help
+	  Directly printk() received data. No interaction.
+
+config USB_G_DBGP_SERIAL
+	depends on USB_G_DBGP
+	bool "serial"
+	help
+	  Userland can interact using /dev/ttyGSxxx.
+endchoice
+endif
+
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
 config USB_G_WEBCAM
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 9bcde11..27283df 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -44,6 +44,7 @@
 g_cdc-objs			:= cdc2.o
 g_multi-objs			:= multi.o
 g_hid-objs			:= hid.o
+g_dbgp-objs			:= dbgp.o
 g_nokia-objs			:= nokia.o
 g_webcam-objs			:= webcam.o
 
@@ -52,7 +53,6 @@
 obj-$(CONFIG_USB_ETH)		+= g_ether.o
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
-obj-$(CONFIG_USB_ETH_FUNCTIONFS)	+= g_eth_ffs.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
@@ -60,6 +60,7 @@
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
 obj-$(CONFIG_USB_G_HID)		+= g_hid.o
+obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index a62af7b..b744ccd 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -89,7 +89,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init audio_do_config(struct usb_configuration *c)
+static int __ref audio_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -113,7 +113,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init audio_bind(struct usb_composite_dev *cdev)
+static int __ref audio_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	int			status;
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 928137d..1f5ba2f 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -129,7 +129,7 @@
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
-static int __init cdc_do_config(struct usb_configuration *c)
+static int __ref cdc_do_config(struct usb_configuration *c)
 {
 	int	status;
 
@@ -159,7 +159,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init cdc_bind(struct usb_composite_dev *cdev)
+static int __ref cdc_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 391d169..e483f80 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -673,20 +673,83 @@
  * string IDs.  Drivers for functions, configurations, or gadgets will
  * then store that ID in the appropriate descriptors and string table.
  *
- * All string identifier should be allocated using this routine, to
- * ensure that for example different functions don't wrongly assign
- * different meanings to the same identifier.
+ * All string identifier should be allocated using this,
+ * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
+ * that for example different functions don't wrongly assign different
+ * meanings to the same identifier.
  */
 int usb_string_id(struct usb_composite_dev *cdev)
 {
 	if (cdev->next_string_id < 254) {
-		/* string id 0 is reserved */
+		/* string id 0 is reserved by USB spec for list of
+		 * supported languages */
+		/* 255 reserved as well? -- mina86 */
 		cdev->next_string_id++;
 		return cdev->next_string_id;
 	}
 	return -ENODEV;
 }
 
+/**
+ * usb_string_ids() - allocate unused string IDs in batch
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * @str: an array of usb_string objects to assign numbers to
+ * Context: single threaded during gadget setup
+ *
+ * @usb_string_ids() is called from bind() callbacks to allocate
+ * string IDs.  Drivers for functions, configurations, or gadgets will
+ * then copy IDs from the string table to the appropriate descriptors
+ * and string table for other languages.
+ *
+ * All string identifier should be allocated using this,
+ * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
+ * example different functions don't wrongly assign different meanings
+ * to the same identifier.
+ */
+int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
+{
+	int next = cdev->next_string_id;
+
+	for (; str->s; ++str) {
+		if (unlikely(next >= 254))
+			return -ENODEV;
+		str->id = ++next;
+	}
+
+	cdev->next_string_id = next;
+
+	return 0;
+}
+
+/**
+ * usb_string_ids_n() - allocate unused string IDs in batch
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * @n: number of string IDs to allocate
+ * Context: single threaded during gadget setup
+ *
+ * Returns the first requested ID.  This ID and next @n-1 IDs are now
+ * valid IDs.  At least providind that @n is non zore because if it
+ * is, returns last requested ID which is now very useful information.
+ *
+ * @usb_string_ids_n() is called from bind() callbacks to allocate
+ * string IDs.  Drivers for functions, configurations, or gadgets will
+ * then store that ID in the appropriate descriptors and string table.
+ *
+ * All string identifier should be allocated using this,
+ * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
+ * example different functions don't wrongly assign different meanings
+ * to the same identifier.
+ */
+int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
+{
+	unsigned next = c->next_string_id;
+	if (unlikely(n > 254 || (unsigned)next + n > 254))
+		return -ENODEV;
+	c->next_string_id += n;
+	return next + 1;
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
@@ -893,6 +956,8 @@
 	spin_lock_irqsave(&cdev->lock, flags);
 	if (cdev->config)
 		reset_config(cdev);
+	if (composite->disconnect)
+		composite->disconnect(cdev);
 	spin_unlock_irqrestore(&cdev->lock, flags);
 }
 
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c
new file mode 100644
index 0000000..0ed50a2
--- /dev/null
+++ b/drivers/usb/gadget/dbgp.c
@@ -0,0 +1,434 @@
+/*
+ * dbgp.c -- EHCI Debug Port device gadget
+ *
+ * Copyright (C) 2010 Stephane Duverger
+ *
+ * Released under the GPLv2.
+ *
+ */
+
+/* verbose messages */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* See comments in "zero.c" */
+#include "epautoconf.c"
+
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+#include "u_serial.c"
+#endif
+
+#define DRIVER_VENDOR_ID	0x0525 /* NetChip */
+#define DRIVER_PRODUCT_ID	0xc0de /* undefined */
+
+#define USB_DEBUG_MAX_PACKET_SIZE     8
+#define DBGP_REQ_EP0_LEN              128
+#define DBGP_REQ_LEN                  512
+
+static struct dbgp {
+	struct usb_gadget  *gadget;
+	struct usb_request *req;
+	struct usb_ep      *i_ep;
+	struct usb_ep      *o_ep;
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+	struct gserial     *serial;
+#endif
+} dbgp;
+
+static struct usb_device_descriptor device_desc = {
+	.bLength = sizeof device_desc,
+	.bDescriptorType = USB_DT_DEVICE,
+	.bcdUSB = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass =	USB_CLASS_VENDOR_SPEC,
+	.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
+	.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+	.bNumConfigurations = 1,
+};
+
+static struct usb_debug_descriptor dbg_desc = {
+	.bLength = sizeof dbg_desc,
+	.bDescriptorType = USB_DT_DEBUG,
+};
+
+static struct usb_endpoint_descriptor i_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	.bEndpointAddress = USB_DIR_IN,
+};
+
+static struct usb_endpoint_descriptor o_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	.bEndpointAddress = USB_DIR_OUT,
+};
+
+#ifdef CONFIG_USB_G_DBGP_PRINTK
+static int dbgp_consume(char *buf, unsigned len)
+{
+	char c;
+
+	if (!len)
+		return 0;
+
+	c = buf[len-1];
+	if (c != 0)
+		buf[len-1] = 0;
+
+	printk(KERN_NOTICE "%s%c", buf, c);
+	return 0;
+}
+
+static void __disable_ep(struct usb_ep *ep)
+{
+	if (ep && ep->driver_data == dbgp.gadget) {
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+	}
+}
+
+static void dbgp_disable_ep(void)
+{
+	__disable_ep(dbgp.i_ep);
+	__disable_ep(dbgp.o_ep);
+}
+
+static void dbgp_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	int stp;
+	int err = 0;
+	int status = req->status;
+
+	if (ep == dbgp.i_ep) {
+		stp = 1;
+		goto fail;
+	}
+
+	if (status != 0) {
+		stp = 2;
+		goto release_req;
+	}
+
+	dbgp_consume(req->buf, req->actual);
+
+	req->length = DBGP_REQ_LEN;
+	err = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (err < 0) {
+		stp = 3;
+		goto release_req;
+	}
+
+	return;
+
+release_req:
+	kfree(req->buf);
+	usb_ep_free_request(dbgp.o_ep, req);
+	dbgp_disable_ep();
+fail:
+	dev_dbg(&dbgp.gadget->dev,
+		"complete: failure (%d:%d) ==> %d\n", stp, err, status);
+}
+
+static int dbgp_enable_ep_req(struct usb_ep *ep)
+{
+	int err, stp;
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!req) {
+		err = -ENOMEM;
+		stp = 1;
+		goto fail_1;
+	}
+
+	req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
+	if (!req->buf) {
+		err = -ENOMEM;
+		stp = 2;
+		goto fail_2;
+	}
+
+	req->complete = dbgp_complete;
+	req->length = DBGP_REQ_LEN;
+	err = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (err < 0) {
+		stp = 3;
+		goto fail_3;
+	}
+
+	return 0;
+
+fail_3:
+	kfree(req->buf);
+fail_2:
+	usb_ep_free_request(dbgp.o_ep, req);
+fail_1:
+	dev_dbg(&dbgp.gadget->dev,
+		"enable ep req: failure (%d:%d)\n", stp, err);
+	return err;
+}
+
+static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
+{
+	int err = usb_ep_enable(ep, desc);
+	ep->driver_data = dbgp.gadget;
+	return err;
+}
+
+static int dbgp_enable_ep(void)
+{
+	int err, stp;
+
+	err = __enable_ep(dbgp.i_ep, &i_desc);
+	if (err < 0) {
+		stp = 1;
+		goto fail_1;
+	}
+
+	err = __enable_ep(dbgp.o_ep, &o_desc);
+	if (err < 0) {
+		stp = 2;
+		goto fail_2;
+	}
+
+	err = dbgp_enable_ep_req(dbgp.o_ep);
+	if (err < 0) {
+		stp = 3;
+		goto fail_3;
+	}
+
+	return 0;
+
+fail_3:
+	__disable_ep(dbgp.o_ep);
+fail_2:
+	__disable_ep(dbgp.i_ep);
+fail_1:
+	dev_dbg(&dbgp.gadget->dev, "enable ep: failure (%d:%d)\n", stp, err);
+	return err;
+}
+#endif
+
+static void dbgp_disconnect(struct usb_gadget *gadget)
+{
+#ifdef CONFIG_USB_G_DBGP_PRINTK
+	dbgp_disable_ep();
+#else
+	gserial_disconnect(dbgp.serial);
+#endif
+}
+
+static void dbgp_unbind(struct usb_gadget *gadget)
+{
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+	kfree(dbgp.serial);
+#endif
+	if (dbgp.req) {
+		kfree(dbgp.req->buf);
+		usb_ep_free_request(gadget->ep0, dbgp.req);
+	}
+
+	gadget->ep0->driver_data = NULL;
+}
+
+static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
+{
+	int stp;
+
+	usb_ep_autoconfig_reset(gadget);
+
+	dbgp.i_ep = usb_ep_autoconfig(gadget, &i_desc);
+	if (!dbgp.i_ep) {
+		stp = 1;
+		goto fail_1;
+	}
+
+	dbgp.i_ep->driver_data = gadget;
+	i_desc.wMaxPacketSize =
+		__constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+
+	dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
+	if (!dbgp.o_ep) {
+		dbgp.i_ep->driver_data = NULL;
+		stp = 2;
+		goto fail_2;
+	}
+
+	dbgp.o_ep->driver_data = gadget;
+	o_desc.wMaxPacketSize =
+		__constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+
+	dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress & 0x7f;
+	dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress & 0x7f;
+
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+	dbgp.serial->in = dbgp.i_ep;
+	dbgp.serial->out = dbgp.o_ep;
+
+	dbgp.serial->in_desc = &i_desc;
+	dbgp.serial->out_desc = &o_desc;
+
+	if (gserial_setup(gadget, 1) < 0) {
+		stp = 3;
+		goto fail_3;
+	}
+
+	return 0;
+
+fail_3:
+	dbgp.o_ep->driver_data = NULL;
+#else
+	return 0;
+#endif
+fail_2:
+	dbgp.i_ep->driver_data = NULL;
+fail_1:
+	dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
+	return -ENODEV;
+}
+
+static int __init dbgp_bind(struct usb_gadget *gadget)
+{
+	int err, stp;
+
+	dbgp.gadget = gadget;
+
+	dbgp.req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+	if (!dbgp.req) {
+		err = -ENOMEM;
+		stp = 1;
+		goto fail;
+	}
+
+	dbgp.req->buf = kmalloc(DBGP_REQ_EP0_LEN, GFP_KERNEL);
+	if (!dbgp.req->buf) {
+		err = -ENOMEM;
+		stp = 2;
+		goto fail;
+	}
+
+	dbgp.req->length = DBGP_REQ_EP0_LEN;
+	gadget->ep0->driver_data = gadget;
+
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+	dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
+	if (!dbgp.serial) {
+		stp = 3;
+		err = -ENOMEM;
+		goto fail;
+	}
+#endif
+	err = dbgp_configure_endpoints(gadget);
+	if (err < 0) {
+		stp = 4;
+		goto fail;
+	}
+
+	dev_dbg(&dbgp.gadget->dev, "bind: success\n");
+	return 0;
+
+fail:
+	dev_dbg(&gadget->dev, "bind: failure (%d:%d)\n", stp, err);
+	dbgp_unbind(gadget);
+	return err;
+}
+
+static void dbgp_setup_complete(struct usb_ep *ep,
+				struct usb_request *req)
+{
+	dev_dbg(&dbgp.gadget->dev, "setup complete: %d, %d/%d\n",
+		req->status, req->actual, req->length);
+}
+
+static int dbgp_setup(struct usb_gadget *gadget,
+		      const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_request *req = dbgp.req;
+	u8 request = ctrl->bRequest;
+	u16 value = le16_to_cpu(ctrl->wValue);
+	u16 length = le16_to_cpu(ctrl->wLength);
+	int err = 0;
+	void *data;
+	u16 len;
+
+	gadget->ep0->driver_data = gadget;
+
+	if (request == USB_REQ_GET_DESCRIPTOR) {
+		switch (value>>8) {
+		case USB_DT_DEVICE:
+			dev_dbg(&dbgp.gadget->dev, "setup: desc device\n");
+			len = sizeof device_desc;
+			data = &device_desc;
+			break;
+		case USB_DT_DEBUG:
+			dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n");
+			len = sizeof dbg_desc;
+			data = &dbg_desc;
+			break;
+		default:
+			goto fail;
+		}
+	} else if (request == USB_REQ_SET_FEATURE &&
+		   value == USB_DEVICE_DEBUG_MODE) {
+		len = 0;
+		data = NULL;
+		dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n");
+#ifdef CONFIG_USB_G_DBGP_PRINTK
+		err = dbgp_enable_ep();
+#else
+		err = gserial_connect(dbgp.serial, 0);
+#endif
+		if (err < 0)
+			goto fail;
+	} else
+		goto fail;
+
+	if (len >= 0) {
+		req->length = min(length, len);
+		req->zero = len < req->length;
+		if (data && req->length)
+			memcpy(req->buf, data, req->length);
+
+		req->complete = dbgp_setup_complete;
+		return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+	}
+
+fail:
+	dev_dbg(&dbgp.gadget->dev,
+		"setup: failure req %x v %x\n", request, value);
+	return err;
+}
+
+static struct usb_gadget_driver dbgp_driver = {
+	.function = "dbgp",
+	.speed = USB_SPEED_HIGH,
+	.bind = dbgp_bind,
+	.unbind = dbgp_unbind,
+	.setup = dbgp_setup,
+	.disconnect = dbgp_disconnect,
+	.driver	= {
+		.owner = THIS_MODULE,
+		.name = "dbgp"
+	},
+};
+
+static int __init dbgp_init(void)
+{
+	return usb_gadget_register_driver(&dbgp_driver);
+}
+
+static void __exit dbgp_exit(void)
+{
+	usb_gadget_unregister_driver(&dbgp_driver);
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+	gserial_cleanup();
+#endif
+}
+
+MODULE_AUTHOR("Stephane Duverger");
+MODULE_LICENSE("GPL");
+module_init(dbgp_init);
+module_exit(dbgp_exit);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4f9e578..dc65462 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1542,7 +1542,7 @@
 	dum = hcd_to_dummy (hcd);
 
 	spin_lock_irqsave (&dum->lock, flags);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		goto done;
 
 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@@ -1588,7 +1588,7 @@
 	int		retval = 0;
 	unsigned long	flags;
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		return -ETIMEDOUT;
 
 	dum = hcd_to_dummy (hcd);
@@ -1739,7 +1739,7 @@
 	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq (&dum->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 	} else {
 		dum->rh_state = DUMMY_RH_RUNNING;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 400f8037..114fa02 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -237,7 +237,7 @@
  * the first one present.  That's to make Microsoft's drivers happy,
  * and to follow DOCSIS 1.0 (cable modem standard).
  */
-static int __init rndis_do_config(struct usb_configuration *c)
+static int __ref rndis_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -270,7 +270,7 @@
 /*
  * We _always_ have an ECM, CDC Subset, or EEM configuration.
  */
-static int __init eth_do_config(struct usb_configuration *c)
+static int __ref eth_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -297,7 +297,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init eth_bind(struct usb_composite_dev *cdev)
+static int __ref eth_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 2aaa0f7..e4f5950 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -714,9 +714,7 @@
 		struct ffs_function *func = ffs->func;
 		ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
 	} else if (gadget->ops->ioctl) {
-		lock_kernel();
 		ret = gadget->ops->ioctl(gadget, code, value);
-		unlock_kernel();
 	} else {
 		ret = -ENOTTY;
 	}
@@ -1377,7 +1375,8 @@
 
 static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
 {
-	unsigned i, count;
+	struct usb_gadget_strings **lang;
+	int first_id;
 
 	ENTER();
 
@@ -1385,7 +1384,9 @@
 		 || test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
 		return -EBADFD;
 
-	ffs_data_get(ffs);
+	first_id = usb_string_ids_n(cdev, ffs->strings_count);
+	if (unlikely(first_id < 0))
+		return first_id;
 
 	ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
 	if (unlikely(!ffs->ep0req))
@@ -1393,25 +1394,16 @@
 	ffs->ep0req->complete = ffs_ep0_complete;
 	ffs->ep0req->context = ffs;
 
-	/* Get strings identifiers */
-	for (count = ffs->strings_count, i = 0; i < count; ++i) {
-		struct usb_gadget_strings **lang;
-
-		int id = usb_string_id(cdev);
-		if (unlikely(id < 0)) {
-			usb_ep_free_request(cdev->gadget->ep0, ffs->ep0req);
-			ffs->ep0req = NULL;
-			return id;
-		}
-
-		lang = ffs->stringtabs;
-		do {
-			(*lang)->strings[i].id = id;
-			++lang;
-		} while (*lang);
+	lang = ffs->stringtabs;
+	for (lang = ffs->stringtabs; *lang; ++lang) {
+		struct usb_string *str = (*lang)->strings;
+		int id = first_id;
+		for (; str->s; ++id, ++str)
+			str->id = id;
 	}
 
 	ffs->gadget = cdev->gadget;
+	ffs_data_get(ffs);
 	return 0;
 }
 
@@ -1480,9 +1472,9 @@
 }
 
 
-static int functionfs_add(struct usb_composite_dev *cdev,
-			  struct usb_configuration *c,
-			  struct ffs_data *ffs)
+static int functionfs_bind_config(struct usb_composite_dev *cdev,
+				  struct usb_configuration *c,
+				  struct ffs_data *ffs)
 {
 	struct ffs_function *func;
 	int ret;
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 1e00ff9..53e1202 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -142,7 +142,7 @@
 static ssize_t f_hidg_read(struct file *file, char __user *buffer,
 			size_t count, loff_t *ptr)
 {
-	struct f_hidg	*hidg     = (struct f_hidg *)file->private_data;
+	struct f_hidg	*hidg     = file->private_data;
 	char		*tmp_buff = NULL;
 	unsigned long	flags;
 
@@ -200,7 +200,7 @@
 static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
 			    size_t count, loff_t *offp)
 {
-	struct f_hidg *hidg  = (struct f_hidg *)file->private_data;
+	struct f_hidg *hidg  = file->private_data;
 	ssize_t status = -ENOMEM;
 
 	if (!access_ok(VERIFY_READ, buffer, count))
@@ -257,7 +257,7 @@
 
 static unsigned int f_hidg_poll(struct file *file, poll_table *wait)
 {
-	struct f_hidg	*hidg  = (struct f_hidg *)file->private_data;
+	struct f_hidg	*hidg  = file->private_data;
 	unsigned int	ret = 0;
 
 	poll_wait(file, &hidg->read_queue, wait);
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index e91d1b1..4322587 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -324,7 +324,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init loopback_bind_config(struct usb_configuration *c)
+static int __ref loopback_bind_config(struct usb_configuration *c)
 {
 	struct f_loopback	*loop;
 	int			status;
@@ -346,7 +346,7 @@
 	return status;
 }
 
-static struct usb_configuration loopback_driver = {
+static  struct usb_configuration loopback_driver = {
 	.label		= "loopback",
 	.strings	= loopback_strings,
 	.bind		= loopback_bind_config,
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4ce899c..32cce02 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -316,6 +316,27 @@
 /*-------------------------------------------------------------------------*/
 
 struct fsg_dev;
+struct fsg_common;
+
+/* FSF callback functions */
+struct fsg_operations {
+	/* Callback function to call when thread exits.  If no
+	 * callback is set or it returns value lower then zero MSF
+	 * will force eject all LUNs it operates on (including those
+	 * marked as non-removable or with prevent_medium_removal flag
+	 * set). */
+	int (*thread_exits)(struct fsg_common *common);
+
+	/* Called prior to ejection.  Negative return means error,
+	 * zero means to continue with ejection, positive means not to
+	 * eject. */
+	int (*pre_eject)(struct fsg_common *common,
+			 struct fsg_lun *lun, int num);
+	/* Called after ejection.  Negative return means error, zero
+	 * or positive is just a success. */
+	int (*post_eject)(struct fsg_common *common,
+			  struct fsg_lun *lun, int num);
+};
 
 
 /* Data shared by all the FSG instances. */
@@ -333,7 +354,6 @@
 	struct usb_ep		*ep0;		/* Copy of gadget->ep0 */
 	struct usb_request	*ep0req;	/* Copy of cdev->req */
 	unsigned int		ep0_req_tag;
-	const char		*ep0req_name;
 
 	struct fsg_buffhd	*next_buffhd_to_fill;
 	struct fsg_buffhd	*next_buffhd_to_drain;
@@ -369,8 +389,8 @@
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
 
-	/* Callback function to call when thread exits. */
-	int			(*thread_exits)(struct fsg_common *common);
+	/* Callback functions. */
+	const struct fsg_operations	*ops;
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -394,12 +414,8 @@
 	const char		*lun_name_format;
 	const char		*thread_name;
 
-	/* Callback function to call when thread exits.  If no
-	 * callback is set or it returns value lower then zero MSF
-	 * will force eject all LUNs it operates on (including those
-	 * marked as non-removable or with prevent_medium_removal flag
-	 * set). */
-	int			(*thread_exits)(struct fsg_common *common);
+	/* Callback functions. */
+	const struct fsg_operations	*ops;
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -435,6 +451,7 @@
 	if (common->fsg)
 		return 1;
 	ERROR(common, "common->fsg is NULL in %s at %u\n", func, line);
+	WARN_ON(1);
 	return 0;
 }
 
@@ -623,8 +640,6 @@
 
 		/* Respond with data/status */
 		req->length = min((u16)1, w_length);
-		fsg->common->ep0req_name =
-			ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out";
 		return ep0_queue(fsg->common);
 	}
 
@@ -1395,43 +1410,55 @@
 	} else if (!curlun->removable) {
 		curlun->sense_data = SS_INVALID_COMMAND;
 		return -EINVAL;
-	}
-
-	loej = common->cmnd[4] & 0x02;
-	start = common->cmnd[4] & 0x01;
-
-	/* eject code from file_storage.c:do_start_stop() */
-
-	if ((common->cmnd[1] & ~0x01) != 0 ||	  /* Mask away Immed */
-		(common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
+	} else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */
+		   (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
 		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return -EINVAL;
 	}
 
-	if (!start) {
-		/* Are we allowed to unload the media? */
-		if (curlun->prevent_medium_removal) {
-			LDBG(curlun, "unload attempt prevented\n");
-			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-			return -EINVAL;
-		}
-		if (loej) {	/* Simulate an unload/eject */
-			up_read(&common->filesem);
-			down_write(&common->filesem);
-			fsg_lun_close(curlun);
-			up_write(&common->filesem);
-			down_read(&common->filesem);
-		}
-	} else {
+	loej  = common->cmnd[4] & 0x02;
+	start = common->cmnd[4] & 0x01;
 
-		/* Our emulation doesn't support mounting; the medium is
-		 * available for use as soon as it is loaded. */
+	/* Our emulation doesn't support mounting; the medium is
+	 * available for use as soon as it is loaded. */
+	if (start) {
 		if (!fsg_lun_is_open(curlun)) {
 			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
 			return -EINVAL;
 		}
+		return 0;
 	}
-	return 0;
+
+	/* Are we allowed to unload the media? */
+	if (curlun->prevent_medium_removal) {
+		LDBG(curlun, "unload attempt prevented\n");
+		curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
+		return -EINVAL;
+	}
+
+	if (!loej)
+		return 0;
+
+	/* Simulate an unload/eject */
+	if (common->ops && common->ops->pre_eject) {
+		int r = common->ops->pre_eject(common, curlun,
+					       curlun - common->luns);
+		if (unlikely(r < 0))
+			return r;
+		else if (r)
+			return 0;
+	}
+
+	up_read(&common->filesem);
+	down_write(&common->filesem);
+	fsg_lun_close(curlun);
+	up_write(&common->filesem);
+	down_read(&common->filesem);
+
+	return common->ops && common->ops->post_eject
+		? min(0, common->ops->post_eject(common, curlun,
+						 curlun - common->luns))
+		: 0;
 }
 
 
@@ -2610,7 +2637,8 @@
 	common->thread_task = NULL;
 	spin_unlock_irq(&common->lock);
 
-	if (!common->thread_exits || common->thread_exits(common) < 0) {
+	if (!common->ops || !common->ops->thread_exits
+	 || common->ops->thread_exits(common) < 0) {
 		struct fsg_lun *curlun = common->luns;
 		unsigned i = common->nluns;
 
@@ -2686,6 +2714,7 @@
 		common->free_storage_on_release = 0;
 	}
 
+	common->ops = cfg->ops;
 	common->private_data = cfg->private_data;
 
 	common->gadget = gadget;
@@ -2807,7 +2836,6 @@
 
 
 	/* Tell the thread to start working */
-	common->thread_exits = cfg->thread_exits;
 	common->thread_task =
 		kthread_create(fsg_main_thread, common,
 			       OR(cfg->thread_name, "file-storage"));
@@ -2990,9 +3018,9 @@
 	NULL,
 };
 
-static int fsg_add(struct usb_composite_dev *cdev,
-		   struct usb_configuration *c,
-		   struct fsg_common *common)
+static int fsg_bind_config(struct usb_composite_dev *cdev,
+			   struct usb_configuration *c,
+			   struct fsg_common *common)
 {
 	struct fsg_dev *fsg;
 	int rc;
@@ -3024,6 +3052,13 @@
 	return rc;
 }
 
+static inline int __deprecated __maybe_unused
+fsg_add(struct usb_composite_dev *cdev,
+	struct usb_configuration *c,
+	struct fsg_common *common)
+{
+	return fsg_bind_config(cdev, c, common);
+}
 
 
 /************************* Module parameters *************************/
@@ -3096,8 +3131,8 @@
 	cfg->product_name = 0;
 	cfg->release = 0xffff;
 
-	cfg->thread_exits = 0;
-	cfg->private_data = 0;
+	cfg->ops = NULL;
+	cfg->private_data = NULL;
 
 	/* Finalise */
 	cfg->can_stall = params->stall;
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 6d3cc44..685d768 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -404,7 +404,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init sourcesink_bind_config(struct usb_configuration *c)
+static int __ref sourcesink_bind_config(struct usb_configuration *c)
 {
 	struct f_sourcesink	*ss;
 	int			status;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index b49d86e..a857b7a 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -56,7 +56,7 @@
  * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
  * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
  * the optional "protocol" module parameter.  In addition, the default
- * Vendor ID, Product ID, and release number can be overridden.
+ * Vendor ID, Product ID, release number and serial number can be overridden.
  *
  * There is support for multiple logical units (LUNs), each of which has
  * its own backing file.  The number of LUNs can be set using the optional
@@ -93,6 +93,8 @@
  *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
  *					LUNs to support
+ *	nofua=b[,b...]		Default false, booleans for ignore FUA flag
+ *					in SCSI WRITE(10,12) commands
  *	stall			Default determined according to the type of
  *					USB device controller (usually true),
  *					boolean to permit the driver to halt
@@ -106,17 +108,18 @@
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
+ *	serial=HHHH...		Override serial number (string of hex chars)
  *	buflen=N		Default N=16384, buffer size used (will be
  *					rounded down to a multiple of
  *					PAGE_CACHE_SIZE)
  *
  * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
- * "removable", "luns", "stall", and "cdrom" options are available; default
- * values are used for everything else.
+ * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
+ * default values are used for everything else.
  *
  * The pathnames of the backing files and the ro settings are available in
- * the attribute files "file" and "ro" in the lun<n> subdirectory of the
- * gadget's sysfs directory.  If the "removable" option is set, writing to
+ * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
+ * the gadget's sysfs directory.  If the "removable" option is set, writing to
  * these files will simulate ejecting/loading the medium (writing an empty
  * line means eject) and adjusting a write-enable tab.  Changes to the ro
  * setting are not allowed when the medium is loaded or if CD-ROM emulation
@@ -270,6 +273,8 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
+/* DRIVER_VERSION must be at least 6 characters long, as it is used
+ * to generate a fallback serial number. */
 #define DRIVER_VERSION		"20 November 2008"
 
 static       char fsg_string_manufacturer[64];
@@ -301,8 +306,10 @@
 static struct {
 	char		*file[FSG_MAX_LUNS];
 	int		ro[FSG_MAX_LUNS];
+	int		nofua[FSG_MAX_LUNS];
 	unsigned int	num_filenames;
 	unsigned int	num_ros;
+	unsigned int	num_nofuas;
 	unsigned int	nluns;
 
 	int		removable;
@@ -314,6 +321,7 @@
 	unsigned short	vendor;
 	unsigned short	product;
 	unsigned short	release;
+	char		*serial;
 	unsigned int	buflen;
 
 	int		transport_type;
@@ -341,6 +349,10 @@
 module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
+module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
+		S_IRUGO);
+MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
+
 module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
 MODULE_PARM_DESC(luns, "number of LUNs");
 
@@ -353,6 +365,8 @@
 module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
 MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
 
+module_param_named(serial, mod_data.serial, charp, S_IRUGO);
+MODULE_PARM_DESC(serial, "USB serial number");
 
 /* In the non-TEST version, only the module parameters listed above
  * are available. */
@@ -1272,7 +1286,8 @@
 			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return -EINVAL;
 		}
-		if (fsg->cmnd[1] & 0x08) {	// FUA
+		/* FUA */
+		if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
 			spin_lock(&curlun->filp->f_lock);
 			curlun->filp->f_flags |= O_DSYNC;
 			spin_unlock(&curlun->filp->f_lock);
@@ -3126,6 +3141,7 @@
 
 /* The write permissions and store_xxx pointers are set in fsg_bind() */
 static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
+static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
 static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
 
 
@@ -3197,6 +3213,7 @@
 {
 	int	prot;
 	int	gcnum;
+	int	i;
 
 	/* Store the default values */
 	mod_data.transport_type = USB_PR_BULK;
@@ -3272,13 +3289,65 @@
 		ERROR(fsg, "invalid buflen\n");
 		return -ETOOSMALL;
 	}
+
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
 
+	/* Serial string handling.
+	 * On a real device, the serial string would be loaded
+	 * from permanent storage. */
+	if (mod_data.serial) {
+		const char *ch;
+		unsigned len = 0;
+
+		/* Sanity check :
+		 * The CB[I] specification limits the serial string to
+		 * 12 uppercase hexadecimal characters.
+		 * BBB need at least 12 uppercase hexadecimal characters,
+		 * with a maximum of 126. */
+		for (ch = mod_data.serial; *ch; ++ch) {
+			++len;
+			if ((*ch < '0' || *ch > '9') &&
+			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
+				WARNING(fsg,
+					"Invalid serial string character: %c; "
+					"Failing back to default\n",
+					*ch);
+				goto fill_serial;
+			}
+		}
+		if (len > 126 ||
+		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||
+		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {
+			WARNING(fsg,
+				"Invalid serial string length; "
+				"Failing back to default\n");
+			goto fill_serial;
+		}
+		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
+	} else {
+		WARNING(fsg,
+			"Userspace failed to provide serial number; "
+			"Failing back to default\n");
+fill_serial:
+		/* Serial number not specified or invalid, make our own.
+		 * We just encode it from the driver version string,
+		 * 12 characters to comply with both CB[I] and BBB spec.
+		 * Warning : Two devices running the same kernel will have
+		 * the same fallback serial number. */
+		for (i = 0; i < 12; i += 2) {
+			unsigned char	c = DRIVER_VERSION[i / 2];
+
+			if (!c)
+				break;
+			sprintf(&fsg_string_serial[i], "%02X", c);
+		}
+	}
+
 	return 0;
 }
 
 
-static int __init fsg_bind(struct usb_gadget *gadget)
+static int __ref fsg_bind(struct usb_gadget *gadget)
 {
 	struct fsg_dev		*fsg = the_fsg;
 	int			rc;
@@ -3305,6 +3374,10 @@
 		}
 	}
 
+	/* Only for removable media? */
+	dev_attr_nofua.attr.mode = 0644;
+	dev_attr_nofua.store = fsg_store_nofua;
+
 	/* Find out how many LUNs there should be */
 	i = mod_data.nluns;
 	if (i == 0)
@@ -3330,6 +3403,7 @@
 		curlun->ro = mod_data.cdrom || mod_data.ro[i];
 		curlun->initially_ro = curlun->ro;
 		curlun->removable = mod_data.removable;
+		curlun->nofua = mod_data.nofua[i];
 		curlun->dev.release = lun_release;
 		curlun->dev.parent = &gadget->dev;
 		curlun->dev.driver = &fsg_driver.driver;
@@ -3344,6 +3418,8 @@
 		if ((rc = device_create_file(&curlun->dev,
 					&dev_attr_ro)) != 0 ||
 				(rc = device_create_file(&curlun->dev,
+					&dev_attr_nofua)) != 0 ||
+				(rc = device_create_file(&curlun->dev,
 					&dev_attr_file)) != 0) {
 			device_unregister(&curlun->dev);
 			goto out;
@@ -3447,16 +3523,6 @@
 			init_utsname()->sysname, init_utsname()->release,
 			gadget->name);
 
-	/* On a real device, serial[] would be loaded from permanent
-	 * storage.  We just encode it from the driver version string. */
-	for (i = 0; i < sizeof fsg_string_serial - 2; i += 2) {
-		unsigned char		c = DRIVER_VERSION[i / 2];
-
-		if (!c)
-			break;
-		sprintf(&fsg_string_serial[i], "%02X", c);
-	}
-
 	fsg->thread_task = kthread_create(fsg_main_thread, fsg,
 			"file-storage-gadget");
 	if (IS_ERR(fsg->thread_task)) {
@@ -3478,8 +3544,8 @@
 				if (IS_ERR(p))
 					p = NULL;
 			}
-			LINFO(curlun, "ro=%d, file: %s\n",
-					curlun->ro, (p ? p : "(error)"));
+			LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
+			      curlun->ro, curlun->nofua, (p ? p : "(error)"));
 		}
 	}
 	kfree(pathbuf);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index d1af253..a9474f8 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -32,12 +32,13 @@
 #  include "u_ether.c"
 
 static u8 gfs_hostaddr[ETH_ALEN];
-#else
-#  if !defined CONFIG_USB_FUNCTIONFS_GENERIC
-#    define CONFIG_USB_FUNCTIONFS_GENERIC
+#  ifdef CONFIG_USB_FUNCTIONFS_ETH
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 #  endif
+#else
 #  define gether_cleanup() do { } while (0)
 #  define gether_setup(gadget, hostaddr)   ((int)0)
+#  define gfs_hostaddr NULL
 #endif
 
 #include "f_fs.c"
@@ -107,15 +108,7 @@
 enum {
 	GFS_STRING_MANUFACTURER_IDX,
 	GFS_STRING_PRODUCT_IDX,
-#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
-	GFS_STRING_RNDIS_CONFIG_IDX,
-#endif
-#ifdef CONFIG_USB_FUNCTIONFS_ETH
-	GFS_STRING_ECM_CONFIG_IDX,
-#endif
-#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
-	GFS_STRING_GENERIC_CONFIG_IDX,
-#endif
+	GFS_STRING_FIRST_CONFIG_IDX,
 };
 
 static       char gfs_manufacturer[50];
@@ -126,13 +119,13 @@
 	[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
 	[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
-	[GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS",
+	{ .s = "FunctionFS + RNDIS" },
 #endif
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
-	[GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM",
+	{ .s = "FunctionFS + ECM" },
 #endif
 #ifdef CONFIG_USB_FUNCTIONFS_GENERIC
-	[GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS",
+	{ .s = "FunctionFS" },
 #endif
 	{  } /* end of list */
 };
@@ -146,59 +139,33 @@
 };
 
 
+
+struct gfs_configuration {
+	struct usb_configuration c;
+	int (*eth)(struct usb_configuration *c, u8 *ethaddr);
+} gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
-static int gfs_do_rndis_config(struct usb_configuration *c);
-
-static struct usb_configuration gfs_rndis_config_driver = {
-	.label			= "FunctionFS + RNDIS",
-	.bind			= gfs_do_rndis_config,
-	.bConfigurationValue	= 1,
-	/* .iConfiguration	= DYNAMIC */
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
-#  define gfs_add_rndis_config(cdev) \
-	usb_add_config(cdev, &gfs_rndis_config_driver)
-#else
-#  define gfs_add_rndis_config(cdev) 0
+	{
+		.eth		= rndis_bind_config,
+	},
 #endif
 
-
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int gfs_do_ecm_config(struct usb_configuration *c);
-
-static struct usb_configuration gfs_ecm_config_driver = {
-	.label			= "FunctionFS + ECM",
-	.bind			= gfs_do_ecm_config,
-	.bConfigurationValue	= 1,
-	/* .iConfiguration	= DYNAMIC */
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
-#  define gfs_add_ecm_config(cdev) \
-	usb_add_config(cdev, &gfs_ecm_config_driver)
-#else
-#  define gfs_add_ecm_config(cdev) 0
+	{
+		.eth		= eth_bind_config,
+	},
 #endif
 
-
 #ifdef CONFIG_USB_FUNCTIONFS_GENERIC
-static int gfs_do_generic_config(struct usb_configuration *c);
-
-static struct usb_configuration gfs_generic_config_driver = {
-	.label			= "FunctionFS",
-	.bind			= gfs_do_generic_config,
-	.bConfigurationValue	= 2,
-	/* .iConfiguration	= DYNAMIC */
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
-#  define gfs_add_generic_config(cdev) \
-	usb_add_config(cdev, &gfs_generic_config_driver)
-#else
-#  define gfs_add_generic_config(cdev) 0
+	{
+	},
 #endif
+};
 
 
 static int gfs_bind(struct usb_composite_dev *cdev);
 static int gfs_unbind(struct usb_composite_dev *cdev);
+static int gfs_do_config(struct usb_configuration *c);
 
 static struct usb_composite_driver gfs_driver = {
 	.name		= gfs_short_name,
@@ -267,7 +234,7 @@
 
 static int gfs_bind(struct usb_composite_dev *cdev)
 {
-	int ret;
+	int ret, i;
 
 	ENTER();
 
@@ -284,57 +251,32 @@
 	snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
 		 init_utsname()->sysname, init_utsname()->release,
 		 cdev->gadget->name);
-	ret = usb_string_id(cdev);
-	if (unlikely(ret < 0))
-		goto error;
-	gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret;
-	gfs_dev_desc.iManufacturer = ret;
 
-	ret = usb_string_id(cdev);
+	ret = usb_string_ids_tab(cdev, gfs_strings);
 	if (unlikely(ret < 0))
 		goto error;
-	gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret;
-	gfs_dev_desc.iProduct = ret;
 
-#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
-	ret = usb_string_id(cdev);
-	if (unlikely(ret < 0))
-		goto error;
-	gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret;
-	gfs_rndis_config_driver.iConfiguration = ret;
-#endif
-
-#ifdef CONFIG_USB_FUNCTIONFS_ETH
-	ret = usb_string_id(cdev);
-	if (unlikely(ret < 0))
-		goto error;
-	gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret;
-	gfs_ecm_config_driver.iConfiguration = ret;
-#endif
-
-#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
-	ret = usb_string_id(cdev);
-	if (unlikely(ret < 0))
-		goto error;
-	gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret;
-	gfs_generic_config_driver.iConfiguration = ret;
-#endif
+	gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id;
+	gfs_dev_desc.iProduct      = gfs_strings[GFS_STRING_PRODUCT_IDX].id;
 
 	ret = functionfs_bind(gfs_ffs_data, cdev);
 	if (unlikely(ret < 0))
 		goto error;
 
-	ret = gfs_add_rndis_config(cdev);
-	if (unlikely(ret < 0))
-		goto error_unbind;
+	for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
+		struct gfs_configuration *c = gfs_configurations + i;
 
-	ret = gfs_add_ecm_config(cdev);
-	if (unlikely(ret < 0))
-		goto error_unbind;
+		ret = GFS_STRING_FIRST_CONFIG_IDX + i;
+		c->c.label			= gfs_strings[ret].s;
+		c->c.iConfiguration		= gfs_strings[ret].id;
+		c->c.bind			= gfs_do_config;
+		c->c.bConfigurationValue	= 1 + i;
+		c->c.bmAttributes		= USB_CONFIG_ATT_SELFPOWER;
 
-	ret = gfs_add_generic_config(cdev);
-	if (unlikely(ret < 0))
-		goto error_unbind;
+		ret = usb_add_config(cdev, &c->c);
+		if (unlikely(ret < 0))
+			goto error_unbind;
+	}
 
 	return 0;
 
@@ -368,10 +310,10 @@
 }
 
 
-static int __gfs_do_config(struct usb_configuration *c,
-			   int (*eth)(struct usb_configuration *c, u8 *ethaddr),
-			   u8 *ethaddr)
+static int gfs_do_config(struct usb_configuration *c)
 {
+	struct gfs_configuration *gc =
+		container_of(c, struct gfs_configuration, c);
 	int ret;
 
 	if (WARN_ON(!gfs_ffs_data))
@@ -382,13 +324,13 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	if (eth) {
-		ret = eth(c, ethaddr);
+	if (gc->eth) {
+		ret = gc->eth(c, gfs_hostaddr);
 		if (unlikely(ret < 0))
 			return ret;
 	}
 
-	ret = functionfs_add(c->cdev, c, gfs_ffs_data);
+	ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data);
 	if (unlikely(ret < 0))
 		return ret;
 
@@ -406,32 +348,12 @@
 	return 0;
 }
 
-#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
-static int gfs_do_rndis_config(struct usb_configuration *c)
-{
-	ENTER();
-
-	return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr);
-}
-#endif
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int gfs_do_ecm_config(struct usb_configuration *c)
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
-	ENTER();
-
-	return __gfs_do_config(c,
-			       can_support_ecm(c->cdev->gadget)
-			     ? ecm_bind_config : geth_bind_config,
-			       gfs_hostaddr);
-}
-#endif
-
-#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
-static int gfs_do_generic_config(struct usb_configuration *c)
-{
-	ENTER();
-
-	return __gfs_do_config(c, NULL, NULL);
+	return can_support_ecm(c->cdev->gadget)
+		? ecm_bind_config(c, ethaddr)
+		: geth_bind_config(c, ethaddr);
 }
 #endif
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index b7bf880..1b413a5c 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1157,7 +1157,7 @@
 /*
  * Creates an output endpoint, and initializes output ports.
  */
-static int __init gmidi_bind(struct usb_gadget *gadget)
+static int __ref gmidi_bind(struct usb_gadget *gadget)
 {
 	struct gmidi_device *dev;
 	struct usb_ep *in_ep, *out_ep;
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 7757226..735495b 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -127,7 +127,7 @@
 
 /****************************** Configurations ******************************/
 
-static int __init do_config(struct usb_configuration *c)
+static int __ref do_config(struct usb_configuration *c)
 {
 	struct hidg_func_node *e;
 	int func = 0, status = 0;
@@ -156,7 +156,7 @@
 
 /****************************** Gadget Bind ******************************/
 
-static int __init hid_bind(struct usb_composite_dev *cdev)
+static int __ref hid_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	struct list_head *tmp;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index de8a838..fc35406 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1299,11 +1299,9 @@
 	struct usb_gadget	*gadget = dev->gadget;
 	long ret = -ENOTTY;
 
-	if (gadget->ops->ioctl) {
-		lock_kernel();
+	if (gadget->ops->ioctl)
 		ret = gadget->ops->ioctl (gadget, code, value);
-		unlock_kernel();
-	}
+
 	return ret;
 }
 
@@ -1867,13 +1865,9 @@
 	buf += 4;
 	length -= 4;
 
-	kbuf = kmalloc (length, GFP_KERNEL);
-	if (!kbuf)
-		return -ENOMEM;
-	if (copy_from_user (kbuf, buf, length)) {
-		kfree (kbuf);
-		return -EFAULT;
-	}
+	kbuf = memdup_user(buf, length);
+	if (IS_ERR(kbuf))
+		return PTR_ERR(kbuf);
 
 	spin_lock_irq (&dev->lock);
 	value = -EINVAL;
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index a391351..c2d2a20 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -842,9 +842,9 @@
 		VDBG(dev, "req->mapped = 0\n");
 	}
 
-	DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08x\n",
-			_ep->name,
-			_req, _req->length, _req->buf, _req->dma);
+	DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n",
+	    _ep->name,
+	    _req, _req->length, _req->buf, (unsigned long long)_req->dma);
 
 	_req->status = -EINPROGRESS;
 	_req->actual = 0;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 705cc1f..585f255 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -141,9 +141,14 @@
 	return 0;
 }
 
-static int __init msg_do_config(struct usb_configuration *c)
+static int __ref msg_do_config(struct usb_configuration *c)
 {
-	struct fsg_common *common;
+	static const struct fsg_operations ops = {
+		.thread_exits = msg_thread_exits,
+	};
+	static struct fsg_common common;
+
+	struct fsg_common *retp;
 	struct fsg_config config;
 	int ret;
 
@@ -153,13 +158,14 @@
 	}
 
 	fsg_config_from_params(&config, &mod_data);
-	config.thread_exits = msg_thread_exits;
-	common = fsg_common_init(0, c->cdev, &config);
-	if (IS_ERR(common))
-		return PTR_ERR(common);
+	config.ops = &ops;
 
-	ret = fsg_add(c->cdev, c, common);
-	fsg_common_put(common);
+	retp = fsg_common_init(&common, c->cdev, &config);
+	if (IS_ERR(retp))
+		return PTR_ERR(retp);
+
+	ret = fsg_bind_config(c->cdev, c, &common);
+	fsg_common_put(&common);
 	return ret;
 }
 
@@ -176,7 +182,7 @@
 /****************************** Gadget Bind ******************************/
 
 
-static int __init msg_bind(struct usb_composite_dev *cdev)
+static int __ref msg_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	int status;
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index a930d7f..795d762 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -24,6 +24,7 @@
 
 #include <linux/kernel.h>
 #include <linux/utsname.h>
+#include <linux/module.h>
 
 
 #if defined USB_ETH_RNDIS
@@ -35,14 +36,13 @@
 
 
 #define DRIVER_DESC		"Multifunction Composite Gadget"
-#define DRIVER_VERSION		"2009/07/21"
 
-/*-------------------------------------------------------------------------*/
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Michal Nazarewicz");
+MODULE_LICENSE("GPL");
 
-#define MULTI_VENDOR_NUM	0x0525	/* XXX NetChip */
-#define MULTI_PRODUCT_NUM	0xa4ab	/* XXX */
 
-/*-------------------------------------------------------------------------*/
+/***************************** All the files... *****************************/
 
 /*
  * kbuild is not very cooperative with respect to linking separately
@@ -57,6 +57,8 @@
 #include "config.c"
 #include "epautoconf.c"
 
+#include "f_mass_storage.c"
+
 #include "u_serial.c"
 #include "f_acm.c"
 
@@ -68,13 +70,24 @@
 #endif
 #include "u_ether.c"
 
-#undef DBG     /* u_ether.c has broken idea about macros */
-#undef VDBG    /* so clean up after it */
-#undef ERROR
-#undef INFO
-#include "f_mass_storage.c"
 
-/*-------------------------------------------------------------------------*/
+
+/***************************** Device Descriptor ****************************/
+
+#define MULTI_VENDOR_NUM	0x0525	/* XXX NetChip */
+#define MULTI_PRODUCT_NUM	0xa4ab	/* XXX */
+
+
+enum {
+	__MULTI_NO_CONFIG,
+#ifdef CONFIG_USB_G_MULTI_RNDIS
+	MULTI_RNDIS_CONFIG_NUM,
+#endif
+#ifdef CONFIG_USB_G_MULTI_CDC
+	MULTI_CDC_CONFIG_NUM,
+#endif
+};
+
 
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
@@ -82,80 +95,82 @@
 
 	.bcdUSB =		cpu_to_le16(0x0200),
 
-	/* .bDeviceClass =		USB_CLASS_COMM, */
-	/* .bDeviceSubClass =	0, */
-	/* .bDeviceProtocol =	0, */
-	.bDeviceClass =		0xEF,
+	.bDeviceClass =		USB_CLASS_MISC /* 0xEF */,
 	.bDeviceSubClass =	2,
 	.bDeviceProtocol =	1,
-	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id can be overridden by module parameters.  */
 	.idVendor =		cpu_to_le16(MULTI_VENDOR_NUM),
 	.idProduct =		cpu_to_le16(MULTI_PRODUCT_NUM),
-	/* .bcdDevice = f(hardware) */
-	/* .iManufacturer = DYNAMIC */
-	/* .iProduct = DYNAMIC */
-	/* NO SERIAL NUMBER */
-	.bNumConfigurations =	1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-	.bLength =		sizeof otg_descriptor,
-	.bDescriptorType =	USB_DT_OTG,
-
-	/* REVISIT SRP-only hardware is possible, although
-	 * it would not be called "OTG" ...
-	 */
-	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
-};
 
 static const struct usb_descriptor_header *otg_desc[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
+	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
+		.bLength =		sizeof(struct usb_otg_descriptor),
+		.bDescriptorType =	USB_DT_OTG,
+
+		/*
+		 * REVISIT SRP-only hardware is possible, although
+		 * it would not be called "OTG" ...
+		 */
+		.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
+	},
 	NULL,
 };
 
 
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
+enum {
+	MULTI_STRING_MANUFACTURER_IDX,
+	MULTI_STRING_PRODUCT_IDX,
+#ifdef CONFIG_USB_G_MULTI_RNDIS
+	MULTI_STRING_RNDIS_CONFIG_IDX,
+#endif
+#ifdef CONFIG_USB_G_MULTI_CDC
+	MULTI_STRING_CDC_CONFIG_IDX,
+#endif
+};
 
 static char manufacturer[50];
 
 static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = manufacturer,
-	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	[MULTI_STRING_MANUFACTURER_IDX].s = manufacturer,
+	[MULTI_STRING_PRODUCT_IDX].s      = DRIVER_DESC,
+#ifdef CONFIG_USB_G_MULTI_RNDIS
+	[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
+#endif
+#ifdef CONFIG_USB_G_MULTI_CDC
+	[MULTI_STRING_CDC_CONFIG_IDX].s   = "Multifunction with CDC ECM",
+#endif
 	{  } /* end of list */
 };
 
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
 static struct usb_gadget_strings *dev_strings[] = {
-	&stringtab_dev,
+	&(struct usb_gadget_strings){
+		.language	= 0x0409,	/* en-us */
+		.strings	= strings_dev,
+	},
 	NULL,
 };
 
-static u8 hostaddr[ETH_ALEN];
 
 
 
 /****************************** Configurations ******************************/
 
-static struct fsg_module_parameters mod_data = {
-	.stall = 1
-};
-FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
+static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 
-static struct fsg_common *fsg_common;
+static struct fsg_common fsg_common;
 
+static u8 hostaddr[ETH_ALEN];
+
+
+/********** RNDIS **********/
 
 #ifdef USB_ETH_RNDIS
 
-static int __init rndis_do_config(struct usb_configuration *c)
+static __ref int rndis_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -172,26 +187,42 @@
 	if (ret < 0)
 		return ret;
 
-	ret = fsg_add(c->cdev, c, fsg_common);
+	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-static struct usb_configuration rndis_config_driver = {
-	.label			= "Multifunction Composite (RNDIS + MS + ACM)",
-	.bind			= rndis_do_config,
-	.bConfigurationValue	= 2,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
+static int rndis_config_register(struct usb_composite_dev *cdev)
+{
+	static struct usb_configuration config = {
+		.bind			= rndis_do_config,
+		.bConfigurationValue	= MULTI_RNDIS_CONFIG_NUM,
+		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	};
+
+	config.label          = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
+	config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
+
+	return usb_add_config(cdev, &config);
+}
+
+#else
+
+static int rndis_config_register(struct usb_composite_dev *cdev)
+{
+	return 0;
+}
 
 #endif
 
+
+/********** CDC ECM **********/
+
 #ifdef CONFIG_USB_G_MULTI_CDC
 
-static int __init cdc_do_config(struct usb_configuration *c)
+static __ref int cdc_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -208,20 +239,33 @@
 	if (ret < 0)
 		return ret;
 
-	ret = fsg_add(c->cdev, c, fsg_common);
+	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-static struct usb_configuration cdc_config_driver = {
-	.label			= "Multifunction Composite (CDC + MS + ACM)",
-	.bind			= cdc_do_config,
-	.bConfigurationValue	= 1,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
+static int cdc_config_register(struct usb_composite_dev *cdev)
+{
+	static struct usb_configuration config = {
+		.bind			= cdc_do_config,
+		.bConfigurationValue	= MULTI_CDC_CONFIG_NUM,
+		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	};
+
+	config.label          = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
+	config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
+
+	return usb_add_config(cdev, &config);
+}
+
+#else
+
+static int cdc_config_register(struct usb_composite_dev *cdev)
+{
+	return 0;
+}
 
 #endif
 
@@ -230,7 +274,7 @@
 /****************************** Gadget Bind ******************************/
 
 
-static int __init multi_bind(struct usb_composite_dev *cdev)
+static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	int status, gcnum;
@@ -252,67 +296,56 @@
 		goto fail0;
 
 	/* set up mass storage function */
-	fsg_common = fsg_common_from_params(0, cdev, &mod_data);
-	if (IS_ERR(fsg_common)) {
-		status = PTR_ERR(fsg_common);
-		goto fail1;
+	{
+		void *retp;
+		retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
+		if (IS_ERR(retp)) {
+			status = PTR_ERR(retp);
+			goto fail1;
+		}
 	}
 
-
+	/* set bcdDevice */
 	gcnum = usb_gadget_controller_number(gadget);
-	if (gcnum >= 0)
+	if (gcnum >= 0) {
 		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
-	else {
-		/* We assume that can_support_ecm() tells the truth;
-		 * but if the controller isn't recognized at all then
-		 * that assumption is a bit more likely to be wrong.
-		 */
-		WARNING(cdev, "controller '%s' not recognized\n",
-		        gadget->name);
+	} else {
+		WARNING(cdev, "controller '%s' not recognized\n", gadget->name);
 		device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
 	}
 
-
-	/* Allocate string descriptor numbers ... note that string
-	 * contents can be overridden by the composite_dev glue.
-	 */
-
-	/* device descriptor strings: manufacturer, product */
+	/* allocate string descriptor numbers */
 	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 	         init_utsname()->sysname, init_utsname()->release,
 	         gadget->name);
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail2;
-	strings_dev[STRING_MANUFACTURER_IDX].id = status;
-	device_desc.iManufacturer = status;
 
-	status = usb_string_id(cdev);
-	if (status < 0)
+	status = usb_string_ids_tab(cdev, strings_dev);
+	if (unlikely(status < 0))
 		goto fail2;
-	strings_dev[STRING_PRODUCT_IDX].id = status;
-	device_desc.iProduct = status;
 
-#ifdef USB_ETH_RNDIS
-	/* register our first configuration */
-	status = usb_add_config(cdev, &rndis_config_driver);
-	if (status < 0)
+	device_desc.iManufacturer =
+		strings_dev[MULTI_STRING_MANUFACTURER_IDX].id;
+	device_desc.iProduct      =
+		strings_dev[MULTI_STRING_PRODUCT_IDX].id;
+
+	/* register configurations */
+	status = rndis_config_register(cdev);
+	if (unlikely(status < 0))
 		goto fail2;
-#endif
 
-#ifdef CONFIG_USB_G_MULTI_CDC
-	/* register our second configuration */
-	status = usb_add_config(cdev, &cdc_config_driver);
-	if (status < 0)
+	status = cdc_config_register(cdev);
+	if (unlikely(status < 0))
 		goto fail2;
-#endif
 
-	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
-	fsg_common_put(fsg_common);
+	/* we're done */
+	dev_info(&gadget->dev, DRIVER_DESC "\n");
+	fsg_common_put(&fsg_common);
 	return 0;
 
+
+	/* error recovery */
 fail2:
-	fsg_common_put(fsg_common);
+	fsg_common_put(&fsg_common);
 fail1:
 	gserial_cleanup();
 fail0:
@@ -339,18 +372,15 @@
 	.unbind		= __exit_p(multi_unbind),
 };
 
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Michal Nazarewicz");
-MODULE_LICENSE("GPL");
 
-static int __init g_multi_init(void)
+static int __init multi_init(void)
 {
 	return usb_composite_register(&multi_driver);
 }
-module_init(g_multi_init);
+module_init(multi_init);
 
-static void __exit g_multi_cleanup(void)
+static void __exit multi_exit(void)
 {
 	usb_composite_unregister(&multi_driver);
 }
-module_exit(g_multi_cleanup);
+module_exit(multi_exit);
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 4c3ac5c..cf241c3 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
@@ -70,6 +70,7 @@
 #define DRIVER_DESC		"Printer Gadget"
 #define DRIVER_VERSION		"2007 OCT 06"
 
+static DEFINE_MUTEX(printer_mutex);
 static const char shortname [] = "printer";
 static const char driver_desc [] = DRIVER_DESC;
 
@@ -476,7 +477,7 @@
 	unsigned long		flags;
 	int			ret = -EBUSY;
 
-	lock_kernel();
+	mutex_lock(&printer_mutex);
 	dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -492,7 +493,7 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	DBG(dev, "printer_open returned %x\n", ret);
-	unlock_kernel();
+	mutex_unlock(&printer_mutex);
 	return ret;
 }
 
@@ -1346,7 +1347,7 @@
 	set_gadget_data(gadget, NULL);
 }
 
-static int __init
+static int __ref
 printer_bind(struct usb_gadget *gadget)
 {
 	struct printer_dev	*dev;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 26193ec..521ebed 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -12,6 +12,8 @@
  * published by the Free Software Foundation.
 */
 
+#define DEBUG
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
@@ -23,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -33,6 +36,7 @@
 #include <plat/regs-usb-hsotg.h>
 #include <mach/regs-sys.h>
 #include <plat/udc-hs.h>
+#include <plat/cpu.h>
 
 #define DMA_ADDR_INVALID (~((dma_addr_t)0))
 
@@ -91,7 +95,9 @@
  * For periodic IN endpoints, we have fifo_size and fifo_load to try
  * and keep track of the amount of data in the periodic FIFO for each
  * of these as we don't have a status register that tells us how much
- * is in each of them.
+ * is in each of them. (note, this may actually be useless information
+ * as in shared-fifo mode periodic in acts like a single-frame packet
+ * buffer than a fifo)
  */
 struct s3c_hsotg_ep {
 	struct usb_ep		ep;
@@ -128,6 +134,7 @@
  * @regs: The memory area mapped for accessing registers.
  * @regs_res: The resource that was allocated when claiming register space.
  * @irq: The IRQ number we are using
+ * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
  * @debug_root: root directrory for debugfs.
  * @debug_file: main status file for debugfs.
  * @debug_fifo: FIFO status file for debugfs.
@@ -145,6 +152,9 @@
 	void __iomem		*regs;
 	struct resource		*regs_res;
 	int			irq;
+	struct clk		*clk;
+
+	unsigned int		dedicated_fifos:1;
 
 	struct dentry		*debug_root;
 	struct dentry		*debug_file;
@@ -310,11 +320,11 @@
 		hsotg->regs + S3C_GNPTXFSIZ);
 	*/
 
-	/* set FIFO sizes to 2048/0x1C0 */
+	/* set FIFO sizes to 2048/1024 */
 
 	writel(2048, hsotg->regs + S3C_GRXFSIZ);
 	writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
-	       S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
+	       S3C_GNPTXFSIZ_NPTxFDep(1024),
 	       hsotg->regs + S3C_GNPTXFSIZ);
 
 	/* arange all the rest of the TX FIFOs, as some versions of this
@@ -464,7 +474,7 @@
 	if (to_write == 0)
 		return 0;
 
-	if (periodic) {
+	if (periodic && !hsotg->dedicated_fifos) {
 		u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
 		int size_left;
 		int size_done;
@@ -474,6 +484,14 @@
 
 		size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
 
+		/* if shared fifo, we cannot write anything until the
+		 * previous data has been completely sent.
+		 */
+		if (hs_ep->fifo_load != 0) {
+			s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+			return -ENOSPC;
+		}
+
 		dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n",
 			__func__, size_left,
 			hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size);
@@ -494,6 +512,11 @@
 			s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
 			return -ENOSPC;
 		}
+	} else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
+		can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index));
+
+		can_write &= 0xffff;
+		can_write *= 4;
 	} else {
 		if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
 			dev_dbg(hsotg->dev,
@@ -505,6 +528,7 @@
 		}
 
 		can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
+		can_write *= 4;	/* fifo size is in 32bit quantities. */
 	}
 
 	dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
@@ -517,6 +541,17 @@
 	if (can_write > 512)
 		can_write = 512;
 
+	/* limit the write to one max-packet size worth of data, but allow
+	 * the transfer to return that it did not run out of fifo space
+	 * doing it. */
+	if (to_write > hs_ep->ep.maxpacket) {
+		to_write = hs_ep->ep.maxpacket;
+
+		s3c_hsotg_en_gsint(hsotg,
+				   periodic ? S3C_GINTSTS_PTxFEmp :
+				   S3C_GINTSTS_NPTxFEmp);
+	}
+
 	/* see if we can write data */
 
 	if (to_write > can_write) {
@@ -579,12 +614,10 @@
 		maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1;
 		maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
 	} else {
+		maxsize = 64+64;
 		if (hs_ep->dir_in) {
-			/* maxsize = S3C_DIEPTSIZ0_XferSize_LIMIT + 1; */
-			maxsize = 64+64+1;
 			maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
 		} else {
-			maxsize = 0x3f;
 			maxpkt = 2;
 		}
 	}
@@ -1353,6 +1386,9 @@
 	read_ptr = hs_req->req.actual;
 	max_req = hs_req->req.length - read_ptr;
 
+	dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
+		__func__, to_read, max_req, read_ptr, hs_req->req.length);
+
 	if (to_read > max_req) {
 		/* more data appeared than we where willing
 		 * to deal with in this request.
@@ -1362,9 +1398,6 @@
 		WARN_ON_ONCE(1);
 	}
 
-	dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
-		__func__, to_read, max_req, read_ptr, hs_req->req.length);
-
 	hs_ep->total_data += to_read;
 	hs_req->req.actual += to_read;
 	to_read = DIV_ROUND_UP(to_read, 4);
@@ -1433,9 +1466,11 @@
 static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
 				     int epnum, bool was_setup)
 {
+	u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
 	struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
 	struct s3c_hsotg_req *hs_req = hs_ep->req;
 	struct usb_request *req = &hs_req->req;
+	unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
 	int result = 0;
 
 	if (!hs_req) {
@@ -1444,9 +1479,7 @@
 	}
 
 	if (using_dma(hsotg)) {
-		u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
 		unsigned size_done;
-		unsigned size_left;
 
 		/* Calculate the size of the transfer by checking how much
 		 * is left in the endpoint size register and then working it
@@ -1456,14 +1489,18 @@
 		 * so may overshoot/undershoot the transfer.
 		 */
 
-		size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
-
 		size_done = hs_ep->size_loaded - size_left;
 		size_done += hs_ep->last_load;
 
 		req->actual = size_done;
 	}
 
+	/* if there is more request to do, schedule new transfer */
+	if (req->actual < req->length && size_left == 0) {
+		s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+		return;
+	}
+
 	if (req->actual < req->length && req->short_not_ok) {
 		dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
 			__func__, req->actual, req->length);
@@ -1758,7 +1795,7 @@
 		if (dir_in) {
 			s3c_hsotg_complete_in(hsotg, hs_ep);
 
-			if (idx == 0)
+			if (idx == 0 && !hs_ep->req)
 				s3c_hsotg_enqueue_setup(hsotg);
 		} else if (using_dma(hsotg)) {
 			/* We're using DMA, we need to fire an OutDone here
@@ -1818,6 +1855,15 @@
 				 __func__, idx);
 			clear |= S3C_DIEPMSK_INTknEPMisMsk;
 		}
+
+		/* FIFO has space or is empty (see GAHBCFG) */
+		if (hsotg->dedicated_fifos &&
+		    ints & S3C_DIEPMSK_TxFIFOEmpty) {
+			dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
+				__func__, idx);
+			s3c_hsotg_trytx(hsotg, hs_ep);
+			clear |= S3C_DIEPMSK_TxFIFOEmpty;
+		}
 	}
 
 	writel(clear, hsotg->regs + epint_reg);
@@ -2071,17 +2117,12 @@
 		kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
 
 		/* it seems after a reset we can end up with a situation
-		 * where the TXFIFO still has data in it... try flushing
-		 * it to remove anything that may still be in it.
+		 * where the TXFIFO still has data in it... the docs
+		 * suggest resetting all the fifos, so use the init_fifo
+		 * code to relayout and flush the fifos.
 		 */
 
-		if (1) {
-			writel(S3C_GRSTCTL_TxFNum(0) | S3C_GRSTCTL_TxFFlsh,
-			       hsotg->regs + S3C_GRSTCTL);
-
-			dev_info(hsotg->dev, "GNPTXSTS=%08x\n",
-				 readl(hsotg->regs + S3C_GNPTXSTS));
-		}
+		s3c_hsotg_init_fifo(hsotg);
 
 		s3c_hsotg_enqueue_setup(hsotg);
 
@@ -2274,6 +2315,12 @@
 		break;
 	}
 
+	/* if the hardware has dedicated fifos, we must give each IN EP
+	 * a unique tx-fifo even if it is non-periodic.
+	 */
+	if (dir_in && hsotg->dedicated_fifos)
+		epctrl |= S3C_DxEPCTL_TxFNum(index);
+
 	/* for non control endpoints, set PID to D0 */
 	if (index)
 		epctrl |= S3C_DxEPCTL_SetD0PID;
@@ -2563,7 +2610,8 @@
 
 	writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
 	       S3C_DIEPMSK_INTknEPMisMsk |
-	       S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
+	       S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
+	       ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
 	       hsotg->regs + S3C_DIEPMSK);
 
 	/* don't need XferCompl, we get that from RXFIFO in slave mode. In
@@ -2732,7 +2780,7 @@
 	 */
 
 	ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum));
-	hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo);
+	hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
 
 	/* if we're using dma, we need to set the next-endpoint pointer
 	 * to be something valid.
@@ -2753,13 +2801,33 @@
  */
 static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
 {
-	u32 osc;
+	struct clk *xusbxti;
+	u32 pwr, osc;
 
-	writel(0, S3C_PHYPWR);
+	pwr = readl(S3C_PHYPWR);
+	pwr &= ~0x19;
+	writel(pwr, S3C_PHYPWR);
 	mdelay(1);
 
 	osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0;
 
+	xusbxti = clk_get(hsotg->dev, "xusbxti");
+	if (xusbxti && !IS_ERR(xusbxti)) {
+		switch (clk_get_rate(xusbxti)) {
+		case 12*MHZ:
+			osc |= S3C_PHYCLK_CLKSEL_12M;
+			break;
+		case 24*MHZ:
+			osc |= S3C_PHYCLK_CLKSEL_24M;
+			break;
+		default:
+		case 48*MHZ:
+			/* default reference clock */
+			break;
+		}
+		clk_put(xusbxti);
+	}
+
 	writel(osc | 0x10, S3C_PHYCLK);
 
 	/* issue a full set of resets to the otg and core */
@@ -2772,6 +2840,8 @@
 
 static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
 {
+	u32 cfg4;
+
 	/* unmask subset of endpoint interrupts */
 
 	writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
@@ -2807,6 +2877,14 @@
 
 	writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
 	       hsotg->regs + S3C_GAHBCFG);
+
+	/* check hardware configuration */
+
+	cfg4 = readl(hsotg->regs + 0x50);
+	hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
+
+	dev_info(hsotg->dev, "%s fifos\n",
+		 hsotg->dedicated_fifos ? "dedicated" : "shared");
 }
 
 static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
@@ -3181,13 +3259,20 @@
 	hsotg->dev = dev;
 	hsotg->plat = plat;
 
+	hsotg->clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(hsotg->clk)) {
+		dev_err(dev, "cannot get otg clock\n");
+		ret = -EINVAL;
+		goto err_mem;
+	}
+
 	platform_set_drvdata(pdev, hsotg);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "cannot find register resource 0\n");
 		ret = -EINVAL;
-		goto err_mem;
+		goto err_clk;
 	}
 
 	hsotg->regs_res = request_mem_region(res->start, resource_size(res),
@@ -3195,7 +3280,7 @@
 	if (!hsotg->regs_res) {
 		dev_err(dev, "cannot reserve registers\n");
 		ret = -ENOENT;
-		goto err_mem;
+		goto err_clk;
 	}
 
 	hsotg->regs = ioremap(res->start, resource_size(res));
@@ -3248,6 +3333,8 @@
 
 	/* reset the system */
 
+	clk_enable(hsotg->clk);
+
 	s3c_hsotg_gate(pdev, true);
 
 	s3c_hsotg_otgreset(hsotg);
@@ -3271,7 +3358,8 @@
 err_regs_res:
 	release_resource(hsotg->regs_res);
 	kfree(hsotg->regs_res);
-
+err_clk:
+	clk_put(hsotg->clk);
 err_mem:
 	kfree(hsotg);
 	return ret;
@@ -3293,6 +3381,9 @@
 
 	s3c_hsotg_gate(pdev, false);
 
+	clk_disable(hsotg->clk);
+	clk_put(hsotg->clk);
+
 	kfree(hsotg);
 	return 0;
 }
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f46a609..b22eedb 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -137,7 +137,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init serial_bind_config(struct usb_configuration *c)
+static int __ref serial_bind_config(struct usb_configuration *c)
 {
 	unsigned i;
 	int status = 0;
@@ -161,7 +161,7 @@
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 };
 
-static int __init gs_bind(struct usb_composite_dev *cdev)
+static int __ref gs_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 04c462f..484acfb 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -57,10 +57,12 @@
 #include <asm/unaligned.h>
 
 
-/* Thanks to NetChip Technologies for donating this product ID.
+/*
+ * Thanks to NetChip Technologies for donating this product ID.
  *
  * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures. */
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
 #define FSG_VENDOR_ID	0x0525	/* NetChip */
 #define FSG_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
 
@@ -84,14 +86,27 @@
 #define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
 #define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
 
-/* Keep those macros in sync with thos in
- * include/linux/ubs/composite.h or else GCC will complain.  If they
+/*
+ * Keep those macros in sync with those in
+ * include/linux/usb/composite.h or else GCC will complain.  If they
  * are identical (the same names of arguments, white spaces in the
  * same places) GCC will allow redefinition otherwise (even if some
- * white space is removed or added) warning will be issued.  No
- * checking if those symbols is defined is performed because warning
- * is desired when those macros were defined by someone else to mean
- * something else. */
+ * white space is removed or added) warning will be issued.
+ *
+ * Those macros are needed here because File Storage Gadget does not
+ * include the composite.h header.  For composite gadgets those macros
+ * are redundant since composite.h is included any way.
+ *
+ * One could check whether those macros are already defined (which
+ * would indicate composite.h had been included) or not (which would
+ * indicate we were in FSG) but this is not done because a warning is
+ * desired if definitions here differ from the ones in composite.h.
+ *
+ * We want the definitions to match and be the same in File Storage
+ * Gadget as well as Mass Storage Function (and so composite gadgets
+ * using MSF).  If someone changes them in composite.h it will produce
+ * a warning in this file when building MSF.
+ */
 #define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args)
 #define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args)
@@ -269,6 +284,7 @@
 	unsigned int	prevent_medium_removal:1;
 	unsigned int	registered:1;
 	unsigned int	info_valid:1;
+	unsigned int	nofua:1;
 
 	u32		sense_data;
 	u32		sense_data_info;
@@ -313,9 +329,11 @@
 	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
-	/* The NetChip 2280 is faster, and handles some protocol faults
+	/*
+	 * The NetChip 2280 is faster, and handles some protocol faults
 	 * better, if we don't submit any short bulk-out read requests.
-	 * So we will record the intended request length here. */
+	 * So we will record the intended request length here.
+	 */
 	unsigned int			bulk_out_intended_length;
 
 	struct usb_request		*inreq;
@@ -395,8 +413,10 @@
 	.iInterface =		FSG_STRING_INTERFACE,
 };
 
-/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
- * and interrupt-in. */
+/*
+ * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
+ * interrupt-in.
+ */
 
 static struct usb_endpoint_descriptor
 fsg_fs_bulk_in_desc = {
@@ -459,7 +479,7 @@
  *
  * That means alternate endpoint descriptors (bigger packets)
  * and a "device qualifier" ... plus more construction options
- * for the config descriptor.
+ * for the configuration descriptor.
  */
 static struct usb_endpoint_descriptor
 fsg_hs_bulk_in_desc = {
@@ -547,8 +567,10 @@
 
  /*-------------------------------------------------------------------------*/
 
-/* If the next two routines are called while the gadget is registered,
- * the caller must own fsg->filesem for writing. */
+/*
+ * If the next two routines are called while the gadget is registered,
+ * the caller must own fsg->filesem for writing.
+ */
 
 static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 {
@@ -587,8 +609,10 @@
 		goto out;
 	}
 
-	/* If we can't read the file, it's no good.
-	 * If we can't write the file, use it read-only. */
+	/*
+	 * If we can't read the file, it's no good.
+	 * If we can't write the file, use it read-only.
+	 */
 	if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
 		LINFO(curlun, "file not readable: %s\n", filename);
 		goto out;
@@ -646,8 +670,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Sync the file data, don't bother with the metadata.
- * This code was copied from fs/buffer.c:sys_fdatasync(). */
+/*
+ * Sync the file data, don't bother with the metadata.
+ * This code was copied from fs/buffer.c:sys_fdatasync().
+ */
 static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
 {
 	struct file	*filp = curlun->filp;
@@ -689,6 +715,14 @@
 				  : curlun->initially_ro);
 }
 
+static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
+
+	return sprintf(buf, "%u\n", curlun->nofua);
+}
+
 static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
@@ -723,26 +757,47 @@
 	ssize_t		rc = count;
 	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
 	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	int		i;
+	unsigned long	ro;
 
-	if (sscanf(buf, "%d", &i) != 1)
+	if (strict_strtoul(buf, 2, &ro))
 		return -EINVAL;
 
-	/* Allow the write-enable status to change only while the backing file
-	 * is closed. */
+	/*
+	 * Allow the write-enable status to change only while the
+	 * backing file is closed.
+	 */
 	down_read(filesem);
 	if (fsg_lun_is_open(curlun)) {
 		LDBG(curlun, "read-only status change prevented\n");
 		rc = -EBUSY;
 	} else {
-		curlun->ro = !!i;
-		curlun->initially_ro = !!i;
+		curlun->ro = ro;
+		curlun->initially_ro = ro;
 		LDBG(curlun, "read-only status set to %d\n", curlun->ro);
 	}
 	up_read(filesem);
 	return rc;
 }
 
+static ssize_t fsg_store_nofua(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
+	unsigned long	nofua;
+
+	if (strict_strtoul(buf, 2, &nofua))
+		return -EINVAL;
+
+	/* Sync data when switching from async mode to sync */
+	if (!nofua && curlun->nofua)
+		fsg_lun_fsync_sub(curlun);
+
+	curlun->nofua = nofua;
+
+	return count;
+}
+
 static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 1da755a..6bb876d 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -704,17 +704,6 @@
 module_param(host_addr, charp, S_IRUGO);
 MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 
-
-static u8 __init nibble(unsigned char c)
-{
-	if (isdigit(c))
-		return c - '0';
-	c = toupper(c);
-	if (isxdigit(c))
-		return 10 + c - 'A';
-	return 0;
-}
-
 static int get_ether_addr(const char *str, u8 *dev_addr)
 {
 	if (str) {
@@ -725,8 +714,8 @@
 
 			if ((*str == '.') || (*str == ':'))
 				str++;
-			num = nibble(*str++) << 4;
-			num |= (nibble(*str++));
+			num = hex_to_bin(*str++) << 4;
+			num |= hex_to_bin(*str++);
 			dev_addr [i] = num;
 		}
 		if (is_valid_ether_addr(dev_addr))
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 3e8dcb5..01e5354 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -18,6 +18,7 @@
 /* #define VERBOSE_DEBUG */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/delay.h>
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index 288d211..de1deb7 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -308,7 +308,7 @@
  * USB configuration
  */
 
-static int __init
+static int __ref
 webcam_config_bind(struct usb_configuration *c)
 {
 	return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
@@ -330,7 +330,7 @@
 	return 0;
 }
 
-static int __init
+static int __ref
 webcam_bind(struct usb_composite_dev *cdev)
 {
 	int ret;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 807280d..cf353920 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -264,7 +264,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init zero_bind(struct usb_composite_dev *cdev)
+static int __ref zero_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f865be2..2d926ce 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -72,8 +72,9 @@
 	  from ARC, and has since changed hands a few times.
 
 config USB_EHCI_TT_NEWSCHED
-	bool "Improved Transaction Translator scheduling (EXPERIMENTAL)"
-	depends on USB_EHCI_HCD && EXPERIMENTAL
+	bool "Improved Transaction Translator scheduling"
+	depends on USB_EHCI_HCD
+	default y
 	---help---
 	  This changes the periodic scheduling code to fill more of the low
 	  and full speed bandwidth available from the Transaction Translator
@@ -84,9 +85,11 @@
 	  If you have multiple periodic low/fullspeed devices connected to a
 	  highspeed USB hub which is connected to a highspeed USB Host
 	  Controller, and some of those devices will not work correctly
-	  (possibly due to "ENOSPC" or "-28" errors), say Y.
+	  (possibly due to "ENOSPC" or "-28" errors), say Y.  Conversely, if
+	  you have only one such device and it doesn't work, you could try
+	  saying N.
 
-	  If unsure, say N.
+	  If unsure, say Y.
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index faa6174..2baf8a8 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -228,7 +228,7 @@
 	 * the root hub is either suspended or stopped.
 	 */
 	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_prepare_ports_for_controller_suspend(ehci);
+	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 874d200..76b7fd2 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -98,13 +98,18 @@
 			HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
 	} else {
 		ehci_dbg (ehci,
-			"%s hcc_params %04x thresh %d uframes %s%s%s\n",
+			"%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n",
 			label,
 			params,
 			HCC_ISOC_THRES(params),
 			HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
 			HCC_CANPARK(params) ? " park" : "",
-			HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
+			HCC_64BIT_ADDR(params) ? " 64 bit addr" : "",
+			HCC_LPM(params) ? " LPM" : "",
+			HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "",
+			HCC_HW_PREFETCH(params) ? " hw prefetch" : "",
+			HCC_32FRAME_PERIODIC_LIST(params) ?
+				" 32 peridic list" : "");
 	}
 }
 #else
@@ -191,8 +196,9 @@
 dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 {
 	return scnprintf (buf, len,
-		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
+		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s",
 		label, label [0] ? " " : "", status,
+		(status & STS_PPCE_MASK) ? " PPCE" : "",
 		(status & STS_ASS) ? " Async" : "",
 		(status & STS_PSS) ? " Periodic" : "",
 		(status & STS_RECL) ? " Recl" : "",
@@ -210,8 +216,9 @@
 dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 {
 	return scnprintf (buf, len,
-		"%s%sintrenable %02x%s%s%s%s%s%s",
+		"%s%sintrenable %02x%s%s%s%s%s%s%s",
 		label, label [0] ? " " : "", enable,
+		(enable & STS_PPCE_MASK) ? " PPCE" : "",
 		(enable & STS_IAA) ? " IAA" : "",
 		(enable & STS_FATAL) ? " FATAL" : "",
 		(enable & STS_FLR) ? " FLR" : "",
@@ -228,9 +235,15 @@
 dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
 {
 	return scnprintf (buf, len,
-		"%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s",
+		"%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s "
+		"period=%s%s %s",
 		label, label [0] ? " " : "", command,
-		(command & CMD_PARK) ? "park" : "(park)",
+		(command & CMD_HIRD) ? " HIRD" : "",
+		(command & CMD_PPCEE) ? " PPCEE" : "",
+		(command & CMD_FSP) ? " FSP" : "",
+		(command & CMD_ASPE) ? " ASPE" : "",
+		(command & CMD_PSPE) ? " PSPE" : "",
+		(command & CMD_PARK) ? " park" : "(park)",
 		CMD_PARK_CNT (command),
 		(command >> 16) & 0x3f,
 		(command & CMD_LRESET) ? " LReset" : "",
@@ -257,11 +270,22 @@
 	}
 
 	return scnprintf (buf, len,
-		"%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s",
+		"%s%sport:%d status %06x %d %s%s%s%s%s%s "
+		"sig=%s%s%s%s%s%s%s%s%s%s%s",
 		label, label [0] ? " " : "", port, status,
+		status>>25,/*device address */
+		(status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ?
+						" ACK" : "",
+		(status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ?
+						" NYET" : "",
+		(status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ?
+						" STALL" : "",
+		(status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ?
+						" ERR" : "",
 		(status & PORT_POWER) ? " POWER" : "",
 		(status & PORT_OWNER) ? " OWNER" : "",
 		sig,
+		(status & PORT_LPM) ? " LPM" : "",
 		(status & PORT_RESET) ? " RESET" : "",
 		(status & PORT_SUSPEND) ? " SUSPEND" : "",
 		(status & PORT_RESUME) ? " RESUME" : "",
@@ -330,6 +354,13 @@
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
 static int debug_async_open(struct inode *, struct file *);
+static int debug_lpm_open(struct inode *, struct file *);
+static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos);
+static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
+			      size_t count, loff_t *ppos);
+static int debug_lpm_close(struct inode *inode, struct file *file);
+
 static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
 static int debug_close(struct inode *, struct file *);
 
@@ -351,6 +382,13 @@
 	.read		= debug_output,
 	.release	= debug_close,
 };
+static const struct file_operations debug_lpm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_lpm_open,
+	.read		= debug_lpm_read,
+	.write		= debug_lpm_write,
+	.release	= debug_lpm_close,
+};
 
 static struct dentry *ehci_debug_root;
 
@@ -674,7 +712,7 @@
 
 	spin_lock_irqsave (&ehci->lock, flags);
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		size = scnprintf (next, size,
 			"bus %s, device %s\n"
 			"%s\n"
@@ -917,51 +955,127 @@
 	return file->private_data ? 0 : -ENOMEM;
 }
 
+static int debug_lpm_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int debug_lpm_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	/* TODO: show lpm stats */
+	return 0;
+}
+
+static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct usb_hcd		*hcd;
+	struct ehci_hcd		*ehci;
+	char buf[50];
+	size_t len;
+	u32 temp;
+	unsigned long port;
+	u32 __iomem	*portsc ;
+	u32 params;
+
+	hcd = bus_to_hcd(file->private_data);
+	ehci = hcd_to_ehci(hcd);
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+	buf[len] = '\0';
+	if (len > 0 && buf[len - 1] == '\n')
+		buf[len - 1] = '\0';
+
+	if (strncmp(buf, "enable", 5) == 0) {
+		if (strict_strtoul(buf + 7, 10, &port))
+			return -EINVAL;
+		params = ehci_readl(ehci, &ehci->caps->hcs_params);
+		if (port > HCS_N_PORTS(params)) {
+			ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port);
+			return -ENODEV;
+		}
+		portsc = &ehci->regs->port_status[port-1];
+		temp = ehci_readl(ehci, portsc);
+		if (!(temp & PORT_DEV_ADDR)) {
+			ehci_dbg(ehci, "LPM: no device attached\n");
+			return -ENODEV;
+		}
+		temp |= PORT_LPM;
+		ehci_writel(ehci, temp, portsc);
+		printk(KERN_INFO "force enable LPM for port %lu\n", port);
+	} else if (strncmp(buf, "hird=", 5) == 0) {
+		unsigned long hird;
+		if (strict_strtoul(buf + 5, 16, &hird))
+			return -EINVAL;
+		printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
+		temp = ehci_readl(ehci, &ehci->regs->command);
+		temp &= ~CMD_HIRD;
+		temp |= hird << 24;
+		ehci_writel(ehci, temp, &ehci->regs->command);
+	} else if (strncmp(buf, "disable", 7) == 0) {
+		if (strict_strtoul(buf + 8, 10, &port))
+			return -EINVAL;
+		params = ehci_readl(ehci, &ehci->caps->hcs_params);
+		if (port > HCS_N_PORTS(params)) {
+			ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port);
+			return -ENODEV;
+		}
+		portsc = &ehci->regs->port_status[port-1];
+		temp = ehci_readl(ehci, portsc);
+		if (!(temp & PORT_DEV_ADDR)) {
+			ehci_dbg(ehci, "ERR: no device attached\n");
+			return -ENODEV;
+		}
+		temp &= ~PORT_LPM;
+		ehci_writel(ehci, temp, portsc);
+		printk(KERN_INFO "disabled LPM for port %lu\n", port);
+	} else
+		return -EOPNOTSUPP;
+	return count;
+}
+
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
 	struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
 
 	ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root);
 	if (!ehci->debug_dir)
-		goto dir_error;
+		return;
 
-	ehci->debug_async = debugfs_create_file("async", S_IRUGO,
-						ehci->debug_dir, bus,
-						&debug_async_fops);
-	if (!ehci->debug_async)
-		goto async_error;
+	if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus,
+						&debug_async_fops))
+		goto file_error;
 
-	ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
-						   ehci->debug_dir, bus,
-						   &debug_periodic_fops);
-	if (!ehci->debug_periodic)
-		goto periodic_error;
+	if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus,
+						&debug_periodic_fops))
+		goto file_error;
 
-	ehci->debug_registers = debugfs_create_file("registers", S_IRUGO,
-						    ehci->debug_dir, bus,
-						    &debug_registers_fops);
-	if (!ehci->debug_registers)
-		goto registers_error;
+	if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus,
+						    &debug_registers_fops))
+		goto file_error;
+
+	if (!debugfs_create_file("lpm", S_IRUGO|S_IWUGO, ehci->debug_dir, bus,
+						    &debug_lpm_fops))
+		goto file_error;
+
 	return;
 
-registers_error:
-	debugfs_remove(ehci->debug_periodic);
-periodic_error:
-	debugfs_remove(ehci->debug_async);
-async_error:
-	debugfs_remove(ehci->debug_dir);
-dir_error:
-	ehci->debug_periodic = NULL;
-	ehci->debug_async = NULL;
-	ehci->debug_dir = NULL;
+file_error:
+	debugfs_remove_recursive(ehci->debug_dir);
 }
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
 {
-	debugfs_remove(ehci->debug_registers);
-	debugfs_remove(ehci->debug_periodic);
-	debugfs_remove(ehci->debug_async);
-	debugfs_remove(ehci->debug_dir);
+	debugfs_remove_recursive(ehci->debug_dir);
 }
 
 #endif /* STUB_DEBUG_FILES */
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5cd967d..a416421 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -313,7 +313,8 @@
 	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
 	void __iomem *non_ehci = hcd->regs;
 
-	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
+	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
+			device_may_wakeup(dev));
 	if (!fsl_deep_sleep())
 		return 0;
 
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a3ef2a9..34a928d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -36,6 +36,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -78,7 +79,13 @@
 #define	EHCI_TUNE_RL_TT		0
 #define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
 #define	EHCI_TUNE_MULT_TT	1
-#define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
+/*
+ * Some drivers think it's safe to schedule isochronous transfers more than
+ * 256 ms into the future (partly as a result of an old bug in the scheduling
+ * code).  In an attempt to avoid trouble, we will use a minimum scheduling
+ * length of 512 frames instead of 256.
+ */
+#define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
 
 #define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
@@ -100,6 +107,11 @@
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
+/* for link power management(LPM) feature */
+static unsigned int hird;
+module_param(hird, int, S_IRUGO);
+MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
+
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
@@ -304,6 +316,7 @@
 static void ehci_work(struct ehci_hcd *ehci);
 
 #include "ehci-hub.c"
+#include "ehci-lpm.c"
 #include "ehci-mem.c"
 #include "ehci-q.c"
 #include "ehci-sched.c"
@@ -577,6 +590,11 @@
 	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
 		log2_irq_thresh = 0;
 	temp = 1 << (16 + log2_irq_thresh);
+	if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) {
+		ehci->has_ppcd = 1;
+		ehci_dbg(ehci, "enable per-port change event\n");
+		temp |= CMD_PPCEE;
+	}
 	if (HCC_CANPARK(hcc_params)) {
 		/* HW default park == 3, on hardware that supports it (like
 		 * NVidia and ALI silicon), maximizes throughput on the async
@@ -603,10 +621,22 @@
 		default:	BUG();
 		}
 	}
+	if (HCC_LPM(hcc_params)) {
+		/* support link power management EHCI 1.1 addendum */
+		ehci_dbg(ehci, "support lpm\n");
+		ehci->has_lpm = 1;
+		if (hird > 0xf) {
+			ehci_dbg(ehci, "hird %d invalid, use default 0",
+			hird);
+			hird = 0;
+		}
+		temp |= hird << 24;
+	}
 	ehci->command = temp;
 
 	/* Accept arbitrarily long scatter-gather lists */
-	hcd->self.sg_tablesize = ~0;
+	if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+		hcd->self.sg_tablesize = ~0;
 	return 0;
 }
 
@@ -619,7 +649,6 @@
 	u32			hcc_params;
 
 	hcd->uses_new_polling = 1;
-	hcd->poll_rh = 0;
 
 	/* EHCI spec section 4.1 */
 	if ((retval = ehci_reset(ehci)) != 0) {
@@ -764,6 +793,7 @@
 	/* remote wakeup [4.3.1] */
 	if (status & STS_PCD) {
 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
+		u32		ppcd = 0;
 
 		/* kick root hub later */
 		pcd_status = status;
@@ -772,9 +802,18 @@
 		if (!(cmd & CMD_RUN))
 			usb_hcd_resume_root_hub(hcd);
 
+		/* get per-port change detect bits */
+		if (ehci->has_ppcd)
+			ppcd = status >> 16;
+
 		while (i--) {
-			int pstatus = ehci_readl(ehci,
-						 &ehci->regs->port_status [i]);
+			int pstatus;
+
+			/* leverage per-port change bits feature */
+			if (ehci->has_ppcd && !(ppcd & (1 << i)))
+				continue;
+			pstatus = ehci_readl(ehci,
+					 &ehci->regs->port_status[i]);
 
 			if (pstatus & PORT_OWNER)
 				continue;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index e7d3d8d..796ea0c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -107,7 +107,7 @@
 }
 
 static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
-		bool suspending)
+		bool suspending, bool do_wakeup)
 {
 	int		port;
 	u32		temp;
@@ -117,8 +117,7 @@
 	 * when the controller is suspended or resumed.  In all other
 	 * cases they don't need to be changed.
 	 */
-	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup ||
-			device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
+	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
 		return;
 
 	/* clear phy low-power mode before changing wakeup flags */
@@ -167,6 +166,10 @@
 			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
 		}
 	}
+
+	/* Does the root hub have a port wakeup pending? */
+	if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
+		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
 }
 
 static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -316,7 +319,7 @@
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
 	spin_lock_irq (&ehci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		spin_unlock_irq(&ehci->lock);
 		return -ESHUTDOWN;
 	}
@@ -603,6 +606,7 @@
 	u32		mask;
 	int		ports, i, retval = 1;
 	unsigned long	flags;
+	u32		ppcd = 0;
 
 	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
 	if (!HC_IS_RUNNING(hcd->state))
@@ -632,7 +636,15 @@
 
 	/* port N changes (bit N)? */
 	spin_lock_irqsave (&ehci->lock, flags);
+
+	/* get per-port change detect bits */
+	if (ehci->has_ppcd)
+		ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;
+
 	for (i = 0; i < ports; i++) {
+		/* leverage per-port change bits feature */
+		if (ehci->has_ppcd && !(ppcd & (1 << i)))
+			continue;
 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
 
 		/*
@@ -790,6 +802,11 @@
 					  status_reg);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
+			if (ehci->has_lpm) {
+				/* clear PORTSC bits on disconnect */
+				temp &= ~PORT_LPM;
+				temp &= ~PORT_DEV_ADDR;
+			}
 			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
 					status_reg);
 			break;
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
new file mode 100644
index 0000000..b4d4d63
--- /dev/null
+++ b/drivers/usb/host/ehci-lpm.c
@@ -0,0 +1,83 @@
+/* ehci-lpm.c EHCI HCD LPM support code
+ * Copyright (c) 2008 - 2010,  Intel Corporation.
+ * Author: Jacob Pan <jacob.jun.pan@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* this file is part of ehci-hcd.c */
+static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
+{
+	u32 __iomem portsc;
+
+	ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
+	if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
+		ehci_dbg(ehci, "invalid port number %d\n", port_num);
+		return -ENODEV;
+	}
+	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
+	portsc &= ~PORT_DEV_ADDR;
+	portsc |= dev_addr<<25;
+	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
+	return 0;
+}
+
+/*
+ * this function is used to check if the device support LPM
+ * if yes, mark the PORTSC register with PORT_LPM bit
+ */
+static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
+{
+	u32 __iomem	*portsc ;
+	u32 val32;
+	int retval;
+
+	portsc = &ehci->regs->port_status[port-1];
+	val32 = ehci_readl(ehci, portsc);
+	if (!(val32 & PORT_DEV_ADDR)) {
+		ehci_dbg(ehci, "LPM: no device attached\n");
+		return -ENODEV;
+	}
+	val32 |= PORT_LPM;
+	ehci_writel(ehci, val32, portsc);
+	msleep(5);
+	val32 |= PORT_SUSPEND;
+	ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
+	ehci_writel(ehci, val32, portsc);
+	/* wait for ACK */
+	msleep(10);
+	retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
+			PORTSC_SUSPEND_STS_ACK, 125);
+	dbg_port(ehci, "LPM", port, val32);
+	if (retval != -ETIMEDOUT) {
+		ehci_dbg(ehci, "LPM: device ACK for LPM\n");
+		val32 |= PORT_LPM;
+		/*
+		 * now device should be in L1 sleep, let's wake up the device
+		 * so that we can complete enumeration.
+		 */
+		ehci_writel(ehci, val32, portsc);
+		msleep(10);
+		val32 |= PORT_RESUME;
+		ehci_writel(ehci, val32, portsc);
+	} else {
+		ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
+			retval);
+		val32 &= ~PORT_LPM;
+		retval = -ETIMEDOUT;
+		ehci_writel(ehci, val32, portsc);
+	}
+
+	return retval;
+}
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 5450e62..116ae28 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -38,6 +38,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/usb/ulpi.h>
 #include <plat/usb.h>
 
 /*
@@ -236,6 +237,35 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	unsigned reg = 0;
+
+	reg = ULPI_FUNC_CTRL_RESET
+		/* FUNCTION_CTRL_SET register */
+		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
+		/* Write */
+		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
+		/* PORTn */
+		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
+		/* start ULPI access*/
+		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
+
+	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg);
+
+	/* Wait for ULPI access completion */
+	while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI)
+			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			dev_dbg(omap->dev, "phy reset operation timed out\n");
+			break;
+		}
+	}
+}
+
 /* omap_start_ehc
  *	- Start the TI USBHOST controller
  */
@@ -425,6 +455,12 @@
 			gpio_set_value(omap->reset_gpio_port[1], 1);
 	}
 
+	/* Soft reset the PHY using PHY reset command over ULPI */
+	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
+		omap_ehci_soft_phy_reset(omap, 0);
+	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
+		omap_ehci_soft_phy_reset(omap, 1);
+
 	return 0;
 
 err_sys_status:
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index d43d176..58b72d7 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -114,6 +114,7 @@
 		break;
 	case PCI_VENDOR_ID_INTEL:
 		ehci->need_io_watchdog = 0;
+		ehci->fs_i_thresh = 1;
 		if (pdev->device == 0x27cc) {
 			ehci->broken_periodic = 1;
 			ehci_info(ehci, "using broken periodic workaround\n");
@@ -277,7 +278,7 @@
  * Also they depend on separate root hub suspend/resume.
  */
 
-static int ehci_pci_suspend(struct usb_hcd *hcd)
+static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	unsigned long		flags;
@@ -291,7 +292,7 @@
 	 * the root hub is either suspended or stopped.
 	 */
 	spin_lock_irqsave (&ehci->lock, flags);
-	ehci_prepare_ports_for_controller_suspend(ehci);
+	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
@@ -361,6 +362,22 @@
 }
 #endif
 
+static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int rc = 0;
+
+	if (!udev->parent) /* udev is root hub itself, impossible */
+		rc = -1;
+	/* we only support lpm device connected to root hub yet */
+	if (ehci->has_lpm && !udev->parent->parent) {
+		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+		if (!rc)
+			rc = ehci_lpm_check(ehci, udev->portnum);
+	}
+	return rc;
+}
+
 static const struct hc_driver ehci_pci_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"EHCI Host Controller",
@@ -407,6 +424,11 @@
 	.relinquish_port =	ehci_relinquish_port,
 	.port_handed_over =	ehci_port_handed_over,
 
+	/*
+	 * call back when device connected and addressed
+	 */
+	.update_device =	ehci_update_device,
+
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 11a79c4..233c288 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1126,8 +1126,7 @@
 #endif
 
 	spin_lock_irqsave (&ehci->lock, flags);
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &ehci_to_hcd(ehci)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 805ec63..a92526d 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -880,8 +880,7 @@
 
 	spin_lock_irqsave (&ehci->lock, flags);
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			&ehci_to_hcd(ehci)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
 		status = -ESHUTDOWN;
 		goto done_not_linked;
 	}
@@ -1075,15 +1074,6 @@
 		if (stream->ep)
 			stream->ep->hcpriv = NULL;
 
-		if (stream->rescheduled) {
-			ehci_info (ehci, "ep%d%s-iso rescheduled "
-				"%lu times in %lu seconds\n",
-				stream->bEndpointAddress, is_in ? "in" : "out",
-				stream->rescheduled,
-				((jiffies - stream->start)/HZ)
-				);
-		}
-
 		kfree(stream);
 	}
 }
@@ -1396,30 +1386,25 @@
 	struct ehci_iso_stream	*stream
 )
 {
-	u32			now, next, start, period;
+	u32			now, next, start, period, span;
 	int			status;
 	unsigned		mod = ehci->periodic_size << 3;
 	struct ehci_iso_sched	*sched = urb->hcpriv;
-	struct pci_dev		*pdev;
 
-	if (sched->span > (mod - SCHEDULE_SLOP)) {
+	period = urb->interval;
+	span = sched->span;
+	if (!stream->highspeed) {
+		period <<= 3;
+		span <<= 3;
+	}
+
+	if (span > mod - SCHEDULE_SLOP) {
 		ehci_dbg (ehci, "iso request %p too long\n", urb);
 		status = -EFBIG;
 		goto fail;
 	}
 
-	if ((stream->depth + sched->span) > mod) {
-		ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
-			urb, stream->depth, sched->span, mod);
-		status = -EFBIG;
-		goto fail;
-	}
-
-	period = urb->interval;
-	if (!stream->highspeed)
-		period <<= 3;
-
-	now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
+	now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
 
 	/* Typical case: reuse current schedule, stream is still active.
 	 * Hopefully there are no gaps from the host falling behind
@@ -1427,34 +1412,35 @@
 	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
 	 */
 	if (likely (!list_empty (&stream->td_list))) {
-		pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-		start = stream->next_uframe;
+		u32	excess;
 
 		/* For high speed devices, allow scheduling within the
-		 * isochronous scheduling threshold.  For full speed devices,
-		 * don't. (Work around for Intel ICH9 bug.)
+		 * isochronous scheduling threshold.  For full speed devices
+		 * and Intel PCI-based controllers, don't (work around for
+		 * Intel ICH9 bug).
 		 */
-		if (!stream->highspeed &&
-				pdev->vendor == PCI_VENDOR_ID_INTEL)
+		if (!stream->highspeed && ehci->fs_i_thresh)
 			next = now + ehci->i_thresh;
 		else
 			next = now;
 
-		/* Fell behind (by up to twice the slop amount)? */
-		if (((start - next) & (mod - 1)) >=
-				mod - 2 * SCHEDULE_SLOP)
-			start += period * DIV_ROUND_UP(
-					(next - start) & (mod - 1),
-					period);
-
-		/* Tried to schedule too far into the future? */
-		if (unlikely(((start - now) & (mod - 1)) + sched->span
-					>= mod - 2 * SCHEDULE_SLOP)) {
+		/* Fell behind (by up to twice the slop amount)?
+		 * We decide based on the time of the last currently-scheduled
+		 * slot, not the time of the next available slot.
+		 */
+		excess = (stream->next_uframe - period - next) & (mod - 1);
+		if (excess >= mod - 2 * SCHEDULE_SLOP)
+			start = next + excess - mod + period *
+					DIV_ROUND_UP(mod - excess, period);
+		else
+			start = next + excess + period;
+		if (start - now >= mod) {
+			ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
+					urb, start - now - period, period,
+					mod);
 			status = -EFBIG;
 			goto fail;
 		}
-		stream->next_uframe = start;
-		goto ready;
 	}
 
 	/* need to schedule; when's the next (u)frame we could start?
@@ -1463,51 +1449,60 @@
 	 * can also help high bandwidth if the dma and irq loads don't
 	 * jump until after the queue is primed.
 	 */
-	start = SCHEDULE_SLOP + (now & ~0x07);
-	start %= mod;
-	stream->next_uframe = start;
+	else {
+		start = SCHEDULE_SLOP + (now & ~0x07);
 
-	/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
-	/* find a uframe slot with enough bandwidth */
-	for (; start < (stream->next_uframe + period); start++) {
-		int		enough_space;
+		/* find a uframe slot with enough bandwidth */
+		next = start + period;
+		for (; start < next; start++) {
 
-		/* check schedule: enough space? */
-		if (stream->highspeed)
-			enough_space = itd_slot_ok (ehci, mod, start,
-					stream->usecs, period);
-		else {
-			if ((start % 8) >= 6)
-				continue;
-			enough_space = sitd_slot_ok (ehci, mod, stream,
-					start, sched, period);
+			/* check schedule: enough space? */
+			if (stream->highspeed) {
+				if (itd_slot_ok(ehci, mod, start,
+						stream->usecs, period))
+					break;
+			} else {
+				if ((start % 8) >= 6)
+					continue;
+				if (sitd_slot_ok(ehci, mod, stream,
+						start, sched, period))
+					break;
+			}
 		}
 
-		/* schedule it here if there's enough bandwidth */
-		if (enough_space) {
-			stream->next_uframe = start % mod;
-			goto ready;
+		/* no room in the schedule */
+		if (start == next) {
+			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
+				urb, now, now + mod);
+			status = -ENOSPC;
+			goto fail;
 		}
 	}
 
-	/* no room in the schedule */
-	ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n",
-		list_empty (&stream->td_list) ? "" : "re",
-		urb, now, now + mod);
-	status = -ENOSPC;
+	/* Tried to schedule too far into the future? */
+	if (unlikely(start - now + span - period
+				>= mod - 2 * SCHEDULE_SLOP)) {
+		ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
+				urb, start - now, span - period,
+				mod - 2 * SCHEDULE_SLOP);
+		status = -EFBIG;
+		goto fail;
+	}
 
-fail:
-	iso_sched_free (stream, sched);
-	urb->hcpriv = NULL;
-	return status;
+	stream->next_uframe = start & (mod - 1);
 
-ready:
 	/* report high speed start in uframes; full speed, in frames */
 	urb->start_frame = stream->next_uframe;
 	if (!stream->highspeed)
 		urb->start_frame >>= 3;
 	return 0;
+
+ fail:
+	iso_sched_free(stream, sched);
+	urb->hcpriv = NULL;
+	return status;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1602,7 +1597,7 @@
 	struct ehci_iso_sched	*iso_sched = urb->hcpriv;
 	struct ehci_itd		*itd;
 
-	next_uframe = stream->next_uframe % mod;
+	next_uframe = stream->next_uframe & (mod - 1);
 
 	if (unlikely (list_empty(&stream->td_list))) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
@@ -1613,7 +1608,6 @@
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 			urb->interval,
 			next_uframe >> 3, next_uframe & 0x7);
-		stream->start = jiffies;
 	}
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
@@ -1639,14 +1633,13 @@
 		itd_patch(ehci, itd, iso_sched, packet, uframe);
 
 		next_uframe += stream->interval;
-		stream->depth += stream->interval;
-		next_uframe %= mod;
+		next_uframe &= mod - 1;
 		packet++;
 
 		/* link completed itds into the schedule */
 		if (((next_uframe >> 3) != frame)
 				|| packet == urb->number_of_packets) {
-			itd_link (ehci, frame % ehci->periodic_size, itd);
+			itd_link(ehci, frame & (ehci->periodic_size - 1), itd);
 			itd = NULL;
 		}
 	}
@@ -1695,7 +1688,6 @@
 
 		t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
 		itd->hw_transaction [uframe] = 0;
-		stream->depth -= stream->interval;
 
 		/* report transfer status */
 		if (unlikely (t & ISO_ERRS)) {
@@ -1815,8 +1807,7 @@
 
 	/* schedule ... need to lock */
 	spin_lock_irqsave (&ehci->lock, flags);
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &ehci_to_hcd(ehci)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
 		status = -ESHUTDOWN;
 		goto done_not_linked;
 	}
@@ -2024,9 +2015,8 @@
 			"sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
 			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
-			(next_uframe >> 3) % ehci->periodic_size,
+			(next_uframe >> 3) & (ehci->periodic_size - 1),
 			stream->interval, hc32_to_cpu(ehci, stream->splits));
-		stream->start = jiffies;
 	}
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
@@ -2047,13 +2037,12 @@
 		sitd->urb = urb;
 
 		sitd_patch(ehci, stream, sitd, sched, packet);
-		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
+		sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1),
 				sitd);
 
 		next_uframe += stream->interval << 3;
-		stream->depth += stream->interval << 3;
 	}
-	stream->next_uframe = next_uframe % mod;
+	stream->next_uframe = next_uframe & (mod - 1);
 
 	/* don't need that schedule data any more */
 	iso_sched_free (stream, sched);
@@ -2111,7 +2100,6 @@
 		desc->actual_length = desc->length - SITD_LENGTH(t);
 		urb->actual_length += desc->actual_length;
 	}
-	stream->depth -= stream->interval << 3;
 
 	/* handle completion now? */
 	if ((urb_index + 1) != urb->number_of_packets)
@@ -2201,8 +2189,7 @@
 
 	/* schedule ... need to lock */
 	spin_lock_irqsave (&ehci->lock, flags);
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &ehci_to_hcd(ehci)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
 		status = -ESHUTDOWN;
 		goto done_not_linked;
 	}
@@ -2263,7 +2250,7 @@
 	now_uframe = ehci->next_uframe;
 	if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
-		clock_frame = (clock >> 3) % ehci->periodic_size;
+		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
 	} else  {
 		clock = now_uframe + mod - 1;
 		clock_frame = -1;
@@ -2272,7 +2259,7 @@
 		free_cached_lists(ehci);
 		ehci->clock_frame = clock_frame;
 	}
-	clock %= mod;
+	clock &= mod - 1;
 	clock_frame = clock >> 3;
 
 	for (;;) {
@@ -2361,7 +2348,7 @@
 				 * frame is current.
 				 */
 				if (((frame == clock_frame) ||
-				     (((frame + 1) % ehci->periodic_size)
+				     (((frame + 1) & (ehci->periodic_size - 1))
 				      == clock_frame))
 				    && live
 				    && (q.sitd->hw_results &
@@ -2428,7 +2415,8 @@
 					|| ehci->periodic_sched == 0)
 				break;
 			ehci->next_uframe = now_uframe;
-			now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
+			now = ehci_readl(ehci, &ehci->regs->frame_index) &
+					(mod - 1);
 			if (now_uframe == now)
 				break;
 
@@ -2441,7 +2429,7 @@
 			}
 		} else {
 			now_uframe++;
-			now_uframe %= mod;
+			now_uframe &= mod - 1;
 		}
 	}
 }
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 650a687..bde823f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -130,6 +130,7 @@
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		broken_periodic:1;
+	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
@@ -140,7 +141,8 @@
 	#define OHCI_HCCTRL_LEN         0x4
 	__hc32			*ohci_hcctrl_reg;
 	unsigned		has_hostpc:1;
-
+	unsigned		has_lpm:1;  /* support link power management */
+	unsigned		has_ppcd:1; /* support per-port change bits */
 	u8			sbrn;		/* packed release number */
 
 	/* irq statistics */
@@ -154,9 +156,6 @@
 	/* debug files */
 #ifdef DEBUG
 	struct dentry		*debug_dir;
-	struct dentry		*debug_async;
-	struct dentry		*debug_periodic;
-	struct dentry		*debug_registers;
 #endif
 };
 
@@ -401,15 +400,12 @@
 	u32			refcount;
 	u8			bEndpointAddress;
 	u8			highspeed;
-	u16			depth;		/* depth in uframes */
 	struct list_head	td_list;	/* queued itds/sitds */
 	struct list_head	free_list;	/* list of unused itds/sitds */
 	struct usb_device	*udev;
 	struct usb_host_endpoint *ep;
 
 	/* output of (re)scheduling */
-	unsigned long		start;		/* jiffies */
-	unsigned long		rescheduled;
 	int			next_uframe;
 	__hc32			splits;
 
@@ -538,11 +534,11 @@
 
 /* Prepare the PORTSC wakeup flags during controller suspend/resume */
 
-#define ehci_prepare_ports_for_controller_suspend(ehci)		\
-		ehci_adjust_port_wakeup_flags(ehci, true);
+#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)	\
+		ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup);
 
-#define ehci_prepare_ports_for_controller_resume(ehci)		\
-		ehci_adjust_port_wakeup_flags(ehci, false);
+#define ehci_prepare_ports_for_controller_resume(ehci)			\
+		ehci_adjust_port_wakeup_flags(ehci, false, false);
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 35742f8..9bfac65 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -159,7 +159,7 @@
 		goto error_set_cluster_id;
 
 	usb_hcd->uses_new_polling = 1;
-	usb_hcd->poll_rh = 1;
+	set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags);
 	usb_hcd->state = HC_STATE_RUNNING;
 	result = 0;
 out:
@@ -776,7 +776,7 @@
 		goto error_alloc;
 	}
 	usb_hcd->wireless = 1;
-	usb_hcd->flags |= HCD_FLAG_SAW_IRQ;
+	set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags);
 	wusbhc = usb_hcd_to_wusbhc(usb_hcd);
 	hwahc = container_of(wusbhc, struct hwahc, wusbhc);
 	hwahc_init(hwahc);
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index ca0e98d..3e56303 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -1521,7 +1521,7 @@
 			return -ETIMEDOUT;
 		}
 		spin_unlock_irq(&imx21->lock);
-		schedule_timeout(1);
+		schedule_timeout_uninterruptible(1);
 		spin_lock_irq(&imx21->lock);
 	}
 	spin_unlock_irqrestore(&imx21->lock, flags);
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h
index d995351..0f97820 100644
--- a/drivers/usb/host/isp1362.h
+++ b/drivers/usb/host/isp1362.h
@@ -8,29 +8,7 @@
 /*
  * Platform specific compile time options
  */
-#if defined(CONFIG_ARCH_KARO)
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/karo.h>
-
-#define USE_32BIT		1
-
-
-/* These options are mutually eclusive */
-#define USE_PLATFORM_DELAY	1
-#define USE_NDELAY		0
-/*
- * MAX_ROOT_PORTS: Number of downstream ports
- *
- * The chip has two USB ports, one of which can be configured as
- * an USB device port, so the value of this constant is implementation
- * specific.
- */
-#define MAX_ROOT_PORTS		2
-#define DUMMY_DELAY_ACCESS do {} while (0)
-
-/* insert platform specific definitions for other machines here */
-#elif defined(CONFIG_BLACKFIN)
+#if defined(CONFIG_BLACKFIN)
 
 #include <linux/io.h>
 #define USE_32BIT		0
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index dbcafa2..d1a3dfc 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -482,7 +482,6 @@
 	u32 chipid;
 
 	hcd->uses_new_polling = 1;
-	hcd->poll_rh = 0;
 
 	hcd->state = HC_STATE_RUNNING;
 	isp1760_enable_interrupts(hcd);
@@ -1450,7 +1449,7 @@
 	epnum = urb->ep->desc.bEndpointAddress;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) {
+	if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 8ad2441..36abd2b 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -645,7 +645,7 @@
 		hcd->product_desc,
 		hcd_name);
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		size -= scnprintf (next, size,
 			"SUSPENDED (no register access)\n");
 		goto done;
@@ -687,7 +687,7 @@
 	next += temp;
 
 	temp = scnprintf (next, size, "hub poll timer %s\n",
-			ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
+			HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off");
 	size -= temp;
 	next += temp;
 
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 02864a2..c3b4ccc 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -212,7 +212,7 @@
 	spin_lock_irqsave (&ohci->lock, flags);
 
 	/* don't submit to a dead HC */
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		retval = -ENODEV;
 		goto fail;
 	}
@@ -685,7 +685,7 @@
 	}
 
 	/* use rhsc irqs after khubd is fully initialized */
-	hcd->poll_rh = 1;
+	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	hcd->uses_new_polling = 1;
 
 	/* start controller operations */
@@ -822,7 +822,7 @@
 	else if (ints & OHCI_INTR_RD) {
 		ohci_vdbg(ohci, "resume detect\n");
 		ohci_writel(ohci, OHCI_INTR_RD, &regs->intrstatus);
-		hcd->poll_rh = 1;
+		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 		if (ohci->autostop) {
 			spin_lock (&ohci->lock);
 			ohci_rh_resume (ohci);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 65cac8c..cddcda9 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -284,7 +284,7 @@
 
 	spin_lock_irq (&ohci->lock);
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
 		rc = -ESHUTDOWN;
 	else
 		rc = ohci_rh_suspend (ohci, 0);
@@ -302,7 +302,7 @@
 
 	spin_lock_irq (&ohci->lock);
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
 		rc = -ESHUTDOWN;
 	else
 		rc = ohci_rh_resume (ohci);
@@ -355,6 +355,11 @@
 		ohci_readl(ohci, &ohci->regs->intrenable);
 		msleep(20);
 	}
+
+	/* Does the root hub have a port wakeup pending? */
+	if (ohci_readl(ohci, &ohci->regs->intrstatus) &
+			(OHCI_INTR_RD | OHCI_INTR_RHSC))
+		usb_hcd_resume_root_hub(hcd);
 }
 
 /* Carry out polling-, autostop-, and autoresume-related state changes */
@@ -364,7 +369,7 @@
 	int	poll_rh = 1;
 	int	rhsc_enable;
 
-	/* Some broken controllers never turn off RHCS in the interrupt
+	/* Some broken controllers never turn off RHSC in the interrupt
 	 * status register.  For their sake we won't re-enable RHSC
 	 * interrupts if the interrupt bit is already active.
 	 */
@@ -489,7 +494,7 @@
 	unsigned long	flags;
 
 	spin_lock_irqsave (&ohci->lock, flags);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		goto done;
 
 	/* undocumented erratum seen on at least rev D */
@@ -533,8 +538,12 @@
 		}
 	}
 
-	hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
-			any_connected, rhsc_status);
+	if (ohci_root_hub_state_changes(ohci, changed,
+			any_connected, rhsc_status))
+		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	else
+		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+
 
 done:
 	spin_unlock_irqrestore (&ohci->lock, flags);
@@ -701,7 +710,7 @@
 	u32		temp;
 	int		retval = 0;
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
 		return -ESHUTDOWN;
 
 	switch (typeReq) {
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index b8a1148..6bdc8b2 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -392,7 +392,7 @@
 
 #ifdef	CONFIG_PM
 
-static int ohci_pci_suspend(struct usb_hcd *hcd)
+static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	unsigned long	flags;
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 23fd6a8..48ee694 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -93,8 +93,11 @@
 {
 	struct usb_hcd *hcd = ssb_get_drvdata(dev);
 
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 	ssb_device_disable(dev, 0);
 }
@@ -106,10 +109,52 @@
 	int err = -ENOMEM;
 	u32 tmp, flags = 0;
 
-	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
-		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+		return -EOPNOTSUPP;
 
-	ssb_device_enable(dev, flags);
+	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+		/* Put the device into host-mode. */
+		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+		ssb_device_enable(dev, flags);
+	} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+		/*
+		 * USB 2.0 special considerations:
+		 *
+		 * In addition to the standard SSB reset sequence, the Host
+		 * Control Register must be programmed to bring the USB core
+		 * and various phy components out of reset.
+		 */
+		ssb_device_enable(dev, 0);
+		ssb_write32(dev, 0x200, 0x7ff);
+
+		/* Change Flush control reg */
+		tmp = ssb_read32(dev, 0x400);
+		tmp &= ~8;
+		ssb_write32(dev, 0x400, tmp);
+		tmp = ssb_read32(dev, 0x400);
+
+		/* Change Shim control reg */
+		tmp = ssb_read32(dev, 0x304);
+		tmp &= ~0x100;
+		ssb_write32(dev, 0x304, tmp);
+		tmp = ssb_read32(dev, 0x304);
+
+		udelay(1);
+
+		/* Work around for 5354 failures */
+		if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
+			/* Change syn01 reg */
+			tmp = 0x00fe00fe;
+			ssb_write32(dev, 0x894, tmp);
+
+			/* Change syn03 reg */
+			tmp = ssb_read32(dev, 0x89c);
+			tmp |= 0x1;
+			ssb_write32(dev, 0x89c, tmp);
+		}
+	} else
+		ssb_device_enable(dev, 0);
 
 	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
 			dev_name(dev->dev));
@@ -200,6 +245,7 @@
 static const struct ssb_device_id ssb_ohci_table[] = {
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
 	SSB_DEVTABLE_END
 };
 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index f608dfd..d9c85a2 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -1641,8 +1641,7 @@
 #endif
 
 	spin_lock_irqsave(&oxu->lock, flags);
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &oxu_to_hcd(oxu)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
@@ -2209,8 +2208,7 @@
 
 	spin_lock_irqsave(&oxu->lock, flags);
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
-			       &oxu_to_hcd(oxu)->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
 		status = -ESHUTDOWN;
 		goto done;
 	}
@@ -2715,7 +2713,6 @@
 	u32 temp, hcc_params;
 
 	hcd->uses_new_polling = 1;
-	hcd->poll_rh = 0;
 
 	/* EHCI spec section 4.1 */
 	retval = ehci_reset(oxu);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index bcf9f0e..990f06b 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -813,8 +813,11 @@
 #endif
 
 	/* avoid all allocations within spinlocks */
-	if (!hep->hcpriv)
+	if (!hep->hcpriv) {
 		ep = kzalloc(sizeof *ep, mem_flags);
+		if (ep == NULL)
+			return -ENOMEM;
+	}
 
 	spin_lock_irqsave(&sl811->lock, flags);
 
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 98cf0b2..6e7fb5f 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -17,7 +17,6 @@
 
 #include "uhci-hcd.h"
 
-#define uhci_debug_operations (* (const struct file_operations *) NULL)
 static struct dentry *uhci_debugfs_root;
 
 #ifdef DEBUG
@@ -495,18 +494,16 @@
 {
 	struct uhci_hcd *uhci = inode->i_private;
 	struct uhci_debug *up;
-	int ret = -ENOMEM;
 	unsigned long flags;
 
-	lock_kernel();
 	up = kmalloc(sizeof(*up), GFP_KERNEL);
 	if (!up)
-		goto out;
+		return -ENOMEM;
 
 	up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
 	if (!up->data) {
 		kfree(up);
-		goto out;
+		return -ENOMEM;
 	}
 
 	up->size = 0;
@@ -517,10 +514,7 @@
 
 	file->private_data = up;
 
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
+	return 0;
 }
 
 static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence)
@@ -528,9 +522,9 @@
 	struct uhci_debug *up;
 	loff_t new = -1;
 
-	lock_kernel();
 	up = file->private_data;
 
+	/* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */
 	switch (whence) {
 	case 0:
 		new = off;
@@ -539,11 +533,10 @@
 		new = file->f_pos + off;
 		break;
 	}
-	if (new < 0 || new > up->size) {
-		unlock_kernel();
+
+	if (new < 0 || new > up->size)
 		return -EINVAL;
-	}
-	unlock_kernel();
+
 	return (file->f_pos = new);
 }
 
@@ -564,7 +557,6 @@
 	return 0;
 }
 
-#undef uhci_debug_operations
 static const struct file_operations uhci_debug_operations = {
 	.owner =	THIS_MODULE,
 	.open =		uhci_debug_open,
@@ -572,6 +564,7 @@
 	.read =		uhci_debug_read,
 	.release =	uhci_debug_release,
 };
+#define UHCI_DEBUG_OPS
 
 #endif	/* CONFIG_DEBUG_FS */
 
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 6637e52..f52d04d 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -140,7 +140,7 @@
 	uhci->rh_state = UHCI_RH_RESET;
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
-	uhci_to_hcd(uhci)->poll_rh = 0;
+	clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
 
 	uhci->dead = 0;		/* Full reset resurrects the controller */
 }
@@ -176,6 +176,8 @@
  */
 static void configure_hc(struct uhci_hcd *uhci)
 {
+	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
+
 	/* Set the frame length to the default: 1 ms exactly */
 	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
 
@@ -191,8 +193,11 @@
 	mb();
 
 	/* Enable PIRQ */
-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-			USBLEGSUP_DEFAULT);
+	pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+	/* Disable platform-specific non-PME# wakeup */
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+		pci_write_config_byte(pdev, USBRES_INTEL, 0);
 }
 
 
@@ -344,7 +349,10 @@
 	/* If interrupts don't work and remote wakeup is enabled then
 	 * the suspended root hub needs to be polled.
 	 */
-	uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
+	if (!int_enable && wakeup_enable)
+		set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+	else
+		clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
 
 	uhci_scan_schedule(uhci);
 	uhci_fsbr_off(uhci);
@@ -363,7 +371,7 @@
 			uhci->io_addr + USBINTR);
 	mb();
 	uhci->rh_state = UHCI_RH_RUNNING;
-	uhci_to_hcd(uhci)->poll_rh = 1;
+	set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
 }
 
 static void wakeup_rh(struct uhci_hcd *uhci)
@@ -589,7 +597,7 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	int retval = -EBUSY;
 	int i;
-	struct dentry *dentry;
+	struct dentry __maybe_unused *dentry;
 
 	hcd->uses_new_polling = 1;
 
@@ -599,18 +607,16 @@
 	INIT_LIST_HEAD(&uhci->idle_qh_list);
 	init_waitqueue_head(&uhci->waitqh);
 
-	if (DEBUG_CONFIGURED) {
-		dentry = debugfs_create_file(hcd->self.bus_name,
-				S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
-				uhci, &uhci_debug_operations);
-		if (!dentry) {
-			dev_err(uhci_dev(uhci), "couldn't create uhci "
-					"debugfs entry\n");
-			retval = -ENOMEM;
-			goto err_create_debug_entry;
-		}
-		uhci->dentry = dentry;
+#ifdef UHCI_DEBUG_OPS
+	dentry = debugfs_create_file(hcd->self.bus_name,
+			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
+			uhci, &uhci_debug_operations);
+	if (!dentry) {
+		dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n");
+		return -ENOMEM;
 	}
+	uhci->dentry = dentry;
+#endif
 
 	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
@@ -691,7 +697,9 @@
 
 	configure_hc(uhci);
 	uhci->is_initialized = 1;
+	spin_lock_irq(&uhci->lock);
 	start_rh(uhci);
+	spin_unlock_irq(&uhci->lock);
 	return 0;
 
 /*
@@ -722,7 +730,6 @@
 err_alloc_frame:
 	debugfs_remove(uhci->dentry);
 
-err_create_debug_entry:
 	return retval;
 }
 
@@ -731,7 +738,7 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	spin_lock_irq(&uhci->lock);
-	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
+	if (HCD_HW_ACCESSIBLE(hcd) && !uhci->dead)
 		uhci_hc_died(uhci);
 	uhci_scan_schedule(uhci);
 	spin_unlock_irq(&uhci->lock);
@@ -748,7 +755,7 @@
 	int rc = 0;
 
 	spin_lock_irq(&uhci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		rc = -ESHUTDOWN;
 	else if (uhci->dead)
 		;		/* Dead controllers tell no tales */
@@ -775,7 +782,7 @@
 	int rc = 0;
 
 	spin_lock_irq(&uhci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		rc = -ESHUTDOWN;
 	else if (!uhci->dead)
 		wakeup_rh(uhci);
@@ -783,15 +790,16 @@
 	return rc;
 }
 
-static int uhci_pci_suspend(struct usb_hcd *hcd)
+static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
 	int rc = 0;
 
 	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
 
 	spin_lock_irq(&uhci->lock);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
 		goto done_okay;		/* Already suspended or dead */
 
 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
@@ -803,11 +811,15 @@
 	/* All PCI host controllers are required to disable IRQ generation
 	 * at the source, so we must turn off PIRQ.
 	 */
-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
-	mb();
-	hcd->poll_rh = 0;
+	pci_write_config_word(pdev, USBLEGSUP, 0);
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
-	/* FIXME: Enable non-PME# remote wakeup? */
+	/* Enable platform-specific non-PME# wakeup */
+	if (do_wakeup) {
+		if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+			pci_write_config_byte(pdev, USBRES_INTEL,
+					USBPORT1EN | USBPORT2EN);
+	}
 
 done_okay:
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -826,7 +838,6 @@
 	 * even if the controller was dead.
 	 */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	mb();
 
 	spin_lock_irq(&uhci->lock);
 
@@ -834,8 +845,6 @@
 	if (hibernated)
 		uhci_hc_died(uhci);
 
-	/* FIXME: Disable non-PME# remote wakeup? */
-
 	/* The firmware or a boot kernel may have changed the controller
 	 * settings during a system wakeup.  Check it and reconfigure
 	 * to avoid problems.
@@ -845,22 +854,20 @@
 	/* If the controller was dead before, it's back alive now */
 	configure_hc(uhci);
 
-	if (uhci->rh_state == UHCI_RH_RESET) {
-
-		/* The controller had to be reset */
+	/* Tell the core if the controller had to be reset */
+	if (uhci->rh_state == UHCI_RH_RESET)
 		usb_root_hub_lost_power(hcd->self.root_hub);
-		suspend_rh(uhci, UHCI_RH_SUSPENDED);
-	}
 
 	spin_unlock_irq(&uhci->lock);
 
 	/* If interrupts don't work and remote wakeup is enabled then
 	 * the suspended root hub needs to be polled.
 	 */
-	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
-		hcd->poll_rh = 1;
-		usb_hcd_poll_rh_status(hcd);
-	}
+	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
+		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+
+	/* Does the root hub have a port wakeup pending? */
+	usb_hcd_poll_rh_status(hcd);
 	return 0;
 }
 #endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 26bd1b2..49bf279 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -67,12 +67,17 @@
 #define   USBPORTSC_RES3	0x4000	/* reserved, write zeroes */
 #define   USBPORTSC_RES4	0x8000	/* reserved, write zeroes */
 
-/* Legacy support register */
+/* PCI legacy support register */
 #define USBLEGSUP		0xc0
 #define   USBLEGSUP_DEFAULT	0x2000	/* only PIRQ enable set */
 #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
 #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
 
+/* PCI Intel-specific resume-enable register */
+#define USBRES_INTEL		0xc4
+#define   USBPORT1EN		0x01
+#define   USBPORT2EN		0x02
+
 #define UHCI_PTR_BITS		cpu_to_le32(0x000F)
 #define UHCI_PTR_TERM		cpu_to_le32(0x0001)
 #define UHCI_PTR_QH		cpu_to_le32(0x0002)
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 8270055..6d59c0f 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -190,7 +190,7 @@
 	spin_lock_irqsave(&uhci->lock, flags);
 
 	uhci_scan_schedule(uhci);
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
 		goto done;
 	uhci_check_ports(uhci);
 
@@ -200,7 +200,7 @@
 	    case UHCI_RH_SUSPENDING:
 	    case UHCI_RH_SUSPENDED:
 		/* if port change, ask to be resumed */
-		if (status)
+		if (status || uhci->resuming_ports)
 			usb_hcd_resume_root_hub(hcd);
 		break;
 
@@ -246,7 +246,7 @@
 	u16 wPortChange, wPortStatus;
 	unsigned long flags;
 
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
 		return -ETIMEDOUT;
 
 	spin_lock_irqsave(&uhci->lock, flags);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index acd582c..d3ade40 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -565,7 +565,7 @@
 	qh->unlink_frame = uhci->frame_number;
 
 	/* Force an interrupt so we know when the QH is fully unlinked */
-	if (list_empty(&uhci->skel_unlink_qh->node))
+	if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped)
 		uhci_set_next_interrupt(uhci);
 
 	/* Move the QH from its old list to the end of the unlinking list */
@@ -1667,7 +1667,7 @@
 			qh->advance_jiffies = jiffies;
 			goto done;
 		}
-		ret = 0;
+		ret = uhci->is_stopped;
 	}
 
 	/* The queue hasn't advanced; check for timeout */
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index e0d3401..72b6892 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -68,7 +68,7 @@
 	whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN);
 
 	usb_hcd->uses_new_polling = 1;
-	usb_hcd->poll_rh = 1;
+	set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags);
 	usb_hcd->state = HC_STATE_RUNNING;
 
 out:
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index ab5a14f..dc0ab83 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -475,7 +475,7 @@
 			    || (prev_end & (WHCI_PAGE_SIZE-1))
 			    || (dma_addr & (WHCI_PAGE_SIZE-1))
 			    || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) {
-				if (std->len % qset->max_packet != 0)
+				if (std && std->len % qset->max_packet != 0)
 					return -EINVAL;
 				std = qset_new_std(whc, qset, urb, mem_flags);
 				if (std == NULL) {
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 2eb658d..4e51343 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -391,49 +391,6 @@
 	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,
@@ -1112,8 +1069,18 @@
 	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
 
 	/* Set up the endpoint ring */
-	virt_dev->eps[ep_index].new_ring =
-		xhci_ring_alloc(xhci, 1, true, mem_flags);
+	/*
+	 * Isochronous endpoint ring needs bigger size because one isoc URB
+	 * carries multiple packets and it will insert multiple tds to the
+	 * ring.
+	 * This should be replaced with dynamic ring resizing in the future.
+	 */
+	if (usb_endpoint_xfer_isoc(&ep->desc))
+		virt_dev->eps[ep_index].new_ring =
+			xhci_ring_alloc(xhci, 8, true, mem_flags);
+	else
+		virt_dev->eps[ep_index].new_ring =
+			xhci_ring_alloc(xhci, 1, true, mem_flags);
 	if (!virt_dev->eps[ep_index].new_ring) {
 		/* Attempt to use the ring cache */
 		if (virt_dev->num_rings_cached == 0)
@@ -1124,6 +1091,7 @@
 		virt_dev->num_rings_cached--;
 		xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring);
 	}
+	virt_dev->eps[ep_index].skip = false;
 	ep_ring = virt_dev->eps[ep_index].new_ring;
 	ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
 
@@ -1389,6 +1357,22 @@
 	return command;
 }
 
+void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv)
+{
+	int last;
+
+	if (!urb_priv)
+		return;
+
+	last = urb_priv->length - 1;
+	if (last >= 0) {
+		int	i;
+		for (i = 0; i <= last; i++)
+			kfree(urb_priv->td[i]);
+	}
+	kfree(urb_priv);
+}
+
 void xhci_free_command(struct xhci_hcd *xhci,
 		struct xhci_command *command)
 {
@@ -1588,7 +1572,7 @@
 	unsigned int num_tests;
 	int i, ret;
 
-	num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]);
+	num_tests = ARRAY_SIZE(simple_test_vector);
 	for (i = 0; i < num_tests; i++) {
 		ret = xhci_test_trb_in_td(xhci,
 				xhci->event_ring->first_seg,
@@ -1601,7 +1585,7 @@
 			return ret;
 	}
 
-	num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]);
+	num_tests = ARRAY_SIZE(complex_test_vector);
 	for (i = 0; i < num_tests; i++) {
 		ret = xhci_test_trb_in_td(xhci,
 				complex_test_vector[i].input_seg,
@@ -1617,6 +1601,29 @@
 	return 0;
 }
 
+static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
+{
+	u64 temp;
+	dma_addr_t deq;
+
+	deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
+			xhci->event_ring->dequeue);
+	if (deq == 0 && !in_interrupt())
+		xhci_warn(xhci, "WARN something wrong with SW event ring "
+				"dequeue ptr.\n");
+	/* Update HC event ring dequeue pointer */
+	temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+	temp &= ERST_PTR_MASK;
+	/* Don't clear the EHB bit (which is RW1C) because
+	 * there might be more events to service.
+	 */
+	temp &= ~ERST_EHB;
+	xhci_dbg(xhci, "// Write event ring dequeue pointer, "
+			"preserving EHB bit\n");
+	xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+			&xhci->ir_set->erst_dequeue);
+}
+
 
 int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 {
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 11482b6..f7efe02 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -53,6 +53,7 @@
 	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval;
+	u32			temp;
 
 	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
 
@@ -93,6 +94,14 @@
 		return retval;
 	xhci_dbg(xhci, "Reset complete\n");
 
+	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+	if (HCC_64BIT_ADDR(temp)) {
+		xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+	} else {
+		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+	}
+
 	xhci_dbg(xhci, "Calling HCD init\n");
 	/* Initialize HCD and host controller data structures. */
 	retval = xhci_init(hcd);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bfc99a9..bc3f4f4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -301,28 +301,6 @@
 	return 1;
 }
 
-void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
-{
-	u64 temp;
-	dma_addr_t deq;
-
-	deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
-			xhci->event_ring->dequeue);
-	if (deq == 0 && !in_interrupt())
-		xhci_warn(xhci, "WARN something wrong with SW event ring "
-				"dequeue ptr.\n");
-	/* Update HC event ring dequeue pointer */
-	temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
-	temp &= ERST_PTR_MASK;
-	/* Don't clear the EHB bit (which is RW1C) because
-	 * there might be more events to service.
-	 */
-	temp &= ~ERST_EHB;
-	xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
-	xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
-			&xhci->ir_set->erst_dequeue);
-}
-
 /* Ring the host controller doorbell after placing a command on the ring */
 void xhci_ring_cmd_db(struct xhci_hcd *xhci)
 {
@@ -359,11 +337,6 @@
 		field = xhci_readl(xhci, db_addr) & DB_MASK;
 		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.
-		 */
-		xhci_readl(xhci, db_addr);
 	}
 }
 
@@ -419,6 +392,50 @@
 	return cur_seg;
 }
 
+
+static 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.
+ */
+static 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);
+}
+
 /*
  * Move the xHC's endpoint ring dequeue pointer past cur_td.
  * Record the new state of the xHC's endpoint ring dequeue segment,
@@ -578,16 +595,24 @@
 		struct xhci_td *cur_td, int status, char *adjective)
 {
 	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct urb	*urb;
+	struct urb_priv	*urb_priv;
 
-	cur_td->urb->hcpriv = NULL;
-	usb_hcd_unlink_urb_from_ep(hcd, cur_td->urb);
-	xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, cur_td->urb);
+	urb = cur_td->urb;
+	urb_priv = urb->hcpriv;
+	urb_priv->td_cnt++;
 
-	spin_unlock(&xhci->lock);
-	usb_hcd_giveback_urb(hcd, cur_td->urb, status);
-	kfree(cur_td);
-	spin_lock(&xhci->lock);
-	xhci_dbg(xhci, "%s URB given back\n", adjective);
+	/* Only giveback urb when this is the last td in urb */
+	if (urb_priv->td_cnt == urb_priv->length) {
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
+		xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, urb);
+
+		spin_unlock(&xhci->lock);
+		usb_hcd_giveback_urb(hcd, urb, status);
+		xhci_urb_free_priv(xhci, urb_priv);
+		spin_lock(&xhci->lock);
+		xhci_dbg(xhci, "%s URB given back\n", adjective);
+	}
 }
 
 /*
@@ -1132,7 +1157,6 @@
 
 	/* Update event ring dequeue pointer before dropping the lock */
 	inc_deq(xhci, xhci->event_ring, true);
-	xhci_set_hc_event_deq(xhci);
 
 	spin_unlock(&xhci->lock);
 	/* Pass this up to the core */
@@ -1258,6 +1282,421 @@
 }
 
 /*
+ * Finish the td processing, remove the td from td list;
+ * Return 1 if the urb can be given back.
+ */
+static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+	union xhci_trb *event_trb, struct xhci_transfer_event *event,
+	struct xhci_virt_ep *ep, int *status, bool skip)
+{
+	struct xhci_virt_device *xdev;
+	struct xhci_ring *ep_ring;
+	unsigned int slot_id;
+	int ep_index;
+	struct urb *urb = NULL;
+	struct xhci_ep_ctx *ep_ctx;
+	int ret = 0;
+	struct urb_priv	*urb_priv;
+	u32 trb_comp_code;
+
+	slot_id = TRB_TO_SLOT_ID(event->flags);
+	xdev = xhci->devs[slot_id];
+	ep_index = TRB_TO_EP_ID(event->flags) - 1;
+	ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+	ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+	trb_comp_code = GET_COMP_CODE(event->transfer_len);
+
+	if (skip)
+		goto td_cleanup;
+
+	if (trb_comp_code == COMP_STOP_INVAL ||
+			trb_comp_code == COMP_STOP) {
+		/* The Endpoint Stop Command completion will take care of any
+		 * stopped TDs.  A stopped TD may be restarted, so don't update
+		 * the ring dequeue pointer or take this TD off any lists yet.
+		 */
+		ep->stopped_td = td;
+		ep->stopped_trb = event_trb;
+		return 0;
+	} else {
+		if (trb_comp_code == COMP_STALL) {
+			/* The transfer is completed from the driver's
+			 * perspective, but we need to issue a set dequeue
+			 * command for this stalled endpoint to move the dequeue
+			 * pointer past the TD.  We can't do that here because
+			 * the halt condition must be cleared first.  Let the
+			 * USB class driver clear the stall later.
+			 */
+			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
+			 * class driver doesn't call usb_reset_endpoint() unless
+			 * the error is -EPIPE.  Clear the halted status in the
+			 * xHCI hardware manually.
+			 */
+			xhci_cleanup_halted_endpoint(xhci,
+					slot_id, ep_index, ep_ring->stream_id,
+					td, event_trb);
+		} else {
+			/* Update ring dequeue pointer */
+			while (ep_ring->dequeue != td->last_trb)
+				inc_deq(xhci, ep_ring, false);
+			inc_deq(xhci, ep_ring, false);
+		}
+
+td_cleanup:
+		/* Clean up the endpoint's TD list */
+		urb = td->urb;
+		urb_priv = urb->hcpriv;
+
+		/* Do one last check of the actual transfer length.
+		 * If the host controller said we transferred more data than
+		 * the buffer length, urb->actual_length will be a very big
+		 * number (since it's unsigned).  Play it safe and say we didn't
+		 * transfer anything.
+		 */
+		if (urb->actual_length > urb->transfer_buffer_length) {
+			xhci_warn(xhci, "URB transfer length is wrong, "
+					"xHC issue? req. len = %u, "
+					"act. len = %u\n",
+					urb->transfer_buffer_length,
+					urb->actual_length);
+			urb->actual_length = 0;
+			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+				*status = -EREMOTEIO;
+			else
+				*status = 0;
+		}
+		list_del(&td->td_list);
+		/* Was this TD slated to be cancelled but completed anyway? */
+		if (!list_empty(&td->cancelled_td_list))
+			list_del(&td->cancelled_td_list);
+
+		urb_priv->td_cnt++;
+		/* Giveback the urb when all the tds are completed */
+		if (urb_priv->td_cnt == urb_priv->length)
+			ret = 1;
+	}
+
+	return ret;
+}
+
+/*
+ * Process control tds, update urb status and actual_length.
+ */
+static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+	union xhci_trb *event_trb, struct xhci_transfer_event *event,
+	struct xhci_virt_ep *ep, int *status)
+{
+	struct xhci_virt_device *xdev;
+	struct xhci_ring *ep_ring;
+	unsigned int slot_id;
+	int ep_index;
+	struct xhci_ep_ctx *ep_ctx;
+	u32 trb_comp_code;
+
+	slot_id = TRB_TO_SLOT_ID(event->flags);
+	xdev = xhci->devs[slot_id];
+	ep_index = TRB_TO_EP_ID(event->flags) - 1;
+	ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+	ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+	trb_comp_code = GET_COMP_CODE(event->transfer_len);
+
+	xhci_debug_trb(xhci, xhci->event_ring->dequeue);
+	switch (trb_comp_code) {
+	case COMP_SUCCESS:
+		if (event_trb == ep_ring->dequeue) {
+			xhci_warn(xhci, "WARN: Success on ctrl setup TRB "
+					"without IOC set??\n");
+			*status = -ESHUTDOWN;
+		} else if (event_trb != td->last_trb) {
+			xhci_warn(xhci, "WARN: Success on ctrl data TRB "
+					"without IOC set??\n");
+			*status = -ESHUTDOWN;
+		} else {
+			xhci_dbg(xhci, "Successful control transfer!\n");
+			*status = 0;
+		}
+		break;
+	case COMP_SHORT_TX:
+		xhci_warn(xhci, "WARN: short transfer on control ep\n");
+		if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+			*status = -EREMOTEIO;
+		else
+			*status = 0;
+		break;
+	default:
+		if (!xhci_requires_manual_halt_cleanup(xhci,
+					ep_ctx, trb_comp_code))
+			break;
+		xhci_dbg(xhci, "TRB error code %u, "
+				"halted endpoint index = %u\n",
+				trb_comp_code, ep_index);
+		/* else fall through */
+	case COMP_STALL:
+		/* Did we transfer part of the data (middle) phase? */
+		if (event_trb != ep_ring->dequeue &&
+				event_trb != td->last_trb)
+			td->urb->actual_length =
+				td->urb->transfer_buffer_length
+				- TRB_LEN(event->transfer_len);
+		else
+			td->urb->actual_length = 0;
+
+		xhci_cleanup_halted_endpoint(xhci,
+			slot_id, ep_index, 0, td, event_trb);
+		return finish_td(xhci, td, event_trb, event, ep, status, true);
+	}
+	/*
+	 * Did we transfer any data, despite the errors that might have
+	 * happened?  I.e. did we get past the setup stage?
+	 */
+	if (event_trb != ep_ring->dequeue) {
+		/* The event was for the status stage */
+		if (event_trb == td->last_trb) {
+			if (td->urb->actual_length != 0) {
+				/* Don't overwrite a previously set error code
+				 */
+				if ((*status == -EINPROGRESS || *status == 0) &&
+						(td->urb->transfer_flags
+						 & URB_SHORT_NOT_OK))
+					/* Did we already see a short data
+					 * stage? */
+					*status = -EREMOTEIO;
+			} else {
+				td->urb->actual_length =
+					td->urb->transfer_buffer_length;
+			}
+		} else {
+		/* Maybe the event was for the data stage? */
+			if (trb_comp_code != COMP_STOP_INVAL) {
+				/* We didn't stop on a link TRB in the middle */
+				td->urb->actual_length =
+					td->urb->transfer_buffer_length -
+					TRB_LEN(event->transfer_len);
+				xhci_dbg(xhci, "Waiting for status "
+						"stage event\n");
+				return 0;
+			}
+		}
+	}
+
+	return finish_td(xhci, td, event_trb, event, ep, status, false);
+}
+
+/*
+ * Process isochronous tds, update urb packet status and actual_length.
+ */
+static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+	union xhci_trb *event_trb, struct xhci_transfer_event *event,
+	struct xhci_virt_ep *ep, int *status)
+{
+	struct xhci_ring *ep_ring;
+	struct urb_priv *urb_priv;
+	int idx;
+	int len = 0;
+	int skip_td = 0;
+	union xhci_trb *cur_trb;
+	struct xhci_segment *cur_seg;
+	u32 trb_comp_code;
+
+	ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+	trb_comp_code = GET_COMP_CODE(event->transfer_len);
+	urb_priv = td->urb->hcpriv;
+	idx = urb_priv->td_cnt;
+
+	if (ep->skip) {
+		/* The transfer is partly done */
+		*status = -EXDEV;
+		td->urb->iso_frame_desc[idx].status = -EXDEV;
+	} else {
+		/* handle completion code */
+		switch (trb_comp_code) {
+		case COMP_SUCCESS:
+			td->urb->iso_frame_desc[idx].status = 0;
+			xhci_dbg(xhci, "Successful isoc transfer!\n");
+			break;
+		case COMP_SHORT_TX:
+			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+				td->urb->iso_frame_desc[idx].status =
+					 -EREMOTEIO;
+			else
+				td->urb->iso_frame_desc[idx].status = 0;
+			break;
+		case COMP_BW_OVER:
+			td->urb->iso_frame_desc[idx].status = -ECOMM;
+			skip_td = 1;
+			break;
+		case COMP_BUFF_OVER:
+		case COMP_BABBLE:
+			td->urb->iso_frame_desc[idx].status = -EOVERFLOW;
+			skip_td = 1;
+			break;
+		case COMP_STALL:
+			td->urb->iso_frame_desc[idx].status = -EPROTO;
+			skip_td = 1;
+			break;
+		case COMP_STOP:
+		case COMP_STOP_INVAL:
+			break;
+		default:
+			td->urb->iso_frame_desc[idx].status = -1;
+			break;
+		}
+	}
+
+	/* calc actual length */
+	if (ep->skip) {
+		td->urb->iso_frame_desc[idx].actual_length = 0;
+		return finish_td(xhci, td, event_trb, event, ep, status, true);
+	}
+
+	if (trb_comp_code == COMP_SUCCESS || skip_td == 1) {
+		td->urb->iso_frame_desc[idx].actual_length =
+			td->urb->iso_frame_desc[idx].length;
+		td->urb->actual_length +=
+			td->urb->iso_frame_desc[idx].length;
+	} else {
+		for (cur_trb = ep_ring->dequeue,
+		     cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
+		     next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
+			if ((cur_trb->generic.field[3] &
+			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
+			    (cur_trb->generic.field[3] &
+			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
+				len +=
+				    TRB_LEN(cur_trb->generic.field[2]);
+		}
+		len += TRB_LEN(cur_trb->generic.field[2]) -
+			TRB_LEN(event->transfer_len);
+
+		if (trb_comp_code != COMP_STOP_INVAL) {
+			td->urb->iso_frame_desc[idx].actual_length = len;
+			td->urb->actual_length += len;
+		}
+	}
+
+	if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS)
+		*status = 0;
+
+	return finish_td(xhci, td, event_trb, event, ep, status, false);
+}
+
+/*
+ * Process bulk and interrupt tds, update urb status and actual_length.
+ */
+static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+	union xhci_trb *event_trb, struct xhci_transfer_event *event,
+	struct xhci_virt_ep *ep, int *status)
+{
+	struct xhci_ring *ep_ring;
+	union xhci_trb *cur_trb;
+	struct xhci_segment *cur_seg;
+	u32 trb_comp_code;
+
+	ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+	trb_comp_code = GET_COMP_CODE(event->transfer_len);
+
+	switch (trb_comp_code) {
+	case COMP_SUCCESS:
+		/* Double check that the HW transferred everything. */
+		if (event_trb != td->last_trb) {
+			xhci_warn(xhci, "WARN Successful completion "
+					"on short TX\n");
+			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+				*status = -EREMOTEIO;
+			else
+				*status = 0;
+		} else {
+			if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
+				xhci_dbg(xhci, "Successful bulk "
+						"transfer!\n");
+			else
+				xhci_dbg(xhci, "Successful interrupt "
+						"transfer!\n");
+			*status = 0;
+		}
+		break;
+	case COMP_SHORT_TX:
+		if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+			*status = -EREMOTEIO;
+		else
+			*status = 0;
+		break;
+	default:
+		/* Others already handled above */
+		break;
+	}
+	dev_dbg(&td->urb->dev->dev,
+			"ep %#x - asked for %d bytes, "
+			"%d bytes untransferred\n",
+			td->urb->ep->desc.bEndpointAddress,
+			td->urb->transfer_buffer_length,
+			TRB_LEN(event->transfer_len));
+	/* Fast path - was this the last TRB in the TD for this URB? */
+	if (event_trb == td->last_trb) {
+		if (TRB_LEN(event->transfer_len) != 0) {
+			td->urb->actual_length =
+				td->urb->transfer_buffer_length -
+				TRB_LEN(event->transfer_len);
+			if (td->urb->transfer_buffer_length <
+					td->urb->actual_length) {
+				xhci_warn(xhci, "HC gave bad length "
+						"of %d bytes left\n",
+						TRB_LEN(event->transfer_len));
+				td->urb->actual_length = 0;
+				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+					*status = -EREMOTEIO;
+				else
+					*status = 0;
+			}
+			/* Don't overwrite a previously set error code */
+			if (*status == -EINPROGRESS) {
+				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+					*status = -EREMOTEIO;
+				else
+					*status = 0;
+			}
+		} else {
+			td->urb->actual_length =
+				td->urb->transfer_buffer_length;
+			/* Ignore a short packet completion if the
+			 * untransferred length was zero.
+			 */
+			if (*status == -EREMOTEIO)
+				*status = 0;
+		}
+	} else {
+		/* Slow path - walk the list, starting from the dequeue
+		 * pointer, to get the actual length transferred.
+		 */
+		td->urb->actual_length = 0;
+		for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
+				cur_trb != event_trb;
+				next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
+			if ((cur_trb->generic.field[3] &
+			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
+			    (cur_trb->generic.field[3] &
+			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
+				td->urb->actual_length +=
+					TRB_LEN(cur_trb->generic.field[2]);
+		}
+		/* If the ring didn't stop on a Link or No-op TRB, add
+		 * in the actual bytes transferred from the Normal TRB
+		 */
+		if (trb_comp_code != COMP_STOP_INVAL)
+			td->urb->actual_length +=
+				TRB_LEN(cur_trb->generic.field[2]) -
+				TRB_LEN(event->transfer_len);
+	}
+
+	return finish_td(xhci, td, event_trb, event, ep, status, false);
+}
+
+/*
  * If this function returns an error condition, it means it got a Transfer
  * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
  * At this point, the host controller is probably hosed and should be reset.
@@ -1276,10 +1715,11 @@
 	union xhci_trb *event_trb;
 	struct urb *urb = NULL;
 	int status = -EINPROGRESS;
+	struct urb_priv *urb_priv;
 	struct xhci_ep_ctx *ep_ctx;
 	u32 trb_comp_code;
+	int ret = 0;
 
-	xhci_dbg(xhci, "In %s\n", __func__);
 	slot_id = TRB_TO_SLOT_ID(event->flags);
 	xdev = xhci->devs[slot_id];
 	if (!xdev) {
@@ -1293,51 +1733,16 @@
 	ep = &xdev->eps[ep_index];
 	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) {
+	if (!ep_ring ||
+		(ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
 		xhci_err(xhci, "ERROR Transfer event for disabled endpoint "
 				"or incorrect stream ring\n");
 		return -ENODEV;
 	}
 
 	event_dma = event->buffer;
-	/* This TRB should be in the TD at the head of this ring's TD list */
-	xhci_dbg(xhci, "%s - checking for list empty\n", __func__);
-	if (list_empty(&ep_ring->td_list)) {
-		xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
-				TRB_TO_SLOT_ID(event->flags), ep_index);
-		xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
-				(unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
-		xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
-		urb = NULL;
-		goto cleanup;
-	}
-	xhci_dbg(xhci, "%s - getting list entry\n", __func__);
-	td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
-
-	/* Is this a TRB in the currently executing TD? */
-	xhci_dbg(xhci, "%s - looking for TD\n", __func__);
-	event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
-			td->last_trb, event_dma);
-	xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg);
-	if (!event_seg) {
-		/* HC is busted, give up! */
-		xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
-		return -ESHUTDOWN;
-	}
-	event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
-	xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
-			(unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
-	xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
-			lower_32_bits(event->buffer));
-	xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
-			upper_32_bits(event->buffer));
-	xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
-			(unsigned int) event->transfer_len);
-	xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
-			(unsigned int) event->flags);
-
-	/* Look for common error cases */
 	trb_comp_code = GET_COMP_CODE(event->transfer_len);
+	/* Look for common error cases */
 	switch (trb_comp_code) {
 	/* Skip codes that require special handling depending on
 	 * transfer type
@@ -1373,278 +1778,156 @@
 		xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
 		status = -ENOSR;
 		break;
+	case COMP_BW_OVER:
+		xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n");
+		break;
+	case COMP_BUFF_OVER:
+		xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n");
+		break;
+	case COMP_UNDERRUN:
+		/*
+		 * When the Isoch ring is empty, the xHC will generate
+		 * a Ring Overrun Event for IN Isoch endpoint or Ring
+		 * Underrun Event for OUT Isoch endpoint.
+		 */
+		xhci_dbg(xhci, "underrun event on endpoint\n");
+		if (!list_empty(&ep_ring->td_list))
+			xhci_dbg(xhci, "Underrun Event for slot %d ep %d "
+					"still with TDs queued?\n",
+				TRB_TO_SLOT_ID(event->flags), ep_index);
+		goto cleanup;
+	case COMP_OVERRUN:
+		xhci_dbg(xhci, "overrun event on endpoint\n");
+		if (!list_empty(&ep_ring->td_list))
+			xhci_dbg(xhci, "Overrun Event for slot %d ep %d "
+					"still with TDs queued?\n",
+				TRB_TO_SLOT_ID(event->flags), ep_index);
+		goto cleanup;
+	case COMP_MISSED_INT:
+		/*
+		 * When encounter missed service error, one or more isoc tds
+		 * may be missed by xHC.
+		 * Set skip flag of the ep_ring; Complete the missed tds as
+		 * short transfer when process the ep_ring next time.
+		 */
+		ep->skip = true;
+		xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
+		goto cleanup;
 	default:
 		if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
 			status = 0;
 			break;
 		}
-		xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n");
-		urb = NULL;
+		xhci_warn(xhci, "ERROR Unknown event condition, HC probably "
+				"busted\n");
 		goto cleanup;
 	}
-	/* Now update the urb's actual_length and give back to the core */
-	/* Was this a control transfer? */
-	if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
-		xhci_debug_trb(xhci, xhci->event_ring->dequeue);
-		switch (trb_comp_code) {
-		case COMP_SUCCESS:
-			if (event_trb == ep_ring->dequeue) {
-				xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
-				status = -ESHUTDOWN;
-			} else if (event_trb != td->last_trb) {
-				xhci_warn(xhci, "WARN: Success on ctrl data TRB without IOC set??\n");
-				status = -ESHUTDOWN;
-			} else {
-				xhci_dbg(xhci, "Successful control transfer!\n");
-				status = 0;
-			}
-			break;
-		case COMP_SHORT_TX:
-			xhci_warn(xhci, "WARN: short transfer on control ep\n");
-			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-				status = -EREMOTEIO;
-			else
-				status = 0;
-			break;
 
-		default:
-			if (!xhci_requires_manual_halt_cleanup(xhci,
-						ep_ctx, trb_comp_code))
-				break;
-			xhci_dbg(xhci, "TRB error code %u, "
-					"halted endpoint index = %u\n",
-					trb_comp_code, ep_index);
-			/* else fall through */
-		case COMP_STALL:
-			/* Did we transfer part of the data (middle) phase? */
-			if (event_trb != ep_ring->dequeue &&
-					event_trb != td->last_trb)
-				td->urb->actual_length =
-					td->urb->transfer_buffer_length
-					- TRB_LEN(event->transfer_len);
-			else
-				td->urb->actual_length = 0;
-
-			xhci_cleanup_halted_endpoint(xhci,
-					slot_id, ep_index, 0, td, event_trb);
-			goto td_cleanup;
-		}
-		/*
-		 * Did we transfer any data, despite the errors that might have
-		 * happened?  I.e. did we get past the setup stage?
+	do {
+		/* This TRB should be in the TD at the head of this ring's
+		 * TD list.
 		 */
-		if (event_trb != ep_ring->dequeue) {
-			/* The event was for the status stage */
-			if (event_trb == td->last_trb) {
-				if (td->urb->actual_length != 0) {
-					/* Don't overwrite a previously set error code */
-					if ((status == -EINPROGRESS ||
-								status == 0) &&
-							(td->urb->transfer_flags
-							 & URB_SHORT_NOT_OK))
-						/* Did we already see a short data stage? */
-						status = -EREMOTEIO;
-				} else {
-					td->urb->actual_length =
-						td->urb->transfer_buffer_length;
-				}
-			} else {
-			/* Maybe the event was for the data stage? */
-				if (trb_comp_code != COMP_STOP_INVAL) {
-					/* We didn't stop on a link TRB in the middle */
-					td->urb->actual_length =
-						td->urb->transfer_buffer_length -
-						TRB_LEN(event->transfer_len);
-					xhci_dbg(xhci, "Waiting for status stage event\n");
-					urb = NULL;
-					goto cleanup;
-				}
+		if (list_empty(&ep_ring->td_list)) {
+			xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
+					"with no TDs queued?\n",
+				  TRB_TO_SLOT_ID(event->flags), ep_index);
+			xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+			  (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+			xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+			if (ep->skip) {
+				ep->skip = false;
+				xhci_dbg(xhci, "td_list is empty while skip "
+						"flag set. Clear skip flag.\n");
 			}
-		}
-	} else {
-		switch (trb_comp_code) {
-		case COMP_SUCCESS:
-			/* Double check that the HW transferred everything. */
-			if (event_trb != td->last_trb) {
-				xhci_warn(xhci, "WARN Successful completion "
-						"on short TX\n");
-				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-					status = -EREMOTEIO;
-				else
-					status = 0;
-			} else {
-				if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
-					xhci_dbg(xhci, "Successful bulk "
-							"transfer!\n");
-				else
-					xhci_dbg(xhci, "Successful interrupt "
-							"transfer!\n");
-				status = 0;
-			}
-			break;
-		case COMP_SHORT_TX:
-			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-				status = -EREMOTEIO;
-			else
-				status = 0;
-			break;
-		default:
-			/* Others already handled above */
-			break;
-		}
-		dev_dbg(&td->urb->dev->dev,
-				"ep %#x - asked for %d bytes, "
-				"%d bytes untransferred\n",
-				td->urb->ep->desc.bEndpointAddress,
-				td->urb->transfer_buffer_length,
-				TRB_LEN(event->transfer_len));
-		/* Fast path - was this the last TRB in the TD for this URB? */
-		if (event_trb == td->last_trb) {
-			if (TRB_LEN(event->transfer_len) != 0) {
-				td->urb->actual_length =
-					td->urb->transfer_buffer_length -
-					TRB_LEN(event->transfer_len);
-				if (td->urb->transfer_buffer_length <
-						td->urb->actual_length) {
-					xhci_warn(xhci, "HC gave bad length "
-							"of %d bytes left\n",
-							TRB_LEN(event->transfer_len));
-					td->urb->actual_length = 0;
-					if (td->urb->transfer_flags &
-							URB_SHORT_NOT_OK)
-						status = -EREMOTEIO;
-					else
-						status = 0;
-				}
-				/* Don't overwrite a previously set error code */
-				if (status == -EINPROGRESS) {
-					if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-						status = -EREMOTEIO;
-					else
-						status = 0;
-				}
-			} else {
-				td->urb->actual_length = td->urb->transfer_buffer_length;
-				/* Ignore a short packet completion if the
-				 * untransferred length was zero.
-				 */
-				if (status == -EREMOTEIO)
-					status = 0;
-			}
-		} else {
-			/* Slow path - walk the list, starting from the dequeue
-			 * pointer, to get the actual length transferred.
-			 */
-			union xhci_trb *cur_trb;
-			struct xhci_segment *cur_seg;
-
-			td->urb->actual_length = 0;
-			for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
-					cur_trb != event_trb;
-					next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-				if ((cur_trb->generic.field[3] &
-				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
-				    (cur_trb->generic.field[3] &
-				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
-					td->urb->actual_length +=
-						TRB_LEN(cur_trb->generic.field[2]);
-			}
-			/* If the ring didn't stop on a Link or No-op TRB, add
-			 * in the actual bytes transferred from the Normal TRB
-			 */
-			if (trb_comp_code != COMP_STOP_INVAL)
-				td->urb->actual_length +=
-					TRB_LEN(cur_trb->generic.field[2]) -
-					TRB_LEN(event->transfer_len);
-		}
-	}
-	if (trb_comp_code == COMP_STOP_INVAL ||
-			trb_comp_code == COMP_STOP) {
-		/* The Endpoint Stop Command completion will take care of any
-		 * stopped TDs.  A stopped TD may be restarted, so don't update
-		 * the ring dequeue pointer or take this TD off any lists yet.
-		 */
-		ep->stopped_td = td;
-		ep->stopped_trb = event_trb;
-	} else {
-		if (trb_comp_code == COMP_STALL) {
-			/* The transfer is completed from the driver's
-			 * perspective, but we need to issue a set dequeue
-			 * command for this stalled endpoint to move the dequeue
-			 * pointer past the TD.  We can't do that here because
-			 * the halt condition must be cleared first.  Let the
-			 * USB class driver clear the stall later.
-			 */
-			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
-			 * class driver doesn't call usb_reset_endpoint() unless
-			 * the error is -EPIPE.  Clear the halted status in the
-			 * xHCI hardware manually.
-			 */
-			xhci_cleanup_halted_endpoint(xhci,
-					slot_id, ep_index, ep_ring->stream_id, td, event_trb);
-		} else {
-			/* Update ring dequeue pointer */
-			while (ep_ring->dequeue != td->last_trb)
-				inc_deq(xhci, ep_ring, false);
-			inc_deq(xhci, ep_ring, false);
+			ret = 0;
+			goto cleanup;
 		}
 
-td_cleanup:
-		/* Clean up the endpoint's TD list */
-		urb = td->urb;
-		/* Do one last check of the actual transfer length.
-		 * If the host controller said we transferred more data than
-		 * the buffer length, urb->actual_length will be a very big
-		 * number (since it's unsigned).  Play it safe and say we didn't
-		 * transfer anything.
-		 */
-		if (urb->actual_length > urb->transfer_buffer_length) {
-			xhci_warn(xhci, "URB transfer length is wrong, "
-					"xHC issue? req. len = %u, "
-					"act. len = %u\n",
-					urb->transfer_buffer_length,
-					urb->actual_length);
-			urb->actual_length = 0;
-			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-				status = -EREMOTEIO;
-			else
-				status = 0;
+		td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
+		/* Is this a TRB in the currently executing TD? */
+		event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
+				td->last_trb, event_dma);
+		if (event_seg && ep->skip) {
+			xhci_dbg(xhci, "Found td. Clear skip flag.\n");
+			ep->skip = false;
 		}
-		list_del(&td->td_list);
-		/* Was this TD slated to be cancelled but completed anyway? */
-		if (!list_empty(&td->cancelled_td_list))
-			list_del(&td->cancelled_td_list);
+		if (!event_seg &&
+		   (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc))) {
+			/* HC is busted, give up! */
+			xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not "
+					"part of current TD\n");
+			return -ESHUTDOWN;
+		}
 
-		/* Leave the TD around for the reset endpoint function to use
-		 * (but only if it's not a control endpoint, since we already
-		 * queued the Set TR dequeue pointer command for stalled
-		 * control endpoints).
-		 */
-		if (usb_endpoint_xfer_control(&urb->ep->desc) ||
-			(trb_comp_code != COMP_STALL &&
-				trb_comp_code != COMP_BABBLE)) {
-			kfree(td);
+		if (event_seg) {
+			event_trb = &event_seg->trbs[(event_dma -
+					 event_seg->dma) / sizeof(*event_trb)];
+			/*
+			 * No-op TRB should not trigger interrupts.
+			 * If event_trb is a no-op TRB, it means the
+			 * corresponding TD has been cancelled. Just ignore
+			 * the TD.
+			 */
+			if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK)
+					 == TRB_TYPE(TRB_TR_NOOP)) {
+				xhci_dbg(xhci, "event_trb is a no-op TRB. "
+						"Skip it\n");
+				goto cleanup;
+			}
 		}
-		urb->hcpriv = NULL;
-	}
+
+		/* Now update the urb's actual_length and give back to
+		 * the core
+		 */
+		if (usb_endpoint_xfer_control(&td->urb->ep->desc))
+			ret = process_ctrl_td(xhci, td, event_trb, event, ep,
+						 &status);
+		else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc))
+			ret = process_isoc_td(xhci, td, event_trb, event, ep,
+						 &status);
+		else
+			ret = process_bulk_intr_td(xhci, td, event_trb, event,
+						 ep, &status);
+
 cleanup:
-	inc_deq(xhci, xhci->event_ring, true);
-	xhci_set_hc_event_deq(xhci);
+		/*
+		 * Do not update event ring dequeue pointer if ep->skip is set.
+		 * Will roll back to continue process missed tds.
+		 */
+		if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+			inc_deq(xhci, xhci->event_ring, true);
+		}
 
-	/* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
-	if (urb) {
-		usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
-		xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
-				urb, urb->actual_length, status);
-		spin_unlock(&xhci->lock);
-		usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
-		spin_lock(&xhci->lock);
-	}
+		if (ret) {
+			urb = td->urb;
+			urb_priv = urb->hcpriv;
+			/* Leave the TD around for the reset endpoint function
+			 * to use(but only if it's not a control endpoint,
+			 * since we already queued the Set TR dequeue pointer
+			 * command for stalled control endpoints).
+			 */
+			if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+				(trb_comp_code != COMP_STALL &&
+					trb_comp_code != COMP_BABBLE))
+				xhci_urb_free_priv(xhci, urb_priv);
+
+			usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+			xhci_dbg(xhci, "Giveback URB %p, len = %d, "
+					"status = %d\n",
+					urb, urb->actual_length, status);
+			spin_unlock(&xhci->lock);
+			usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+			spin_lock(&xhci->lock);
+		}
+
+	/*
+	 * If ep->skip is set, it means there are missed tds on the
+	 * endpoint ring need to take care of.
+	 * Process them as short transfer until reach the td pointed by
+	 * the event.
+	 */
+	} while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+
 	return 0;
 }
 
@@ -1652,7 +1935,7 @@
  * This function handles all OS-owned events on the event ring.  It may drop
  * xhci->lock between event processing (e.g. to pass up port status changes).
  */
-void xhci_handle_event(struct xhci_hcd *xhci)
+static void xhci_handle_event(struct xhci_hcd *xhci)
 {
 	union xhci_trb *event;
 	int update_ptrs = 1;
@@ -1710,15 +1993,130 @@
 		return;
 	}
 
-	if (update_ptrs) {
-		/* Update SW and HC event ring dequeue pointer */
+	if (update_ptrs)
+		/* Update SW event ring dequeue pointer */
 		inc_deq(xhci, xhci->event_ring, true);
-		xhci_set_hc_event_deq(xhci);
-	}
+
 	/* Are there more items on the event ring? */
 	xhci_handle_event(xhci);
 }
 
+/*
+ * xHCI spec says we can get an interrupt, and if the HC has an error condition,
+ * we might get bad data out of the event ring.  Section 4.10.2.7 has a list of
+ * indicators of an event TRB error, but we check the status *first* to be safe.
+ */
+irqreturn_t xhci_irq(struct usb_hcd *hcd)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	u32 status;
+	union xhci_trb *trb;
+	u64 temp_64;
+	union xhci_trb *event_ring_deq;
+	dma_addr_t deq;
+
+	spin_lock(&xhci->lock);
+	trb = xhci->event_ring->dequeue;
+	/* Check if the xHC generated the interrupt, or the irq is shared */
+	status = xhci_readl(xhci, &xhci->op_regs->status);
+	if (status == 0xffffffff)
+		goto hw_died;
+
+	if (!(status & STS_EINT)) {
+		spin_unlock(&xhci->lock);
+		xhci_warn(xhci, "Spurious interrupt.\n");
+		return IRQ_NONE;
+	}
+	xhci_dbg(xhci, "op reg status = %08x\n", status);
+	xhci_dbg(xhci, "Event ring dequeue ptr:\n");
+	xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
+			(unsigned long long)
+			xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
+			lower_32_bits(trb->link.segment_ptr),
+			upper_32_bits(trb->link.segment_ptr),
+			(unsigned int) trb->link.intr_target,
+			(unsigned int) trb->link.control);
+
+	if (status & STS_FATAL) {
+		xhci_warn(xhci, "WARNING: Host System Error\n");
+		xhci_halt(xhci);
+hw_died:
+		xhci_to_hcd(xhci)->state = HC_STATE_HALT;
+		spin_unlock(&xhci->lock);
+		return -ESHUTDOWN;
+	}
+
+	/*
+	 * Clear the op reg interrupt status first,
+	 * so we can receive interrupts from other MSI-X interrupters.
+	 * Write 1 to clear the interrupt status.
+	 */
+	status |= STS_EINT;
+	xhci_writel(xhci, status, &xhci->op_regs->status);
+	/* FIXME when MSI-X is supported and there are multiple vectors */
+	/* Clear the MSI-X event interrupt status */
+
+	if (hcd->irq != -1) {
+		u32 irq_pending;
+		/* Acknowledge the PCI interrupt */
+		irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+		irq_pending |= 0x3;
+		xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
+	}
+
+	if (xhci->xhc_state & XHCI_STATE_DYING) {
+		xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
+				"Shouldn't IRQs be disabled?\n");
+		/* Clear the event handler busy flag (RW1C);
+		 * the event ring should be empty.
+		 */
+		temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+		xhci_write_64(xhci, temp_64 | ERST_EHB,
+				&xhci->ir_set->erst_dequeue);
+		spin_unlock(&xhci->lock);
+
+		return IRQ_HANDLED;
+	}
+
+	event_ring_deq = xhci->event_ring->dequeue;
+	/* FIXME this should be a delayed service routine
+	 * that clears the EHB.
+	 */
+	xhci_handle_event(xhci);
+
+	temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+	/* If necessary, update the HW's version of the event ring deq ptr. */
+	if (event_ring_deq != xhci->event_ring->dequeue) {
+		deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
+				xhci->event_ring->dequeue);
+		if (deq == 0)
+			xhci_warn(xhci, "WARN something wrong with SW event "
+					"ring dequeue ptr.\n");
+		/* Update HC event ring dequeue pointer */
+		temp_64 &= ERST_PTR_MASK;
+		temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
+	}
+
+	/* Clear the event handler busy flag (RW1C); event ring is empty. */
+	temp_64 |= ERST_EHB;
+	xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
+
+	spin_unlock(&xhci->lock);
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
+{
+	irqreturn_t ret;
+
+	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+
+	ret = xhci_irq(hcd);
+
+	return ret;
+}
+
 /****		Endpoint Ring Operations	****/
 
 /*
@@ -1827,10 +2225,12 @@
 		unsigned int stream_id,
 		unsigned int num_trbs,
 		struct urb *urb,
-		struct xhci_td **td,
+		unsigned int td_index,
 		gfp_t mem_flags)
 {
 	int ret;
+	struct urb_priv *urb_priv;
+	struct xhci_td	*td;
 	struct xhci_ring *ep_ring;
 	struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
 
@@ -1846,24 +2246,29 @@
 			num_trbs, mem_flags);
 	if (ret)
 		return ret;
-	*td = kzalloc(sizeof(struct xhci_td), mem_flags);
-	if (!*td)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&(*td)->td_list);
-	INIT_LIST_HEAD(&(*td)->cancelled_td_list);
 
-	ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
-	if (unlikely(ret)) {
-		kfree(*td);
-		return ret;
+	urb_priv = urb->hcpriv;
+	td = urb_priv->td[td_index];
+
+	INIT_LIST_HEAD(&td->td_list);
+	INIT_LIST_HEAD(&td->cancelled_td_list);
+
+	if (td_index == 0) {
+		ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
+		if (unlikely(ret)) {
+			xhci_urb_free_priv(xhci, urb_priv);
+			urb->hcpriv = NULL;
+			return ret;
+		}
 	}
 
-	(*td)->urb = urb;
-	urb->hcpriv = (void *) (*td);
+	td->urb = urb;
 	/* Add this TD to the tail of the endpoint ring's TD list */
-	list_add_tail(&(*td)->td_list, &ep_ring->td_list);
-	(*td)->start_seg = ep_ring->enq_seg;
-	(*td)->first_trb = ep_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;
+
+	urb_priv->td[td_index] = td;
 
 	return 0;
 }
@@ -2002,6 +2407,7 @@
 {
 	struct xhci_ring *ep_ring;
 	unsigned int num_trbs;
+	struct urb_priv *urb_priv;
 	struct xhci_td *td;
 	struct scatterlist *sg;
 	int num_sgs;
@@ -2022,9 +2428,13 @@
 
 	trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, &td, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (trb_buff_len < 0)
 		return trb_buff_len;
+
+	urb_priv = urb->hcpriv;
+	td = urb_priv->td[0];
+
 	/*
 	 * Don't give the first TRB to the hardware (by toggling the cycle bit)
 	 * until we've finished creating all the other TRBs.  The ring's cycle
@@ -2145,6 +2555,7 @@
 		struct urb *urb, int slot_id, unsigned int ep_index)
 {
 	struct xhci_ring *ep_ring;
+	struct urb_priv *urb_priv;
 	struct xhci_td *td;
 	int num_trbs;
 	struct xhci_generic_trb *start_trb;
@@ -2190,10 +2601,13 @@
 
 	ret = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, &td, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (ret < 0)
 		return ret;
 
+	urb_priv = urb->hcpriv;
+	td = urb_priv->td[0];
+
 	/*
 	 * Don't give the first TRB to the hardware (by toggling the cycle bit)
 	 * until we've finished creating all the other TRBs.  The ring's cycle
@@ -2279,6 +2693,7 @@
 	struct xhci_generic_trb *start_trb;
 	int start_cycle;
 	u32 field, length_field;
+	struct urb_priv *urb_priv;
 	struct xhci_td *td;
 
 	ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
@@ -2306,10 +2721,13 @@
 		num_trbs++;
 	ret = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, &td, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (ret < 0)
 		return ret;
 
+	urb_priv = urb->hcpriv;
+	td = urb_priv->td[0];
+
 	/*
 	 * Don't give the first TRB to the hardware (by toggling the cycle bit)
 	 * until we've finished creating all the other TRBs.  The ring's cycle
@@ -2366,6 +2784,224 @@
 	return 0;
 }
 
+static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
+		struct urb *urb, int i)
+{
+	int num_trbs = 0;
+	u64 addr, td_len, running_total;
+
+	addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);
+	td_len = urb->iso_frame_desc[i].length;
+
+	running_total = TRB_MAX_BUFF_SIZE -
+			(addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+	if (running_total != 0)
+		num_trbs++;
+
+	while (running_total < td_len) {
+		num_trbs++;
+		running_total += TRB_MAX_BUFF_SIZE;
+	}
+
+	return num_trbs;
+}
+
+/* This is for isoc transfer */
+static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+		struct urb *urb, int slot_id, unsigned int ep_index)
+{
+	struct xhci_ring *ep_ring;
+	struct urb_priv *urb_priv;
+	struct xhci_td *td;
+	int num_tds, trbs_per_td;
+	struct xhci_generic_trb *start_trb;
+	bool first_trb;
+	int start_cycle;
+	u32 field, length_field;
+	int running_total, trb_buff_len, td_len, td_remain_len, ret;
+	u64 start_addr, addr;
+	int i, j;
+
+	ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
+
+	num_tds = urb->number_of_packets;
+	if (num_tds < 1) {
+		xhci_dbg(xhci, "Isoc URB with zero packets?\n");
+		return -EINVAL;
+	}
+
+	if (!in_interrupt())
+		dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d),"
+				" addr = %#llx, num_tds = %d\n",
+				urb->ep->desc.bEndpointAddress,
+				urb->transfer_buffer_length,
+				urb->transfer_buffer_length,
+				(unsigned long long)urb->transfer_dma,
+				num_tds);
+
+	start_addr = (u64) urb->transfer_dma;
+	start_trb = &ep_ring->enqueue->generic;
+	start_cycle = ep_ring->cycle_state;
+
+	/* Queue the first TRB, even if it's zero-length */
+	for (i = 0; i < num_tds; i++) {
+		first_trb = true;
+
+		running_total = 0;
+		addr = start_addr + urb->iso_frame_desc[i].offset;
+		td_len = urb->iso_frame_desc[i].length;
+		td_remain_len = td_len;
+
+		trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
+
+		ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
+				urb->stream_id, trbs_per_td, urb, i, mem_flags);
+		if (ret < 0)
+			return ret;
+
+		urb_priv = urb->hcpriv;
+		td = urb_priv->td[i];
+
+		for (j = 0; j < trbs_per_td; j++) {
+			u32 remainder = 0;
+			field = 0;
+
+			if (first_trb) {
+				/* Queue the isoc TRB */
+				field |= TRB_TYPE(TRB_ISOC);
+				/* Assume URB_ISO_ASAP is set */
+				field |= TRB_SIA;
+				if (i > 0)
+					field |= ep_ring->cycle_state;
+				first_trb = false;
+			} else {
+				/* Queue other normal TRBs */
+				field |= TRB_TYPE(TRB_NORMAL);
+				field |= ep_ring->cycle_state;
+			}
+
+			/* Chain all the TRBs together; clear the chain bit in
+			 * the last TRB to indicate it's the last TRB in the
+			 * chain.
+			 */
+			if (j < trbs_per_td - 1) {
+				field |= TRB_CHAIN;
+			} else {
+				td->last_trb = ep_ring->enqueue;
+				field |= TRB_IOC;
+			}
+
+			/* Calculate TRB length */
+			trb_buff_len = TRB_MAX_BUFF_SIZE -
+				(addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+			if (trb_buff_len > td_remain_len)
+				trb_buff_len = td_remain_len;
+
+			remainder = xhci_td_remainder(td_len - running_total);
+			length_field = TRB_LEN(trb_buff_len) |
+				remainder |
+				TRB_INTR_TARGET(0);
+			queue_trb(xhci, ep_ring, false, false,
+				lower_32_bits(addr),
+				upper_32_bits(addr),
+				length_field,
+				/* We always want to know if the TRB was short,
+				 * or we won't get an event when it completes.
+				 * (Unless we use event data TRBs, which are a
+				 * waste of space and HC resources.)
+				 */
+				field | TRB_ISP);
+			running_total += trb_buff_len;
+
+			addr += trb_buff_len;
+			td_remain_len -= trb_buff_len;
+		}
+
+		/* Check TD length */
+		if (running_total != td_len) {
+			xhci_err(xhci, "ISOC TD length unmatch\n");
+			return -EINVAL;
+		}
+	}
+
+	wmb();
+	start_trb->field[3] |= start_cycle;
+
+	ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
+	return 0;
+}
+
+/*
+ * Check transfer ring to guarantee there is enough room for the urb.
+ * Update ISO URB start_frame and interval.
+ * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to
+ * update the urb->start_frame by now.
+ * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input.
+ */
+int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
+		struct urb *urb, int slot_id, unsigned int ep_index)
+{
+	struct xhci_virt_device *xdev;
+	struct xhci_ring *ep_ring;
+	struct xhci_ep_ctx *ep_ctx;
+	int start_frame;
+	int xhci_interval;
+	int ep_interval;
+	int num_tds, num_trbs, i;
+	int ret;
+
+	xdev = xhci->devs[slot_id];
+	ep_ring = xdev->eps[ep_index].ring;
+	ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+
+	num_trbs = 0;
+	num_tds = urb->number_of_packets;
+	for (i = 0; i < num_tds; i++)
+		num_trbs += count_isoc_trbs_needed(xhci, urb, i);
+
+	/* Check the ring to guarantee there is enough room for the whole urb.
+	 * Do not insert any td of the urb to the ring if the check failed.
+	 */
+	ret = prepare_ring(xhci, ep_ring, ep_ctx->ep_info & EP_STATE_MASK,
+				num_trbs, mem_flags);
+	if (ret)
+		return ret;
+
+	start_frame = xhci_readl(xhci, &xhci->run_regs->microframe_index);
+	start_frame &= 0x3fff;
+
+	urb->start_frame = start_frame;
+	if (urb->dev->speed == USB_SPEED_LOW ||
+			urb->dev->speed == USB_SPEED_FULL)
+		urb->start_frame >>= 3;
+
+	xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
+	ep_interval = urb->interval;
+	/* Convert to microframes */
+	if (urb->dev->speed == USB_SPEED_LOW ||
+			urb->dev->speed == USB_SPEED_FULL)
+		ep_interval *= 8;
+	/* FIXME change this to a warning and a suggestion to use the new API
+	 * to set the polling interval (once the API is added).
+	 */
+	if (xhci_interval != ep_interval) {
+		if (!printk_ratelimit())
+			dev_dbg(&urb->dev->dev, "Driver uses different interval"
+					" (%d microframe%s) than xHCI "
+					"(%d microframe%s)\n",
+					ep_interval,
+					ep_interval == 1 ? "" : "s",
+					xhci_interval,
+					xhci_interval == 1 ? "" : "s");
+		urb->interval = xhci_interval;
+		/* Convert back to frames for LS/FS devices */
+		if (urb->dev->speed == USB_SPEED_LOW ||
+				urb->dev->speed == USB_SPEED_FULL)
+			urb->interval /= 8;
+	}
+	return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+}
+
 /****		Command Ring Operations		****/
 
 /* Generic function for queueing a command TRB on the command ring.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3998f72..d5c550e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -20,6 +20,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/pci.h>
 #include <linux/irq.h>
 #include <linux/log2.h>
 #include <linux/module.h>
@@ -171,22 +172,84 @@
 	return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
 }
 
-
-#if 0
-/* Set up MSI-X table for entry 0 (may claim other entries later) */
-static int xhci_setup_msix(struct xhci_hcd *xhci)
+/*
+ * Free IRQs
+ * free all IRQs request
+ */
+static void xhci_free_irq(struct xhci_hcd *xhci)
 {
-	int ret;
+	int i;
 	struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
 
-	xhci->msix_count = 0;
-	/* XXX: did I do this right?  ixgbe does kcalloc for more than one */
-	xhci->msix_entries = kmalloc(sizeof(struct msix_entry), GFP_KERNEL);
+	/* return if using legacy interrupt */
+	if (xhci_to_hcd(xhci)->irq >= 0)
+		return;
+
+	if (xhci->msix_entries) {
+		for (i = 0; i < xhci->msix_count; i++)
+			if (xhci->msix_entries[i].vector)
+				free_irq(xhci->msix_entries[i].vector,
+						xhci_to_hcd(xhci));
+	} else if (pdev->irq >= 0)
+		free_irq(pdev->irq, xhci_to_hcd(xhci));
+
+	return;
+}
+
+/*
+ * Set up MSI
+ */
+static int xhci_setup_msi(struct xhci_hcd *xhci)
+{
+	int ret;
+	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+
+	ret = pci_enable_msi(pdev);
+	if (ret) {
+		xhci_err(xhci, "failed to allocate MSI entry\n");
+		return ret;
+	}
+
+	ret = request_irq(pdev->irq, (irq_handler_t)xhci_msi_irq,
+				0, "xhci_hcd", xhci_to_hcd(xhci));
+	if (ret) {
+		xhci_err(xhci, "disable MSI interrupt\n");
+		pci_disable_msi(pdev);
+	}
+
+	return ret;
+}
+
+/*
+ * Set up MSI-X
+ */
+static int xhci_setup_msix(struct xhci_hcd *xhci)
+{
+	int i, ret = 0;
+	struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+
+	/*
+	 * calculate number of msi-x vectors supported.
+	 * - HCS_MAX_INTRS: the max number of interrupts the host can handle,
+	 *   with max number of interrupters based on the xhci HCSPARAMS1.
+	 * - num_online_cpus: maximum msi-x vectors per CPUs core.
+	 *   Add additional 1 vector to ensure always available interrupt.
+	 */
+	xhci->msix_count = min(num_online_cpus() + 1,
+				HCS_MAX_INTRS(xhci->hcs_params1));
+
+	xhci->msix_entries =
+		kmalloc((sizeof(struct msix_entry))*xhci->msix_count,
+				GFP_KERNEL);
 	if (!xhci->msix_entries) {
 		xhci_err(xhci, "Failed to allocate MSI-X entries\n");
 		return -ENOMEM;
 	}
-	xhci->msix_entries[0].entry = 0;
+
+	for (i = 0; i < xhci->msix_count; i++) {
+		xhci->msix_entries[i].entry = i;
+		xhci->msix_entries[i].vector = 0;
+	}
 
 	ret = pci_enable_msix(pdev, xhci->msix_entries, xhci->msix_count);
 	if (ret) {
@@ -194,20 +257,19 @@
 		goto free_entries;
 	}
 
-	/*
-	 * Pass the xhci pointer value as the request_irq "cookie".
-	 * If more irqs are added, this will need to be unique for each one.
-	 */
-	ret = request_irq(xhci->msix_entries[0].vector, &xhci_irq, 0,
-			"xHCI", xhci_to_hcd(xhci));
-	if (ret) {
-		xhci_err(xhci, "Failed to allocate MSI-X interrupt\n");
-		goto disable_msix;
+	for (i = 0; i < xhci->msix_count; i++) {
+		ret = request_irq(xhci->msix_entries[i].vector,
+				(irq_handler_t)xhci_msi_irq,
+				0, "xhci_hcd", xhci_to_hcd(xhci));
+		if (ret)
+			goto disable_msix;
 	}
-	xhci_dbg(xhci, "Finished setting up MSI-X\n");
-	return 0;
+
+	return ret;
 
 disable_msix:
+	xhci_err(xhci, "disable MSI-X interrupt\n");
+	xhci_free_irq(xhci);
 	pci_disable_msix(pdev);
 free_entries:
 	kfree(xhci->msix_entries);
@@ -215,21 +277,23 @@
 	return ret;
 }
 
-/* XXX: code duplication; can xhci_setup_msix call this? */
 /* Free any IRQs and disable MSI-X */
 static void xhci_cleanup_msix(struct xhci_hcd *xhci)
 {
 	struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-	if (!xhci->msix_entries)
-		return;
 
-	free_irq(xhci->msix_entries[0].vector, xhci);
-	pci_disable_msix(pdev);
-	kfree(xhci->msix_entries);
-	xhci->msix_entries = NULL;
-	xhci_dbg(xhci, "Finished cleaning up MSI-X\n");
+	xhci_free_irq(xhci);
+
+	if (xhci->msix_entries) {
+		pci_disable_msix(pdev);
+		kfree(xhci->msix_entries);
+		xhci->msix_entries = NULL;
+	} else {
+		pci_disable_msi(pdev);
+	}
+
+	return;
 }
-#endif
 
 /*
  * Initialize memory for HCD and xHC (one-time init).
@@ -257,100 +321,8 @@
 	return retval;
 }
 
-/*
- * Called in interrupt context when there might be work
- * queued on the event ring
- *
- * xhci->lock must be held by caller.
- */
-static void xhci_work(struct xhci_hcd *xhci)
-{
-	u32 temp;
-	u64 temp_64;
-
-	/*
-	 * Clear the op reg interrupt status first,
-	 * so we can receive interrupts from other MSI-X interrupters.
-	 * Write 1 to clear the interrupt status.
-	 */
-	temp = xhci_readl(xhci, &xhci->op_regs->status);
-	temp |= STS_EINT;
-	xhci_writel(xhci, temp, &xhci->op_regs->status);
-	/* FIXME when MSI-X is supported and there are multiple vectors */
-	/* Clear the MSI-X event interrupt status */
-
-	/* Acknowledge the interrupt */
-	temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
-	temp |= 0x3;
-	xhci_writel(xhci, temp, &xhci->ir_set->irq_pending);
-	/* Flush posted writes */
-	xhci_readl(xhci, &xhci->ir_set->irq_pending);
-
-	if (xhci->xhc_state & XHCI_STATE_DYING)
-		xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
-				"Shouldn't IRQs be disabled?\n");
-	else
-		/* FIXME this should be a delayed service routine
-		 * that clears the EHB.
-		 */
-		xhci_handle_event(xhci);
-
-	/* Clear the event handler busy flag (RW1C); the event ring should be empty. */
-	temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
-	xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
-	/* Flush posted writes -- FIXME is this necessary? */
-	xhci_readl(xhci, &xhci->ir_set->irq_pending);
-}
-
 /*-------------------------------------------------------------------------*/
 
-/*
- * xHCI spec says we can get an interrupt, and if the HC has an error condition,
- * we might get bad data out of the event ring.  Section 4.10.2.7 has a list of
- * indicators of an event TRB error, but we check the status *first* to be safe.
- */
-irqreturn_t xhci_irq(struct usb_hcd *hcd)
-{
-	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-	u32 temp, temp2;
-	union xhci_trb *trb;
-
-	spin_lock(&xhci->lock);
-	trb = xhci->event_ring->dequeue;
-	/* Check if the xHC generated the interrupt, or the irq is shared */
-	temp = xhci_readl(xhci, &xhci->op_regs->status);
-	temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
-	if (temp == 0xffffffff && temp2 == 0xffffffff)
-		goto hw_died;
-
-	if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
-		spin_unlock(&xhci->lock);
-		return IRQ_NONE;
-	}
-	xhci_dbg(xhci, "op reg status = %08x\n", temp);
-	xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
-	xhci_dbg(xhci, "Event ring dequeue ptr:\n");
-	xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
-			(unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
-			lower_32_bits(trb->link.segment_ptr),
-			upper_32_bits(trb->link.segment_ptr),
-			(unsigned int) trb->link.intr_target,
-			(unsigned int) trb->link.control);
-
-	if (temp & STS_FATAL) {
-		xhci_warn(xhci, "WARNING: Host System Error\n");
-		xhci_halt(xhci);
-hw_died:
-		xhci_to_hcd(xhci)->state = HC_STATE_HALT;
-		spin_unlock(&xhci->lock);
-		return -ESHUTDOWN;
-	}
-
-	xhci_work(xhci);
-	spin_unlock(&xhci->lock);
-
-	return IRQ_HANDLED;
-}
 
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
 void xhci_event_ring_work(unsigned long arg)
@@ -423,21 +395,36 @@
 {
 	u32 temp;
 	u64 temp_64;
+	u32 ret;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
 	void (*doorbell)(struct xhci_hcd *) = NULL;
 
 	hcd->uses_new_polling = 1;
-	hcd->poll_rh = 0;
 
 	xhci_dbg(xhci, "xhci_run\n");
-#if 0	/* FIXME: MSI not setup yet */
-	/* Do this at the very last minute */
-	ret = xhci_setup_msix(xhci);
-	if (!ret)
-		return ret;
+	/* unregister the legacy interrupt */
+	if (hcd->irq)
+		free_irq(hcd->irq, hcd);
+	hcd->irq = -1;
 
-	return -ENOSYS;
-#endif
+	ret = xhci_setup_msix(xhci);
+	if (ret)
+		/* fall back to msi*/
+		ret = xhci_setup_msi(xhci);
+
+	if (ret) {
+		/* fall back to legacy interrupt*/
+		ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+					hcd->irq_descr, hcd);
+		if (ret) {
+			xhci_err(xhci, "request interrupt %d failed\n",
+					pdev->irq);
+			return ret;
+		}
+		hcd->irq = pdev->irq;
+	}
+
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
 	init_timer(&xhci->event_ring_timer);
 	xhci->event_ring_timer.data = (unsigned long) xhci;
@@ -495,7 +482,6 @@
 		return -ENODEV;
 	}
 
-	xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
 	if (doorbell)
 		(*doorbell)(xhci);
 	if (xhci->quirks & XHCI_NEC_HOST)
@@ -522,11 +508,9 @@
 	spin_lock_irq(&xhci->lock);
 	xhci_halt(xhci);
 	xhci_reset(xhci);
+	xhci_cleanup_msix(xhci);
 	spin_unlock_irq(&xhci->lock);
 
-#if 0	/* No MSI yet */
-	xhci_cleanup_msix(xhci);
-#endif
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
 	/* Tell the event ring poll function not to reschedule */
 	xhci->zombie = 1;
@@ -560,11 +544,8 @@
 
 	spin_lock_irq(&xhci->lock);
 	xhci_halt(xhci);
-	spin_unlock_irq(&xhci->lock);
-
-#if 0
 	xhci_cleanup_msix(xhci);
-#endif
+	spin_unlock_irq(&xhci->lock);
 
 	xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n",
 		    xhci_readl(xhci, &xhci->op_regs->status));
@@ -720,7 +701,8 @@
 	unsigned long flags;
 	int ret = 0;
 	unsigned int slot_id, ep_index;
-
+	struct urb_priv	*urb_priv;
+	int size, i;
 
 	if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
 		return -EINVAL;
@@ -734,12 +716,36 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		if (!in_interrupt())
 			xhci_dbg(xhci, "urb submitted during PCI suspend\n");
 		ret = -ESHUTDOWN;
 		goto exit;
 	}
+
+	if (usb_endpoint_xfer_isoc(&urb->ep->desc))
+		size = urb->number_of_packets;
+	else
+		size = 1;
+
+	urb_priv = kzalloc(sizeof(struct urb_priv) +
+				  size * sizeof(struct xhci_td *), mem_flags);
+	if (!urb_priv)
+		return -ENOMEM;
+
+	for (i = 0; i < size; i++) {
+		urb_priv->td[i] = kzalloc(sizeof(struct xhci_td), mem_flags);
+		if (!urb_priv->td[i]) {
+			urb_priv->length = i;
+			xhci_urb_free_priv(xhci, urb_priv);
+			return -ENOMEM;
+		}
+	}
+
+	urb_priv->length = size;
+	urb_priv->td_cnt = 0;
+	urb->hcpriv = urb_priv;
+
 	if (usb_endpoint_xfer_control(&urb->ep->desc)) {
 		/* Check to see if the max packet size for the default control
 		 * endpoint changed during FS device enumeration
@@ -788,11 +794,18 @@
 				slot_id, ep_index);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 	} else {
-		ret = -EINVAL;
+		spin_lock_irqsave(&xhci->lock, flags);
+		if (xhci->xhc_state & XHCI_STATE_DYING)
+			goto dying;
+		ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
+				slot_id, ep_index);
+		spin_unlock_irqrestore(&xhci->lock, flags);
 	}
 exit:
 	return ret;
 dying:
+	xhci_urb_free_priv(xhci, urb_priv);
+	urb->hcpriv = NULL;
 	xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
 			"non-responsive xHCI host.\n",
 			urb->ep->desc.bEndpointAddress, urb);
@@ -800,6 +813,47 @@
 	return -ESHUTDOWN;
 }
 
+/* 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.
+ */
+static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
+		struct urb *urb)
+{
+	unsigned int slot_id;
+	unsigned int ep_index;
+	unsigned int stream_id;
+	struct xhci_virt_ep *ep;
+
+	slot_id = urb->dev->slot_id;
+	ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+	stream_id = urb->stream_id;
+	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;
+}
+
 /*
  * Remove the URB's TD from the endpoint ring.  This may cause the HC to stop
  * USB transfers, potentially stopping in the middle of a TRB buffer.  The HC
@@ -834,9 +888,10 @@
 int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
 	unsigned long flags;
-	int ret;
+	int ret, i;
 	u32 temp;
 	struct xhci_hcd *xhci;
+	struct urb_priv	*urb_priv;
 	struct xhci_td *td;
 	unsigned int ep_index;
 	struct xhci_ring *ep_ring;
@@ -851,12 +906,12 @@
 	temp = xhci_readl(xhci, &xhci->op_regs->status);
 	if (temp == 0xffffffff) {
 		xhci_dbg(xhci, "HW died, freeing TD.\n");
-		td = (struct xhci_td *) urb->hcpriv;
+		urb_priv = urb->hcpriv;
 
 		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
-		kfree(td);
+		xhci_urb_free_priv(xhci, urb_priv);
 		return ret;
 	}
 	if (xhci->xhc_state & XHCI_STATE_DYING) {
@@ -884,9 +939,14 @@
 
 	xhci_dbg(xhci, "Endpoint ring:\n");
 	xhci_debug_ring(xhci, ep_ring);
-	td = (struct xhci_td *) urb->hcpriv;
 
-	list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
+	urb_priv = urb->hcpriv;
+
+	for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
+		td = urb_priv->td[i];
+		list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
+	}
+
 	/* Queue a stop endpoint command, but only if this is
 	 * the first cancellation to be handled.
 	 */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6c7e343..34a60d9 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -720,6 +720,14 @@
 	struct timer_list	stop_cmd_timer;
 	int			stop_cmds_pending;
 	struct xhci_hcd		*xhci;
+	/*
+	 * Sometimes the xHC can not process isochronous endpoint ring quickly
+	 * enough, and it will miss some isoc tds on the ring and generate
+	 * a Missed Service Error Event.
+	 * Set skip flag when receive a Missed Service Error Event and
+	 * process the missed tds on the endpoint ring.
+	 */
+	bool			skip;
 };
 
 struct xhci_virt_device {
@@ -911,6 +919,9 @@
 /* Control transfer TRB specific fields */
 #define TRB_DIR_IN		(1<<16)
 
+/* Isochronous TRB specific fields */
+#define TRB_SIA			(1<<31)
+
 struct xhci_generic_trb {
 	u32 field[4];
 };
@@ -1082,6 +1093,12 @@
 	dma_addr_t *sp_dma_buffers;
 };
 
+struct urb_priv {
+	int	length;
+	int	td_cnt;
+	struct	xhci_td	*td[0];
+};
+
 /*
  * Each segment table entry is 4*32bits long.  1K seems like an ok size:
  * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
@@ -1130,7 +1147,7 @@
 	int		page_size;
 	/* Valid values are 12 to 20, inclusive */
 	int		page_shift;
-	/* only one MSI vector for now, but might need more later */
+	/* msi-x vectors */
 	int		msix_count;
 	struct msix_entry	*msix_entries;
 	/* data structures */
@@ -1327,11 +1344,6 @@
 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,
@@ -1339,6 +1351,7 @@
 struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
 		bool allocate_in_ctx, bool allocate_completion,
 		gfp_t mem_flags);
+void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv);
 void xhci_free_command(struct xhci_hcd *xhci,
 		struct xhci_command *command);
 
@@ -1358,6 +1371,7 @@
 void xhci_shutdown(struct usb_hcd *hcd);
 int xhci_get_frame(struct usb_hcd *hcd);
 irqreturn_t xhci_irq(struct usb_hcd *hcd);
+irqreturn_t xhci_msi_irq(int 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,
@@ -1386,8 +1400,6 @@
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
 void *xhci_setup_one_noop(struct xhci_hcd *xhci);
-void xhci_handle_event(struct xhci_hcd *xhci);
-void xhci_set_hc_event_deq(struct xhci_hcd *xhci);
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
 int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id);
@@ -1401,6 +1413,8 @@
 		int slot_id, unsigned int ep_index);
 int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
 		int slot_id, unsigned int ep_index);
+int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
+		struct urb *urb, int slot_id, unsigned int ep_index);
 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id, bool command_must_succeed);
 int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 82e1663..aecf380 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -650,7 +650,7 @@
 
 static int ftdi_elan_release(struct inode *inode, struct file *file)
 {
-        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        struct usb_ftdi *ftdi = file->private_data;
         if (ftdi == NULL)
                 return -ENODEV;
         up(&ftdi->sw_lock);        /* decrement the count on our device */
@@ -673,7 +673,7 @@
         int bytes_read = 0;
         int retry_on_empty = 10;
         int retry_on_timeout = 5;
-        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        struct usb_ftdi *ftdi = file->private_data;
         if (ftdi->disconnected > 0) {
                 return -ENODEV;
         }
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 7dc9d3c..2de49c8 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/usb/iowarrior.h>
 
@@ -61,6 +61,7 @@
 MODULE_LICENSE("GPL");
 
 /* Module parameters */
+static DEFINE_MUTEX(iowarrior_mutex);
 static int debug = 0;
 module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
@@ -282,7 +283,7 @@
 	int read_idx;
 	int offset;
 
-	dev = (struct iowarrior *)file->private_data;
+	dev = file->private_data;
 
 	/* verify that the device wasn't unplugged */
 	if (dev == NULL || !dev->present)
@@ -348,7 +349,7 @@
 	char *buf = NULL;	/* for IOW24 and IOW56 we need a buffer */
 	struct urb *int_out_urb = NULL;
 
-	dev = (struct iowarrior *)file->private_data;
+	dev = file->private_data;
 
 	mutex_lock(&dev->mutex);
 	/* verify that the device wasn't unplugged */
@@ -483,7 +484,7 @@
 	int retval;
 	int io_res;		/* checks for bytes read/written and copy_to/from_user results */
 
-	dev = (struct iowarrior *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL) {
 		return -ENODEV;
 	}
@@ -493,7 +494,7 @@
 		return -ENOMEM;
 
 	/* lock this object */
-	lock_kernel();
+	mutex_lock(&iowarrior_mutex);
 	mutex_lock(&dev->mutex);
 
 	/* verify that the device wasn't unplugged */
@@ -585,7 +586,7 @@
 error_out:
 	/* unlock the device */
 	mutex_unlock(&dev->mutex);
-	unlock_kernel();
+	mutex_unlock(&iowarrior_mutex);
 	kfree(buffer);
 	return retval;
 }
@@ -602,12 +603,12 @@
 
 	dbg("%s", __func__);
 
-	lock_kernel();
+	mutex_lock(&iowarrior_mutex);
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&iowarrior_driver, subminor);
 	if (!interface) {
-		unlock_kernel();
+		mutex_unlock(&iowarrior_mutex);
 		err("%s - error, can't find device for minor %d", __func__,
 		    subminor);
 		return -ENODEV;
@@ -617,7 +618,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&iowarrior_open_disc_lock);
-		unlock_kernel();
+		mutex_unlock(&iowarrior_mutex);
 		return -ENODEV;
 	}
 
@@ -644,7 +645,7 @@
 
 out:
 	mutex_unlock(&dev->mutex);
-	unlock_kernel();
+	mutex_unlock(&iowarrior_mutex);
 	return retval;
 }
 
@@ -656,7 +657,7 @@
 	struct iowarrior *dev;
 	int retval = 0;
 
-	dev = (struct iowarrior *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL) {
 		return -ENODEV;
 	}
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 8547bf9..6482c6e 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -448,7 +448,7 @@
 
 	dbg(2, "%s: enter", __func__);
 
-	dev = (struct lego_usb_tower *)file->private_data;
+	dev = file->private_data;
 
 	if (dev == NULL) {
 		dbg(1, "%s: object is NULL", __func__);
@@ -597,7 +597,7 @@
 
 	dbg(2, "%s: enter, count = %Zd", __func__, count);
 
-	dev = (struct lego_usb_tower *)file->private_data;
+	dev = file->private_data;
 
 	/* lock this object */
 	if (mutex_lock_interruptible(&dev->lock)) {
@@ -686,7 +686,7 @@
 
 	dbg(2, "%s: enter, count = %Zd", __func__, count);
 
-	dev = (struct lego_usb_tower *)file->private_data;
+	dev = file->private_data;
 
 	/* lock this object */
 	if (mutex_lock_interruptible(&dev->lock)) {
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index a85771b..cc13ae6 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -32,7 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/errno.h>
 #include <linux/random.h>
 #include <linux/poll.h>
@@ -72,6 +72,7 @@
 	struct mutex lock;          /* general race avoidance */
 };
 
+static DEFINE_MUTEX(rio500_mutex);
 static struct rio_usb_data rio_instance;
 
 static int open_rio(struct inode *inode, struct file *file)
@@ -79,12 +80,12 @@
 	struct rio_usb_data *rio = &rio_instance;
 
 	/* against disconnect() */
-	lock_kernel();
+	mutex_lock(&rio500_mutex);
 	mutex_lock(&(rio->lock));
 
 	if (rio->isopen || !rio->present) {
 		mutex_unlock(&(rio->lock));
-		unlock_kernel();
+		mutex_unlock(&rio500_mutex);
 		return -EBUSY;
 	}
 	rio->isopen = 1;
@@ -94,7 +95,7 @@
 	mutex_unlock(&(rio->lock));
 
 	dev_info(&rio->rio_dev->dev, "Rio opened.\n");
-	unlock_kernel();
+	mutex_unlock(&rio500_mutex);
 
 	return 0;
 }
@@ -491,7 +492,7 @@
 	struct rio_usb_data *rio = usb_get_intfdata (intf);
 
 	usb_set_intfdata (intf, NULL);
-	lock_kernel();
+	mutex_lock(&rio500_mutex);
 	if (rio) {
 		usb_deregister_dev(intf, &usb_rio_class);
 
@@ -501,7 +502,7 @@
 			/* better let it finish - the release will do whats needed */
 			rio->rio_dev = NULL;
 			mutex_unlock(&(rio->lock));
-			unlock_kernel();
+			mutex_unlock(&rio500_mutex);
 			return;
 		}
 		kfree(rio->ibuf);
@@ -512,7 +513,7 @@
 		rio->present = 0;
 		mutex_unlock(&(rio->lock));
 	}
-	unlock_kernel();
+	mutex_unlock(&rio500_mutex);
 }
 
 static const struct usb_device_id rio_table[] = {
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index d25814c..70d00e9 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2487,7 +2487,7 @@
 {
 	struct sisusb_usb_data *sisusb;
 
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+	if (!(sisusb = file->private_data))
 		return -ENODEV;
 
 	mutex_lock(&sisusb->lock);
@@ -2519,7 +2519,7 @@
 	u16 buf16;
 	u32 buf32, address;
 
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+	if (!(sisusb = file->private_data))
 		return -ENODEV;
 
 	mutex_lock(&sisusb->lock);
@@ -2661,7 +2661,7 @@
 	u16 buf16;
 	u32 buf32, address;
 
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+	if (!(sisusb = file->private_data))
 		return -ENODEV;
 
 	mutex_lock(&sisusb->lock);
@@ -2804,7 +2804,7 @@
 	struct sisusb_usb_data *sisusb;
 	loff_t ret;
 
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+	if (!(sisusb = file->private_data))
 		return -ENODEV;
 
 	mutex_lock(&sisusb->lock);
@@ -2969,7 +2969,7 @@
 	long retval = 0;
 	u32 __user *argp = (u32 __user *)arg;
 
-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+	if (!(sisusb = file->private_data))
 		return -ENODEV;
 
 	mutex_lock(&sisusb->lock);
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 7828c76..d00dde1 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
@@ -30,6 +29,7 @@
 #define IOCTL_GET_DRV_VERSION	2
 
 
+static DEFINE_MUTEX(lcd_mutex);
 static const struct usb_device_id id_table[] = {
 	{ .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
 	{ },
@@ -74,12 +74,12 @@
 	struct usb_interface *interface;
 	int subminor, r;
 
-	lock_kernel();
+	mutex_lock(&lcd_mutex);
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&lcd_driver, subminor);
 	if (!interface) {
-		unlock_kernel();
+		mutex_unlock(&lcd_mutex);
 		err ("USBLCD: %s - error, can't find device for minor %d",
 		     __func__, subminor);
 		return -ENODEV;
@@ -89,7 +89,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&open_disc_mutex);
-		unlock_kernel();
+		mutex_unlock(&lcd_mutex);
 		return -ENODEV;
 	}
 
@@ -101,13 +101,13 @@
 	r = usb_autopm_get_interface(interface);
 	if (r < 0) {
 		kref_put(&dev->kref, lcd_delete);
-		unlock_kernel();
+		mutex_unlock(&lcd_mutex);
 		return r;
 	}
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
-	unlock_kernel();
+	mutex_unlock(&lcd_mutex);
 
 	return 0;
 }
@@ -116,7 +116,7 @@
 {
 	struct usb_lcd *dev;
 
-	dev = (struct usb_lcd *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL)
 		return -ENODEV;
 
@@ -132,7 +132,7 @@
 	int retval = 0;
 	int bytes_read;
 
-	dev = (struct usb_lcd *)file->private_data;
+	dev = file->private_data;
 
 	/* do a blocking bulk read to get data from the device */
 	retval = usb_bulk_msg(dev->udev, 
@@ -158,20 +158,20 @@
 	u16 bcdDevice;
 	char buf[30];
 
-	dev = (struct usb_lcd *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL)
 		return -ENODEV;
 	
 	switch (cmd) {
 	case IOCTL_GET_HARD_VERSION:
-		lock_kernel();
+		mutex_lock(&lcd_mutex);
 		bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
 		sprintf(buf,"%1d%1d.%1d%1d",
 			(bcdDevice & 0xF000)>>12,
 			(bcdDevice & 0xF00)>>8,
 			(bcdDevice & 0xF0)>>4,
 			(bcdDevice & 0xF));
-		unlock_kernel();
+		mutex_unlock(&lcd_mutex);
 		if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
 			return -EFAULT;
 		break;
@@ -217,7 +217,7 @@
 	struct urb *urb = NULL;
 	char *buf = NULL;
 	
-	dev = (struct usb_lcd *)file->private_data;
+	dev = file->private_data;
 	
 	/* verify that we actually have some data to write */
 	if (count == 0)
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 16dffe9..eef370e 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -136,7 +136,7 @@
 					iso_out = e;
 			}
 		}
-		if ((in && out)  ||  (iso_in && iso_out))
+		if ((in && out)  ||  iso_in || iso_out)
 			goto found;
 	}
 	return -EINVAL;
@@ -162,6 +162,9 @@
 		dev->in_iso_pipe = usb_rcvisocpipe (udev,
 				iso_in->desc.bEndpointAddress
 					& USB_ENDPOINT_NUMBER_MASK);
+	}
+
+	if (iso_out) {
 		dev->iso_out = &iso_out->desc;
 		dev->out_iso_pipe = usb_sndisocpipe (udev,
 				iso_out->desc.bEndpointAddress
@@ -1378,7 +1381,6 @@
 			break;
 		}
 	}
-	simple_free_urb (urb);
 
 	ctx->pending--;
 	if (ctx->pending == 0) {
@@ -1495,6 +1497,7 @@
 			}
 
 			simple_free_urb (urbs [i]);
+			urbs[i] = NULL;
 			context.pending--;
 			context.submit_error = 1;
 			break;
@@ -1504,6 +1507,10 @@
 
 	wait_for_completion (&context.done);
 
+	for (i = 0; i < param->sglen; i++) {
+		if (urbs[i])
+			simple_free_urb(urbs[i]);
+	}
 	/*
 	 * Isochronous transfers are expected to fail sometimes.  As an
 	 * arbitrary limit, we will report an error if any submissions
@@ -1548,6 +1555,7 @@
  * off just killing the userspace task and waiting for it to exit.
  */
 
+/* No BKL needed */
 static int
 usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
 {
@@ -2170,7 +2178,7 @@
 	.name =		"usbtest",
 	.id_table =	id_table,
 	.probe =	usbtest_probe,
-	.ioctl =	usbtest_ioctl,
+	.unlocked_ioctl = usbtest_ioctl,
 	.disconnect =	usbtest_disconnect,
 	.suspend =	usbtest_suspend,
 	.resume =	usbtest_resume,
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 61c76b1..44cb37b 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -646,17 +646,14 @@
 	size_t size;
 	int rc;
 
-	lock_kernel();
 	mutex_lock(&mon_lock);
 	if ((mbus = mon_bus_lookup(iminor(inode))) == NULL) {
 		mutex_unlock(&mon_lock);
-		unlock_kernel();
 		return -ENODEV;
 	}
 	if (mbus != &mon_bus0 && mbus->u_bus == NULL) {
 		printk(KERN_ERR TAG ": consistency error on open\n");
 		mutex_unlock(&mon_lock);
-		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -689,7 +686,6 @@
 
 	file->private_data = rp;
 	mutex_unlock(&mon_lock);
-	unlock_kernel();
 	return 0;
 
 err_allocbuff:
@@ -698,7 +694,6 @@
 	kfree(rp);
 err_alloc:
 	mutex_unlock(&mon_lock);
-	unlock_kernel();
 	return rc;
 }
 
@@ -954,7 +949,7 @@
 
 /*
  */
-static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct mon_reader_bin *rp = file->private_data;
 	// struct mon_bus* mbus = rp->r.m_bus;
@@ -1009,7 +1004,7 @@
 
 		mutex_lock(&rp->fetch_lock);
 		spin_lock_irqsave(&rp->b_lock, flags);
-		mon_free_buff(rp->b_vec, size/CHUNK_SIZE);
+		mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
 		kfree(rp->b_vec);
 		rp->b_vec  = vec;
 		rp->b_size = size;
@@ -1094,19 +1089,6 @@
 	return ret;
 }
 
-static long mon_bin_unlocked_ioctl(struct file *file, unsigned int cmd,
-				   unsigned long arg)
-{
-	int ret;
-
-	lock_kernel();
-	ret = mon_bin_ioctl(file, cmd, arg);
-	unlock_kernel();
-
-	return ret;
-}
-
-
 #ifdef CONFIG_COMPAT
 static long mon_bin_compat_ioctl(struct file *file,
     unsigned int cmd, unsigned long arg)
@@ -1250,7 +1232,7 @@
 	.read =		mon_bin_read,
 	/* .write =	mon_text_write, */
 	.poll =		mon_bin_poll,
-	.unlocked_ioctl = mon_bin_unlocked_ioctl,
+	.unlocked_ioctl = mon_bin_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	mon_bin_compat_ioctl,
 #endif
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 3b795c5..540c766 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -704,7 +704,6 @@
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (int_usb & MUSB_INTR_CONNECT) {
 		struct usb_hcd *hcd = musb_to_hcd(musb);
-		void __iomem *mbase = musb->mregs;
 
 		handled = IRQ_HANDLED;
 		musb->is_active = 1;
@@ -717,9 +716,9 @@
 		if (is_peripheral_active(musb)) {
 			/* REVISIT HNP; just force disconnect */
 		}
-		musb_writew(mbase, MUSB_INTRTXE, musb->epmask);
-		musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe);
-		musb_writeb(mbase, MUSB_INTRUSBE, 0xf7);
+		musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
+		musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+		musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
 #endif
 		musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
 					|USB_PORT_STAT_HIGH_SPEED
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index bba76af..c79a5e3 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -92,29 +92,29 @@
 	{ "LS_EOF1",		0x7E,	8 },
 	{ "SOFT_RST",		0x7F,	8 },
 	{ "DMA_CNTLch0",	0x204,	16 },
-	{ "DMA_ADDRch0",	0x208,	16 },
-	{ "DMA_COUNTch0",	0x20C,	16 },
+	{ "DMA_ADDRch0",	0x208,	32 },
+	{ "DMA_COUNTch0",	0x20C,	32 },
 	{ "DMA_CNTLch1",	0x214,	16 },
-	{ "DMA_ADDRch1",	0x218,	16 },
-	{ "DMA_COUNTch1",	0x21C,	16 },
+	{ "DMA_ADDRch1",	0x218,	32 },
+	{ "DMA_COUNTch1",	0x21C,	32 },
 	{ "DMA_CNTLch2",	0x224,	16 },
-	{ "DMA_ADDRch2",	0x228,	16 },
-	{ "DMA_COUNTch2",	0x22C,	16 },
+	{ "DMA_ADDRch2",	0x228,	32 },
+	{ "DMA_COUNTch2",	0x22C,	32 },
 	{ "DMA_CNTLch3",	0x234,	16 },
-	{ "DMA_ADDRch3",	0x238,	16 },
-	{ "DMA_COUNTch3",	0x23C,	16 },
+	{ "DMA_ADDRch3",	0x238,	32 },
+	{ "DMA_COUNTch3",	0x23C,	32 },
 	{ "DMA_CNTLch4",	0x244,	16 },
-	{ "DMA_ADDRch4",	0x248,	16 },
-	{ "DMA_COUNTch4",	0x24C,	16 },
+	{ "DMA_ADDRch4",	0x248,	32 },
+	{ "DMA_COUNTch4",	0x24C,	32 },
 	{ "DMA_CNTLch5",	0x254,	16 },
-	{ "DMA_ADDRch5",	0x258,	16 },
-	{ "DMA_COUNTch5",	0x25C,	16 },
+	{ "DMA_ADDRch5",	0x258,	32 },
+	{ "DMA_COUNTch5",	0x25C,	32 },
 	{ "DMA_CNTLch6",	0x264,	16 },
-	{ "DMA_ADDRch6",	0x268,	16 },
-	{ "DMA_COUNTch6",	0x26C,	16 },
+	{ "DMA_ADDRch6",	0x268,	32 },
+	{ "DMA_COUNTch6",	0x26C,	32 },
 	{ "DMA_CNTLch7",	0x274,	16 },
-	{ "DMA_ADDRch7",	0x278,	16 },
-	{ "DMA_COUNTch7",	0x27C,	16 },
+	{ "DMA_ADDRch7",	0x278,	32 },
+	{ "DMA_COUNTch7",	0x27C,	32 },
 	{  }	/* Terminating Entry */
 };
 
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 21b9788..59bef8f 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -402,6 +402,9 @@
 					musb->g.a_alt_hnp_support = 1;
 					break;
 #endif
+				case USB_DEVICE_DEBUG_MODE:
+					handled = 0;
+					break;
 stall:
 				default:
 					handled = -EINVAL;
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 92e85e0..43233c3 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -244,7 +244,7 @@
 
 	spin_lock_irqsave(&musb->lock, flags);
 
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+	if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) {
 		spin_unlock_irqrestore(&musb->lock, flags);
 		return -ESHUTDOWN;
 	}
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index dc66e43..6dc107f 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -173,10 +173,7 @@
 	musb_channel->max_packet_sz = packet_sz;
 	channel->status = MUSB_DMA_STATUS_BUSY;
 
-	if ((mode == 1) && (len >= packet_sz))
-		configure_channel(channel, packet_sz, 1, dma_addr, len);
-	else
-		configure_channel(channel, packet_sz, 0, dma_addr, len);
+	configure_channel(channel, packet_sz, mode, dma_addr, len);
 
 	return true;
 }
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e06d65e..2111a24 100644
--- 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 <plat/mux.h>
-
 #include "musb_core.h"
 #include "omap2430.h"
 
@@ -194,10 +192,6 @@
 	u32 l;
 	struct omap_musb_board_data *data = board_data;
 
-#if defined(CONFIG_ARCH_OMAP2430)
-	omap_cfg_reg(AE5_2430_USB0HS_STP);
-#endif
-
 	/* We require some kind of external transceiver, hooked
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 3d2d3e5..3b12895 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -49,8 +49,6 @@
 	  Enable this to support ULPI connected USB OTG transceivers which
 	  are likely found on embedded boards.
 
-	  The only chip currently supported is NXP's ISP1504
-
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
 	depends on TWL4030_CORE && REGULATOR_TWL4030
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index d331b22..ccc8195 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -31,30 +31,110 @@
 
 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
 
-#define TR_FLAG(flags, a, b)	(((flags) & a) ? b : 0)
-
 /* ULPI hardcoded IDs, used for probing */
 static unsigned int ulpi_ids[] = {
 	ULPI_ID(0x04cc, 0x1504),	/* NXP ISP1504 */
+	ULPI_ID(0x0424, 0x0006),        /* SMSC USB3319 */
 };
 
-static int ulpi_set_flags(struct otg_transceiver *otg)
+static int ulpi_set_otg_flags(struct otg_transceiver *otg)
+{
+	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
+			     ULPI_OTG_CTRL_DM_PULLDOWN;
+
+	if (otg->flags & ULPI_OTG_ID_PULLUP)
+		flags |= ULPI_OTG_CTRL_ID_PULLUP;
+
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for Dp/DmPulldown is enabled.
+	 */
+	if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS)
+		flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
+
+	if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS)
+		flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
+
+	if (otg->flags & ULPI_OTG_EXTVBUSIND)
+		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
+
+	return otg_io_write(otg, flags, ULPI_OTG_CTRL);
+}
+
+static int ulpi_set_fc_flags(struct otg_transceiver *otg)
 {
 	unsigned int flags = 0;
 
-	if (otg->flags & USB_OTG_PULLUP_ID)
-		flags |= ULPI_OTG_CTRL_ID_PULLUP;
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for XcvrSelect is Full Speed.
+	 */
+	if (otg->flags & ULPI_FC_HS)
+		flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
+	else if (otg->flags & ULPI_FC_LS)
+		flags |= ULPI_FUNC_CTRL_LOW_SPEED;
+	else if (otg->flags & ULPI_FC_FS4LS)
+		flags |= ULPI_FUNC_CTRL_FS4LS;
+	else
+		flags |= ULPI_FUNC_CTRL_FULL_SPEED;
 
-	if (otg->flags & USB_OTG_PULLDOWN_DM)
-		flags |= ULPI_OTG_CTRL_DM_PULLDOWN;
+	if (otg->flags & ULPI_FC_TERMSEL)
+		flags |= ULPI_FUNC_CTRL_TERMSELECT;
 
-	if (otg->flags & USB_OTG_PULLDOWN_DP)
-		flags |= ULPI_OTG_CTRL_DP_PULLDOWN;
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for OpMode is Normal Operation.
+	 */
+	if (otg->flags & ULPI_FC_OP_NODRV)
+		flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+	else if (otg->flags & ULPI_FC_OP_DIS_NRZI)
+		flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
+	else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP)
+		flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
+	else
+		flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
 
-	if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR)
-		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for SuspendM is Powered.
+	 */
+	flags |= ULPI_FUNC_CTRL_SUSPENDM;
 
-	return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL));
+	return otg_io_write(otg, flags, ULPI_FUNC_CTRL);
+}
+
+static int ulpi_set_ic_flags(struct otg_transceiver *otg)
+{
+	unsigned int flags = 0;
+
+	if (otg->flags & ULPI_IC_AUTORESUME)
+		flags |= ULPI_IFC_CTRL_AUTORESUME;
+
+	if (otg->flags & ULPI_IC_EXTVBUS_INDINV)
+		flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
+
+	if (otg->flags & ULPI_IC_IND_PASSTHRU)
+		flags |= ULPI_IFC_CTRL_PASSTHRU;
+
+	if (otg->flags & ULPI_IC_PROTECT_DIS)
+		flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
+
+	return otg_io_write(otg, flags, ULPI_IFC_CTRL);
+}
+
+static int ulpi_set_flags(struct otg_transceiver *otg)
+{
+	int ret;
+
+	ret = ulpi_set_otg_flags(otg);
+	if (ret)
+		return ret;
+
+	ret = ulpi_set_ic_flags(otg);
+	if (ret)
+		return ret;
+
+	return ulpi_set_fc_flags(otg);
 }
 
 static int ulpi_init(struct otg_transceiver *otg)
@@ -81,6 +161,31 @@
 	return -ENODEV;
 }
 
+static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+	unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL);
+
+	if (!host) {
+		otg->host = NULL;
+		return 0;
+	}
+
+	otg->host = host;
+
+	flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
+		   ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
+		   ULPI_IFC_CTRL_CARKITMODE);
+
+	if (otg->flags & ULPI_IC_6PIN_SERIAL)
+		flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
+	else if (otg->flags & ULPI_IC_3PIN_SERIAL)
+		flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
+	else if (otg->flags & ULPI_IC_CARKIT)
+		flags |= ULPI_IFC_CTRL_CARKITMODE;
+
+	return otg_io_write(otg, flags, ULPI_IFC_CTRL);
+}
+
 static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
 {
 	unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL);
@@ -88,14 +193,14 @@
 	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
 
 	if (on) {
-		if (otg->flags & USB_OTG_DRV_VBUS)
+		if (otg->flags & ULPI_OTG_DRVVBUS)
 			flags |= ULPI_OTG_CTRL_DRVVBUS;
 
-		if (otg->flags & USB_OTG_DRV_VBUS_EXT)
+		if (otg->flags & ULPI_OTG_DRVVBUS_EXT)
 			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
 	}
 
-	return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL));
+	return otg_io_write(otg, flags, ULPI_OTG_CTRL);
 }
 
 struct otg_transceiver *
@@ -112,6 +217,7 @@
 	otg->flags	= flags;
 	otg->io_ops	= ops;
 	otg->init	= ulpi_init;
+	otg->set_host	= ulpi_set_host;
 	otg->set_vbus	= ulpi_set_vbus;
 
 	return otg;
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index bd8aab0..916b2b6 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -642,6 +642,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called zio.
 
+config USB_SERIAL_SSU100
+	tristate "USB Quatech SSU-100 Single Port Serial Driver"
+	help
+	  Say Y here if you want to use the Quatech SSU-100 single
+	  port usb to serial adapter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ssu100.
+
 config USB_SERIAL_DEBUG
 	tristate "USB Debugging Device"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index e54c728..40ebe17 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
 obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
+obj-$(CONFIG_USB_SERIAL_SSU100)			+= ssu100.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
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 8b8c797..2bef441 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -126,6 +126,10 @@
 	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
 	{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
+	{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
 	{ } /* Terminating Entry */
 };
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index e298dc4..eb12d9b 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -157,6 +157,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
@@ -746,6 +749,7 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index d01946d..6e612c5 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -40,6 +40,11 @@
 
 #define FTDI_NXTCAM_PID		0xABB8 /* NXTCam for Mindstorms NXT */
 
+/* US Interface Navigator (http://www.usinterface.com/) */
+#define FTDI_USINT_CAT_PID	0xb810	/* Navigator CAT and 2nd PTT lines */
+#define FTDI_USINT_WKEY_PID	0xb811	/* Navigator WKEY and FSK lines */
+#define FTDI_USINT_RS232_PID	0xb812	/* Navigator RS232 and CONFIG lines */
+
 /* OOCDlink by Joern Kaipf <joernk@web.de>
  * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
 #define FTDI_OOCDLINK_PID	0xbaf8	/* Amontec JTAGkey */
@@ -1032,3 +1037,8 @@
 #define XVERVE_SIGNALYZER_SH2_PID	0xBCA2
 #define XVERVE_SIGNALYZER_SH4_PID	0xBCA4
 
+/*
+ * Segway Robotic Mobility Platform USB interface (using VID 0x0403)
+ * Submitted by John G. Rogers
+ */
+#define SEGWAY_RMP200_PID	0xe729
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index a817ced..ca92f67 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -208,18 +208,23 @@
 	urb->transfer_buffer_length = count;
 	usb_serial_debug_data(debug, &port->dev, __func__, count,
 						urb->transfer_buffer);
+	spin_lock_irqsave(&port->lock, flags);
+	port->tx_bytes += count;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	clear_bit(i, &port->write_urbs_free);
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result) {
 		dev_err(&port->dev, "%s - error submitting urb: %d\n",
 						__func__, result);
+		set_bit(i, &port->write_urbs_free);
+		spin_lock_irqsave(&port->lock, flags);
+		port->tx_bytes -= count;
+		spin_unlock_irqrestore(&port->lock, flags);
+
 		clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
 		return result;
 	}
-	clear_bit(i, &port->write_urbs_free);
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->tx_bytes += count;
-	spin_unlock_irqrestore(&port->lock, flags);
 
 	/* Try sending off another urb, unless in irq context (in which case
 	 * there will be no free urb). */
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 0fca265..dc47f98 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1298,7 +1298,7 @@
 				kfree(header);
 				kfree(rom_desc);
 				kfree(ti_manuf_desc);
-				return status;
+				return -EINVAL;
 			}
 
 			/* verify the write -- must do this in order for
@@ -1321,7 +1321,7 @@
 				kfree(header);
 				kfree(rom_desc);
 				kfree(ti_manuf_desc);
-				return status;
+				return -EINVAL;
 			}
 
 			kfree(vheader);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 28913fa..4735931 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -534,7 +534,6 @@
 	{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
 	{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
 	{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
-	{ USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */
 	{ }                             /* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 74551cb..efc7211 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -1,6 +1,8 @@
 /*
  * Infinity Unlimited USB Phoenix driver
  *
+ * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk)
+
  * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
  *
  * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
@@ -40,7 +42,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.11"
+#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
 
 static const struct usb_device_id id_table[] = {
@@ -81,6 +83,9 @@
 	u8 *dbgbuf;		/* debug buffer */
 	u8 len;
 	int vcc;		/* vcc (either 3 or 5 V) */
+	u32 baud;
+	u32 boost;
+	u32 clk;
 };
 
 
@@ -157,13 +162,14 @@
 	    port->number, set, clear);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (set & TIOCM_RTS)
-		priv->tiostatus = TIOCM_RTS;
 
-	if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
+	if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) {
 		dbg("%s TIOCMSET RESET called !!!", __func__);
 		priv->reset = 1;
 	}
+	if (set & TIOCM_RTS)
+		priv->tiostatus = TIOCM_RTS;
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
@@ -851,20 +857,24 @@
 	return status;
 }
 
-static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
 			 u32 *actual, u8 parity)
 {
 	int status;
+	u32 baud;
 	u8 *dataout;
 	u8 DataCount = 0;
 	u8 T1Frekvens = 0;
 	u8 T1reload = 0;
 	unsigned int T1FrekvensHZ = 0;
 
+	dbg("%s - enter baud_base=%d", __func__, baud_base);
 	dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
 
 	if (!dataout)
 		return -ENOMEM;
+	/*baud = (((priv->clk / 35) * baud_base) / 100000); */
+	baud = baud_base;
 
 	if (baud < 1200 || baud > 230400) {
 		kfree(dataout);
@@ -948,15 +958,20 @@
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	const u32 supported_mask = CMSPAR|PARENB|PARODD;
-
+	struct iuu_private *priv = usb_get_serial_port_data(port);
 	unsigned int cflag = tty->termios->c_cflag;
 	int status;
 	u32 actual;
 	u32 parity;
 	int csize = CS7;
-	int baud = 9600;	/* Fixed for the moment */
+	int baud;
 	u32 newval = cflag & supported_mask;
 
+	/* Just use the ospeed. ispeed should be the same. */
+	baud = tty->termios->c_ospeed;
+
+	dbg("%s - enter c_ospeed or baud=%d", __func__, baud);
+
 	/* compute the parity parameter */
 	parity = 0;
 	if (cflag & CMSPAR) {	/* Using mark space */
@@ -976,15 +991,15 @@
 
 	/* set it */
 	status = iuu_uart_baud(port,
-			(clockmode == 2) ? 16457 : 9600 * boost / 100,
+			baud * priv->boost / 100,
 			&actual, parity);
 
 	/* set the termios value to the real one, so the user now what has
 	 * changed. We support few fields so its easies to copy the old hw
 	 * settings back over and then adjust them
 	 */
- 	if (old_termios)
- 		tty_termios_copy_hw(tty->termios, old_termios);
+	if (old_termios)
+		tty_termios_copy_hw(tty->termios, old_termios);
 	if (status != 0)	/* Set failed - return old bits */
 		return;
 	/* Re-encode speed, parity and csize */
@@ -1018,6 +1033,7 @@
 
 static void iuu_init_termios(struct tty_struct *tty)
 {
+	dbg("%s - enter", __func__);
 	*(tty->termios) = tty_std_termios;
 	tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
 				| TIOCM_CTS | CSTOPB | PARENB;
@@ -1033,10 +1049,16 @@
 	struct usb_serial *serial = port->serial;
 	u8 *buf;
 	int result;
+	int baud;
 	u32 actual;
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 
-	dbg("%s -  port %d", __func__, port->number);
+	baud = tty->termios->c_ospeed;
+	tty->termios->c_ispeed = baud;
+	/* Re-encode speed */
+	tty_encode_baud_rate(tty, baud, baud);
+
+	dbg("%s -  port %d, baud %d", __func__, port->number, baud);
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
 
@@ -1071,23 +1093,29 @@
 	iuu_uart_on(port);
 	if (boost < 100)
 		boost = 100;
+	priv->boost = boost;
+	priv->baud = baud;
 	switch (clockmode) {
 	case 2:		/*  3.680 Mhz */
+		priv->clk = IUU_CLK_3680000;
 		iuu_clk(port, IUU_CLK_3680000 * boost / 100);
 		result =
-		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
+		    iuu_uart_baud(port, baud * boost / 100, &actual,
 				  IUU_PARITY_EVEN);
 		break;
 	case 3:		/*  6.00 Mhz */
 		iuu_clk(port, IUU_CLK_6000000 * boost / 100);
+		priv->clk = IUU_CLK_6000000;
+		/* Ratio of 6000000 to 3500000 for baud 9600 */
 		result =
 		    iuu_uart_baud(port, 16457 * boost / 100, &actual,
 				  IUU_PARITY_EVEN);
 		break;
 	default:		/*  3.579 Mhz */
 		iuu_clk(port, IUU_CLK_3579000 * boost / 100);
+		priv->clk = IUU_CLK_3579000;
 		result =
-		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
+		    iuu_uart_baud(port, baud * boost / 100, &actual,
 				  IUU_PARITY_EVEN);
 	}
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5cd30e43..9fc6ea2 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -145,7 +145,10 @@
 #define HUAWEI_PRODUCT_E143D			0x143D
 #define HUAWEI_PRODUCT_E143E			0x143E
 #define HUAWEI_PRODUCT_E143F			0x143F
+#define HUAWEI_PRODUCT_K4505			0x1464
+#define HUAWEI_PRODUCT_K3765			0x1465
 #define HUAWEI_PRODUCT_E14AC			0x14AC
+#define HUAWEI_PRODUCT_ETS1220			0x1803
 
 #define QUANTA_VENDOR_ID			0x0408
 #define QUANTA_PRODUCT_Q101			0xEA02
@@ -264,9 +267,6 @@
 #define BANDRICH_PRODUCT_1011			0x1011
 #define BANDRICH_PRODUCT_1012			0x1012
 
-#define AMOI_VENDOR_ID			0x1614
-#define AMOI_PRODUCT_9508			0x0800
-
 #define QUALCOMM_VENDOR_ID			0x05C6
 
 #define CMOTECH_VENDOR_ID			0x16d8
@@ -482,8 +482,10 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
-	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
@@ -1017,6 +1019,13 @@
 		serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
 		return -ENODEV;
 
+	/* Don't bind network interfaces on Huawei K3765 & K4505 */
+	if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
+		(serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
+			serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
+		serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+		return -ENODEV;
+
 	data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
 
 	if (!data)
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
new file mode 100644
index 0000000..6e82d4f
--- /dev/null
+++ b/drivers/usb/serial/ssu100.c
@@ -0,0 +1,698 @@
+/*
+ * usb-serial driver for Quatech SSU-100
+ *
+ * based on ftdi_sio.c and the original serqt_usb.c from Quatech
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define QT_OPEN_CLOSE_CHANNEL       0xca
+#define QT_SET_GET_DEVICE           0xc2
+#define QT_SET_GET_REGISTER         0xc0
+#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
+#define QT_SET_ATF                  0xcd
+#define QT_GET_SET_UART             0xc1
+#define QT_TRANSFER_IN              0xc0
+#define QT_HW_FLOW_CONTROL_MASK     0xc5
+#define QT_SW_FLOW_CONTROL_MASK     0xc6
+
+#define MODEM_CTL_REGISTER         0x04
+#define MODEM_STATUS_REGISTER      0x06
+
+
+#define SERIAL_LSR_OE       0x02
+#define SERIAL_LSR_PE       0x04
+#define SERIAL_LSR_FE       0x08
+#define SERIAL_LSR_BI       0x10
+
+#define SERIAL_LSR_TEMT     0x40
+
+#define  SERIAL_MCR_DTR             0x01
+#define  SERIAL_MCR_RTS             0x02
+#define  SERIAL_MCR_LOOP            0x10
+
+#define  SERIAL_MSR_CTS             0x10
+#define  SERIAL_MSR_CD              0x80
+#define  SERIAL_MSR_RI              0x40
+#define  SERIAL_MSR_DSR             0x20
+#define  SERIAL_MSR_MASK            0xf0
+
+#define  SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS)
+
+#define  SERIAL_8_DATA              0x03
+#define  SERIAL_7_DATA              0x02
+#define  SERIAL_6_DATA              0x01
+#define  SERIAL_5_DATA              0x00
+
+#define  SERIAL_ODD_PARITY          0X08
+#define  SERIAL_EVEN_PARITY         0X18
+
+#define  MAX_BAUD_RATE              460800
+
+#define ATC_DISABLED                0x00
+#define DUPMODE_BITS        0xc0
+#define RR_BITS             0x03
+#define LOOPMODE_BITS       0x41
+#define RS232_MODE          0x00
+#define RTSCTS_TO_CONNECTOR 0x40
+#define CLKS_X4             0x02
+#define FULLPWRBIT          0x00000080
+#define NEXT_BOARD_POWER_BIT        0x00000004
+
+static int debug = 1;
+
+/* Version Information */
+#define DRIVER_VERSION "v0.1"
+#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
+
+#define	USB_VENDOR_ID_QUATECH	0x061d	/* Quatech VID */
+#define QUATECH_SSU100	0xC020	/* SSU100 */
+
+static const struct usb_device_id id_table[] = {
+	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+
+static struct usb_driver ssu100_driver = {
+	.name			       = "ssu100",
+	.probe			       = usb_serial_probe,
+	.disconnect		       = usb_serial_disconnect,
+	.id_table		       = id_table,
+	.suspend		       = usb_serial_suspend,
+	.resume			       = usb_serial_resume,
+	.no_dynamic_id		       = 1,
+	.supports_autosuspend	       = 1,
+};
+
+struct ssu100_port_private {
+	u8 shadowLSR;
+	u8 shadowMSR;
+	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+	unsigned short max_packet_size;
+};
+
+static void ssu100_release(struct usb_serial *serial)
+{
+	struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
+
+	dbg("%s", __func__);
+	kfree(priv);
+}
+
+static inline int ssu100_control_msg(struct usb_device *dev,
+				     u8 request, u16 data, u16 index)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			       request, 0x40, data, index,
+			       NULL, 0, 300);
+}
+
+static inline int ssu100_setdevice(struct usb_device *dev, u8 *data)
+{
+	u16 x = ((u16)(data[1] << 8) | (u16)(data[0]));
+
+	return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
+}
+
+
+static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
+			       data, 3, 300);
+}
+
+static inline int ssu100_getregister(struct usb_device *dev,
+				     unsigned short uart,
+				     unsigned short reg,
+				     u8 *data)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			       QT_SET_GET_REGISTER, 0xc0, reg,
+			       uart, data, sizeof(*data), 300);
+
+}
+
+
+static inline int ssu100_setregister(struct usb_device *dev,
+				     unsigned short uart,
+				     u16 data)
+{
+	u16 value = (data << 8) | MODEM_CTL_REGISTER;
+
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			       QT_SET_GET_REGISTER, 0x40, value, uart,
+			       NULL, 0, 300);
+
+}
+
+#define set_mctrl(dev, set)		update_mctrl((dev), (set), 0)
+#define clear_mctrl(dev, clear)	update_mctrl((dev), 0, (clear))
+
+/* these do not deal with device that have more than 1 port */
+static inline int update_mctrl(struct usb_device *dev, unsigned int set,
+			       unsigned int clear)
+{
+	unsigned urb_value;
+	int result;
+
+	if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
+		dbg("%s - DTR|RTS not being set|cleared", __func__);
+		return 0;	/* no change */
+	}
+
+	clear &= ~set;	/* 'set' takes precedence over 'clear' */
+	urb_value = 0;
+	if (set & TIOCM_DTR)
+		urb_value |= SERIAL_MCR_DTR;
+	if (set & TIOCM_RTS)
+		urb_value |= SERIAL_MCR_RTS;
+
+	result = ssu100_setregister(dev, 0, urb_value);
+	if (result < 0)
+		dbg("%s Error from MODEM_CTRL urb", __func__);
+
+	return result;
+}
+
+static int ssu100_initdevice(struct usb_device *dev)
+{
+	u8 *data;
+	int result = 0;
+
+	dbg("%s", __func__);
+
+	data = kzalloc(3, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	result = ssu100_getdevice(dev, data);
+	if (result < 0) {
+		dbg("%s - get_device failed %i", __func__, result);
+		goto out;
+	}
+
+	data[1] &= ~FULLPWRBIT;
+
+	result = ssu100_setdevice(dev, data);
+	if (result < 0) {
+		dbg("%s - setdevice failed %i", __func__, result);
+		goto out;
+	}
+
+	result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0);
+	if (result < 0) {
+		dbg("%s - set prebuffer level failed %i", __func__, result);
+		goto out;
+	}
+
+	result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0);
+	if (result < 0) {
+		dbg("%s - set ATFprebuffer level failed %i", __func__, result);
+		goto out;
+	}
+
+	result = ssu100_getdevice(dev, data);
+	if (result < 0) {
+		dbg("%s - get_device failed %i", __func__, result);
+		goto out;
+	}
+
+	data[0] &= ~(RR_BITS | DUPMODE_BITS);
+	data[0] |= CLKS_X4;
+	data[1] &= ~(LOOPMODE_BITS);
+	data[1] |= RS232_MODE;
+
+	result = ssu100_setdevice(dev, data);
+	if (result < 0) {
+		dbg("%s - setdevice failed %i", __func__, result);
+		goto out;
+	}
+
+out:	kfree(data);
+	return result;
+
+}
+
+
+static void ssu100_set_termios(struct tty_struct *tty,
+			       struct usb_serial_port *port,
+			       struct ktermios *old_termios)
+{
+	struct usb_device *dev = port->serial->dev;
+	struct ktermios *termios = tty->termios;
+	u16 baud, divisor, remainder;
+	unsigned int cflag = termios->c_cflag;
+	u16 urb_value = 0; /* will hold the new flags */
+	int result;
+
+	dbg("%s", __func__);
+
+	if (cflag & PARENB) {
+		if (cflag & PARODD)
+			urb_value |= SERIAL_ODD_PARITY;
+		else
+			urb_value |= SERIAL_EVEN_PARITY;
+	}
+
+	switch (cflag & CSIZE) {
+	case CS5:
+		urb_value |= SERIAL_5_DATA;
+		break;
+	case CS6:
+		urb_value |= SERIAL_6_DATA;
+		break;
+	case CS7:
+		urb_value |= SERIAL_7_DATA;
+		break;
+	default:
+	case CS8:
+		urb_value |= SERIAL_8_DATA;
+		break;
+	}
+
+	baud = tty_get_baud_rate(tty);
+	if (!baud)
+		baud = 9600;
+
+	dbg("%s - got baud = %d\n", __func__, baud);
+
+
+	divisor = MAX_BAUD_RATE / baud;
+	remainder = MAX_BAUD_RATE % baud;
+	if (((remainder * 2) >= baud) && (baud != 110))
+		divisor++;
+
+	urb_value = urb_value << 8;
+
+	result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
+	if (result < 0)
+		dbg("%s - set uart failed", __func__);
+
+	if (cflag & CRTSCTS)
+		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+					    SERIAL_CRTSCTS, 0);
+	else
+		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
+					    0, 0);
+	if (result < 0)
+		dbg("%s - set HW flow control failed", __func__);
+
+	if (I_IXOFF(tty) || I_IXON(tty)) {
+		u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));
+
+		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+					    x, 0);
+	} else
+		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
+					    0, 0);
+
+	if (result < 0)
+		dbg("%s - set SW flow control failed", __func__);
+
+}
+
+
+static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+	struct usb_device *dev = port->serial->dev;
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+	u8 *data;
+	int result;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	data = kzalloc(2, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				 QT_OPEN_CLOSE_CHANNEL,
+				 QT_TRANSFER_IN, 0x01,
+				 0, data, 2, 300);
+	if (result < 0) {
+		dbg("%s - open failed %i", __func__, result);
+		kfree(data);
+		return result;
+	}
+
+	priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
+				      SERIAL_LSR_FE | SERIAL_LSR_BI);
+
+	priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
+				      SERIAL_MSR_RI | SERIAL_MSR_CD);
+
+	kfree(data);
+
+/* set to 9600 */
+	result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300);
+	if (result < 0)
+		dbg("%s - set uart failed", __func__);
+
+	if (tty)
+		ssu100_set_termios(tty, port, tty->termios);
+
+	return usb_serial_generic_open(tty, port);
+}
+
+static void ssu100_close(struct usb_serial_port *port)
+{
+	dbg("%s", __func__);
+	usb_serial_generic_close(port);
+}
+
+static int get_serial_info(struct usb_serial_port *port,
+			   struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.line		= port->serial->minor;
+	tmp.port		= 0;
+	tmp.irq			= 0;
+	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+	tmp.xmit_fifo_size	= port->bulk_out_size;
+	tmp.baud_base		= 9600;
+	tmp.close_delay		= 5*HZ;
+	tmp.closing_wait	= 30*HZ;
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+
+	dbg("%s cmd 0x%04x", __func__, cmd);
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return get_serial_info(port,
+				       (struct serial_struct __user *) arg);
+
+	case TIOCMIWAIT:
+		while (priv != NULL) {
+			u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK;
+			interruptible_sleep_on(&priv->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			else {
+				u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR;
+				if (!diff)
+					return -EIO; /* no change => error */
+
+				/* Return 0 if caller wanted to know about
+				   these bits */
+
+				if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) ||
+				    ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) ||
+				    ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) ||
+				    ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS)))
+					return 0;
+			}
+		}
+		return 0;
+
+	default:
+		break;
+	}
+
+	dbg("%s arg not supported", __func__);
+
+	return -ENOIOCTLCMD;
+}
+
+static void ssu100_set_max_packet_size(struct usb_serial_port *port)
+{
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+	struct usb_device *udev = serial->dev;
+
+	struct usb_interface *interface = serial->interface;
+	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
+
+	unsigned num_endpoints;
+	int i;
+
+	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
+	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
+
+	for (i = 0; i < num_endpoints; i++) {
+		dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
+			interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
+		ep_desc = &interface->cur_altsetting->endpoint[i].desc;
+	}
+
+	/* set max packet size based on descriptor */
+	priv->max_packet_size = ep_desc->wMaxPacketSize;
+
+	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
+}
+
+static int ssu100_attach(struct usb_serial *serial)
+{
+	struct ssu100_port_private *priv;
+	struct usb_serial_port *port = *serial->port;
+
+	dbg("%s", __func__);
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
+			sizeof(*priv));
+		return -ENOMEM;
+	}
+
+	init_waitqueue_head(&priv->delta_msr_wait);
+	usb_set_serial_port_data(port, priv);
+
+	ssu100_set_max_packet_size(port);
+
+	return ssu100_initdevice(serial->dev);
+}
+
+static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct usb_device *dev = port->serial->dev;
+	u8 *d;
+	int r;
+
+	dbg("%s\n", __func__);
+
+	d = kzalloc(2, GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d);
+	if (r < 0)
+		goto mget_out;
+
+	r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1);
+	if (r < 0)
+		goto mget_out;
+
+	r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) |
+		(d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) |
+		(d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) |
+		(d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) |
+		(d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) |
+		(d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0);
+
+mget_out:
+	kfree(d);
+	return r;
+}
+
+static int ssu100_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct usb_device *dev = port->serial->dev;
+
+	dbg("%s\n", __func__);
+	return update_mctrl(dev, set, clear);
+}
+
+static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
+{
+	struct usb_device *dev = port->serial->dev;
+
+	dbg("%s\n", __func__);
+
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected) {
+		/* Disable flow control */
+		if (!on &&
+		    ssu100_setregister(dev, 0, 0) < 0)
+			dev_err(&port->dev, "error from flowcontrol urb\n");
+		/* drop RTS and DTR */
+		if (on)
+			set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
+		else
+			clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
+	}
+	mutex_unlock(&port->serial->disc_mutex);
+}
+
+static int ssu100_process_packet(struct tty_struct *tty,
+				 struct usb_serial_port *port,
+				 struct ssu100_port_private *priv,
+				 char *packet, int len)
+{
+	int i;
+	char flag;
+	char *ch;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	if (len < 4) {
+		dbg("%s - malformed packet", __func__);
+		return 0;
+	}
+
+	if ((packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
+		if (packet[2] == 0x00)
+			priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |
+						       SERIAL_LSR_PE |
+						       SERIAL_LSR_FE |
+						       SERIAL_LSR_BI);
+
+		if (packet[2] == 0x01) {
+			priv->shadowMSR = packet[3];
+			wake_up_interruptible(&priv->delta_msr_wait);
+		}
+
+		len -= 4;
+		ch = packet + 4;
+	} else
+		ch = packet;
+
+	if (!len)
+		return 0;	/* status only */
+
+	if (port->port.console && port->sysrq) {
+		for (i = 0; i < len; i++, ch++) {
+			if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+				tty_insert_flip_char(tty, *ch, flag);
+		}
+	} else
+		tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
+
+	return len;
+}
+
+static void ssu100_process_read_urb(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+	char *data = (char *)urb->transfer_buffer;
+	struct tty_struct *tty;
+	int count = 0;
+	int i;
+	int len;
+
+	dbg("%s", __func__);
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+
+	for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
+		len = min_t(int, urb->actual_length - i, priv->max_packet_size);
+		count += ssu100_process_packet(tty, port, priv, &data[i], len);
+	}
+
+	if (count)
+		tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+
+static struct usb_serial_driver ssu100_device = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "ssu100",
+	},
+	.description	     = DRIVER_DESC,
+	.id_table	     = id_table,
+	.usb_driver	     = &ssu100_driver,
+	.num_ports	     = 1,
+	.bulk_in_size        = 256,
+	.bulk_out_size       = 256,
+	.open		     = ssu100_open,
+	.close		     = ssu100_close,
+	.attach              = ssu100_attach,
+	.release             = ssu100_release,
+	.dtr_rts             = ssu100_dtr_rts,
+	.process_read_urb    = ssu100_process_read_urb,
+	.tiocmget            = ssu100_tiocmget,
+	.tiocmset            = ssu100_tiocmset,
+	.ioctl               = ssu100_ioctl,
+	.set_termios         = ssu100_set_termios,
+};
+
+static int __init ssu100_init(void)
+{
+	int retval;
+
+	dbg("%s", __func__);
+
+	/* register with usb-serial */
+	retval = usb_serial_register(&ssu100_device);
+
+	if (retval)
+		goto failed_usb_sio_register;
+
+	retval = usb_register(&ssu100_driver);
+	if (retval)
+		goto failed_usb_register;
+
+	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+	       DRIVER_DESC "\n");
+
+	return 0;
+
+failed_usb_register:
+	usb_serial_deregister(&ssu100_device);
+failed_usb_sio_register:
+	return retval;
+}
+
+static void __exit ssu100_exit(void)
+{
+	usb_deregister(&ssu100_driver);
+	usb_serial_deregister(&ssu100_device);
+}
+
+module_init(ssu100_init);
+module_exit(ssu100_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 941c2d4..2a982e6 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -653,6 +653,7 @@
 	return id;
 }
 
+/* Caller must hold table_lock */
 static struct usb_serial_driver *search_serial_device(
 					struct usb_interface *iface)
 {
@@ -718,17 +719,23 @@
 	int num_ports = 0;
 	int max_endpoints;
 
-	lock_kernel(); /* guard against unloading a serial driver module */
+	mutex_lock(&table_lock);
 	type = search_serial_device(interface);
 	if (!type) {
-		unlock_kernel();
+		mutex_unlock(&table_lock);
 		dbg("none matched");
 		return -ENODEV;
 	}
 
+	if (!try_module_get(type->driver.owner)) {
+		mutex_unlock(&table_lock);
+		dev_err(&interface->dev, "module get failed, exiting\n");
+		return -EIO;
+	}
+	mutex_unlock(&table_lock);
+
 	serial = create_serial(dev, interface, type);
 	if (!serial) {
-		unlock_kernel();
 		dev_err(&interface->dev, "%s - out of memory\n", __func__);
 		return -ENOMEM;
 	}
@@ -737,20 +744,11 @@
 	if (type->probe) {
 		const struct usb_device_id *id;
 
-		if (!try_module_get(type->driver.owner)) {
-			unlock_kernel();
-			dev_err(&interface->dev,
-				"module get failed, exiting\n");
-			kfree(serial);
-			return -EIO;
-		}
-
 		id = get_iface_id(type, interface);
 		retval = type->probe(serial, id);
 		module_put(type->driver.owner);
 
 		if (retval) {
-			unlock_kernel();
 			dbg("sub driver rejected device");
 			kfree(serial);
 			return retval;
@@ -822,7 +820,6 @@
 		 * properly during a later invocation of usb_serial_probe
 		 */
 		if (num_bulk_in == 0 || num_bulk_out == 0) {
-			unlock_kernel();
 			dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
 			kfree(serial);
 			return -ENODEV;
@@ -835,7 +832,6 @@
 	if (type == &usb_serial_generic_device) {
 		num_ports = num_bulk_out;
 		if (num_ports == 0) {
-			unlock_kernel();
 			dev_err(&interface->dev,
 			    "Generic device with no bulk out, not allowed.\n");
 			kfree(serial);
@@ -847,7 +843,6 @@
 		/* if this device type has a calc_num_ports function, call it */
 		if (type->calc_num_ports) {
 			if (!try_module_get(type->driver.owner)) {
-				unlock_kernel();
 				dev_err(&interface->dev,
 					"module get failed, exiting\n");
 				kfree(serial);
@@ -878,7 +873,6 @@
 	max_endpoints = max(max_endpoints, num_interrupt_out);
 	max_endpoints = max(max_endpoints, (int)serial->num_ports);
 	serial->num_port_pointers = max_endpoints;
-	unlock_kernel();
 
 	dbg("%s - setting up %d port structures for this device",
 						__func__, max_endpoints);
@@ -1077,6 +1071,8 @@
 		dev_set_name(&port->dev, "ttyUSB%d", port->number);
 		dbg ("%s - registering %s", __func__, dev_name(&port->dev));
 		port->dev_state = PORT_REGISTERING;
+		device_enable_async_suspend(&port->dev);
+
 		retval = device_add(&port->dev);
 		if (retval) {
 			dev_err(&port->dev, "Error registering port device, "
@@ -1349,6 +1345,7 @@
 		driver->description = driver->driver.name;
 
 	/* Add this device to our list of devices */
+	mutex_lock(&table_lock);
 	list_add(&driver->driver_list, &usb_serial_driver_list);
 
 	retval = usb_serial_bus_register(driver);
@@ -1360,6 +1357,7 @@
 		printk(KERN_INFO "USB Serial support registered for %s\n",
 						driver->description);
 
+	mutex_unlock(&table_lock);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(usb_serial_register);
@@ -1370,8 +1368,10 @@
 	/* must be called with BKL held */
 	printk(KERN_INFO "USB Serial deregistering driver %s\n",
 	       device->description);
+	mutex_lock(&table_lock);
 	list_del(&device->driver_list);
 	usb_serial_bus_deregister(device);
+	mutex_unlock(&table_lock);
 }
 EXPORT_SYMBOL_GPL(usb_serial_deregister);
 
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 54cc942..6542ca4 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -269,7 +269,7 @@
 	/* The firmware will time-out commands after 20 seconds. Some commands
 	 * can legitimately take longer than this, so we use a different
 	 * command that only waits for the interrupt and then sends status,
-	 * without having to send a new ATAPI command to the device. 
+	 * without having to send a new ATAPI command to the device.
 	 *
 	 * NOTE: There is some indication that a data transfer after a timeout
 	 * may not work, but that is a condition that should never happen.
@@ -324,14 +324,14 @@
 
 	/* Find the length we desire to read. */
 	switch (srb->cmnd[0]) {
-		case INQUIRY:
-		case REQUEST_SENSE:		/* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
-		case MODE_SENSE:
-		case MODE_SENSE_10:
-			length = le16_to_cpu(fst->Count);
-			break;
-		default:
-			length = scsi_bufflen(srb);
+	case INQUIRY:
+	case REQUEST_SENSE:	/* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+		length = le16_to_cpu(fst->Count);
+		break;
+	default:
+		length = scsi_bufflen(srb);
 	}
 
 	/* verify that this amount is legal */
@@ -414,7 +414,7 @@
 		/* should never hit here -- filtered in usb.c */
 		US_DEBUGP ("freecom unimplemented direction: %d\n",
 				us->srb->sc_data_direction);
-		// Return fail, SCSI seems to handle this better.
+		/* Return fail, SCSI seems to handle this better. */
 		return USB_STOR_TRANSPORT_FAILED;
 		break;
 	}
@@ -494,8 +494,7 @@
 				offset = 0;
 			}
 			offset += sprintf (line+offset, "%08x:", i);
-		}
-		else if ((i & 7) == 0) {
+		} else if ((i & 7) == 0) {
 			offset += sprintf (line+offset, " -");
 		}
 		offset += sprintf (line+offset, " %02x", buffer[i] & 0xff);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index e9cbc14..6b9982c 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1456,8 +1456,7 @@
 	int retStatus = ISD200_GOOD;
 	struct isd200_info *info;
 
-	info = (struct isd200_info *)
-			kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
 	if (!info)
 		retStatus = ISD200_ERROR;
 	else {
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index a7d0bf9..90bb017 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -336,6 +336,7 @@
 		else {
 			US_DEBUG(usb_stor_show_command(us->srb));
 			us->proto_handler(us->srb, us);
+			usb_mark_last_busy(us->pusb_dev);
 		}
 
 		/* lock access to the state */
@@ -845,6 +846,7 @@
 		/* Should we unbind if no devices were detected? */
 	}
 
+	usb_autopm_put_interface(us->pusb_intf);
 	complete_and_exit(&us->scanning_done, 0);
 }
 
@@ -968,6 +970,7 @@
 		goto BadDevice;
 	}
 
+	usb_autopm_get_interface_no_resume(us->pusb_intf);
 	wake_up_process(th);
 
 	return 0;
@@ -1040,6 +1043,7 @@
 	.pre_reset =	usb_stor_pre_reset,
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	usb_storage_usb_ids,
+	.supports_autosuspend = 1,
 	.soft_unbind =	1,
 };
 
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index d110588..552679b 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -142,7 +142,7 @@
 {
 	struct usb_skel *dev;
 
-	dev = (struct usb_skel *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL)
 		return -ENODEV;
 
@@ -162,7 +162,7 @@
 	struct usb_skel *dev;
 	int res;
 
-	dev = (struct usb_skel *)file->private_data;
+	dev = file->private_data;
 	if (dev == NULL)
 		return -ENODEV;
 
@@ -246,7 +246,7 @@
 	int rv;
 	bool ongoing_io;
 
-	dev = (struct usb_skel *)file->private_data;
+	dev = file->private_data;
 
 	/* if we cannot read at all, return EOF */
 	if (!dev->bulk_in_urb || !count)
@@ -401,7 +401,7 @@
 	char *buf = NULL;
 	size_t writesize = min(count, (size_t)MAX_TRANSFER);
 
-	dev = (struct usb_skel *)file->private_data;
+	dev = file->private_data;
 
 	/* verify that we actually have some data to write */
 	if (count == 0)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d5922a8..35fe6ab 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -127,6 +127,8 @@
  *      queued reset so that usb_cancel_queued_reset() doesn't try to
  *      remove from the workqueue when running inside the worker
  *      thread. See __usb_queue_reset_device().
+ * @resetting_device: USB core reset the device, so use alt setting 0 as
+ *	current; needs bandwidth alloc after reset.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -843,7 +845,7 @@
 
 	void (*disconnect) (struct usb_interface *intf);
 
-	int (*ioctl) (struct usb_interface *intf, unsigned int code,
+	int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
 			void *buf);
 
 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
@@ -1015,6 +1017,7 @@
  *	is a different endpoint (and pipe) from "out" endpoint two.
  *	The current configuration controls the existence, type, and
  *	maximum packet size of any given endpoint.
+ * @stream_id: the endpoint's stream ID for bulk streams
  * @dev: Identifies the USB device to perform the request.
  * @status: This is read in non-iso completion functions to get the
  *	status of the particular request.  ISO requests only use it
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 139353e..890bc14 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -276,6 +276,8 @@
 	int			(*bind)(struct usb_composite_dev *);
 	int			(*unbind)(struct usb_composite_dev *);
 
+	void			(*disconnect)(struct usb_composite_dev *);
+
 	/* global suspend hooks */
 	void			(*suspend)(struct usb_composite_dev *);
 	void			(*resume)(struct usb_composite_dev *);
@@ -342,6 +344,10 @@
 };
 
 extern int usb_string_id(struct usb_composite_dev *c);
+extern int usb_string_ids_tab(struct usb_composite_dev *c,
+			      struct usb_string *str);
+extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
+
 
 /* messaging utils */
 #define DBG(d, fmt, args...) \
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 80287af..2e262cb 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -39,6 +39,12 @@
 #define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
 
 	u32		hcc_params;      /* HCCPARAMS - offset 0x8 */
+/* EHCI 1.1 addendum */
+#define HCC_32FRAME_PERIODIC_LIST(p)	((p)&(1 << 19))
+#define HCC_PER_PORT_CHANGE_EVENT(p)	((p)&(1 << 18))
+#define HCC_LPM(p)			((p)&(1 << 17))
+#define HCC_HW_PREFETCH(p)		((p)&(1 << 16))
+
 #define HCC_EXT_CAPS(p)		(((p)>>8)&0xff)	/* for pci extended caps */
 #define HCC_ISOC_CACHE(p)       ((p)&(1 << 7))  /* true: can cache isoc frame */
 #define HCC_ISOC_THRES(p)       (((p)>>4)&0x7)  /* bits 6:4, uframes cached */
@@ -54,6 +60,13 @@
 
 	/* USBCMD: offset 0x00 */
 	u32		command;
+
+/* EHCI 1.1 addendum */
+#define CMD_HIRD	(0xf<<24)	/* host initiated resume duration */
+#define CMD_PPCEE	(1<<15)		/* per port change event enable */
+#define CMD_FSP		(1<<14)		/* fully synchronized prefetch */
+#define CMD_ASPE	(1<<13)		/* async schedule prefetch enable */
+#define CMD_PSPE	(1<<12)		/* periodic schedule prefetch enable */
 /* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
 #define CMD_PARK	(1<<11)		/* enable "park" on async qh */
 #define CMD_PARK_CNT(c)	(((c)>>8)&3)	/* how many transfers to park for */
@@ -67,6 +80,7 @@
 
 	/* USBSTS: offset 0x04 */
 	u32		status;
+#define STS_PPCE_MASK	(0xff<<16)	/* Per-Port change event 1-16 */
 #define STS_ASS		(1<<15)		/* Async Schedule Status */
 #define STS_PSS		(1<<14)		/* Periodic Schedule Status */
 #define STS_RECL	(1<<13)		/* Reclamation */
@@ -100,6 +114,14 @@
 
 	/* PORTSC: offset 0x44 */
 	u32		port_status[0];	/* up to N_PORTS */
+/* EHCI 1.1 addendum */
+#define PORTSC_SUSPEND_STS_ACK 0
+#define PORTSC_SUSPEND_STS_NYET 1
+#define PORTSC_SUSPEND_STS_STALL 2
+#define PORTSC_SUSPEND_STS_ERR 3
+
+#define PORT_DEV_ADDR	(0x7f<<25)		/* device address */
+#define PORT_SSTS	(0x3<<23)		/* suspend status */
 /* 31:23 reserved */
 #define PORT_WKOC_E	(1<<22)		/* wake on overcurrent (enable) */
 #define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
@@ -115,6 +137,7 @@
 #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10))	/* USB 1.1 device */
 /* 11:10 for detecting lowspeed devices (reset vs release ownership) */
 /* 9 reserved */
+#define PORT_LPM	(1<<9)		/* LPM transaction */
 #define PORT_RESET	(1<<8)		/* reset port */
 #define PORT_SUSPEND	(1<<7)		/* suspend port */
 #define PORT_RESUME	(1<<6)		/* resume it */
diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h
index a34a2a0..6f649c1 100644
--- a/include/linux/usb/functionfs.h
+++ b/include/linux/usb/functionfs.h
@@ -180,9 +180,9 @@
 static void functionfs_unbind(struct ffs_data *ffs)
 	__attribute__((nonnull));
 
-static int functionfs_add(struct usb_composite_dev *cdev,
-			  struct usb_configuration *c,
-			  struct ffs_data *ffs)
+static int functionfs_bind_config(struct usb_composite_dev *cdev,
+				  struct usb_configuration *c,
+				  struct ffs_data *ffs)
 	__attribute__((warn_unused_result, nonnull));
 
 
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 2e3a4ea..3b571f1 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -89,18 +89,33 @@
 	 */
 	const struct hc_driver	*driver;	/* hw-specific hooks */
 
-	/* Flags that need to be manipulated atomically */
+	/* Flags that need to be manipulated atomically because they can
+	 * change while the host controller is running.  Always use
+	 * set_bit() or clear_bit() to change their values.
+	 */
 	unsigned long		flags;
-#define HCD_FLAG_HW_ACCESSIBLE	0x00000001
-#define HCD_FLAG_SAW_IRQ	0x00000002
+#define HCD_FLAG_HW_ACCESSIBLE		0	/* at full power */
+#define HCD_FLAG_SAW_IRQ		1
+#define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
+#define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
+#define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
 
+	/* The flags can be tested using these macros; they are likely to
+	 * be slightly faster than test_bit().
+	 */
+#define HCD_HW_ACCESSIBLE(hcd)	((hcd)->flags & (1U << HCD_FLAG_HW_ACCESSIBLE))
+#define HCD_SAW_IRQ(hcd)	((hcd)->flags & (1U << HCD_FLAG_SAW_IRQ))
+#define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
+#define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
+#define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
+
+	/* Flags that get set only during HCD registration or removal. */
 	unsigned		rh_registered:1;/* is root hub registered? */
+	unsigned		rh_pollable:1;	/* may we poll the root hub? */
 
 	/* The next flag is a stopgap, to be removed when all the HCDs
 	 * support the new root-hub polling mechanism. */
 	unsigned		uses_new_polling:1;
-	unsigned		poll_rh:1;	/* poll for rh status? */
-	unsigned		poll_pending:1;	/* status has changed? */
 	unsigned		wireless:1;	/* Wireless USB HCD */
 	unsigned		authorized_default:1;
 	unsigned		has_tt:1;	/* Integrated TT in root hub */
@@ -198,7 +213,7 @@
 	 * a whole, not just the root hub; they're for PCI bus glue.
 	 */
 	/* called after suspending the hub, before entering D3 etc */
-	int	(*pci_suspend)(struct usb_hcd *hcd);
+	int	(*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup);
 
 	/* called after entering D0 (etc), before resuming the hub */
 	int	(*pci_resume)(struct usb_hcd *hcd, bool hibernated);
@@ -299,6 +314,10 @@
 	int	(*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,
 			struct usb_tt *tt, gfp_t mem_flags);
 	int	(*reset_device)(struct usb_hcd *, struct usb_device *);
+		/* Notifies the HCD after a device is connected and its
+		 * address is set
+		 */
+	int	(*update_device)(struct usb_hcd *, struct usb_device *);
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index f8302d0..545cba7 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -43,13 +43,6 @@
 	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
 };
 
-#define USB_OTG_PULLUP_ID		(1 << 0)
-#define USB_OTG_PULLDOWN_DP		(1 << 1)
-#define USB_OTG_PULLDOWN_DM		(1 << 2)
-#define USB_OTG_EXT_VBUS_INDICATOR	(1 << 3)
-#define USB_OTG_DRV_VBUS		(1 << 4)
-#define USB_OTG_DRV_VBUS_EXT		(1 << 5)
-
 struct otg_transceiver;
 
 /* for transceivers connected thru an ULPI interface, the user must
@@ -146,10 +139,10 @@
 	return -EINVAL;
 }
 
-static inline int otg_io_write(struct otg_transceiver *otg, u32 reg, u32 val)
+static inline int otg_io_write(struct otg_transceiver *otg, u32 val, u32 reg)
 {
 	if (otg->io_ops && otg->io_ops->write)
-		return otg->io_ops->write(otg, reg, val);
+		return otg->io_ops->write(otg, val, reg);
 
 	return -EINVAL;
 }
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 16b7f33..3e93de7 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -26,4 +26,8 @@
    and can't handle talking to these interfaces */
 #define USB_QUIRK_HONOR_BNUMINTERFACES	0x00000020
 
+/* device needs a pause during initialization, after we read the device
+   descriptor */
+#define USB_QUIRK_DELAY_INIT		0x00000040
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 2369d07..82b1507 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -11,6 +11,42 @@
 #ifndef __LINUX_USB_ULPI_H
 #define __LINUX_USB_ULPI_H
 
+#include <linux/usb/otg.h>
+/*-------------------------------------------------------------------------*/
+
+/*
+ * ULPI Flags
+ */
+#define ULPI_OTG_ID_PULLUP		(1 << 0)
+#define ULPI_OTG_DP_PULLDOWN_DIS	(1 << 1)
+#define ULPI_OTG_DM_PULLDOWN_DIS	(1 << 2)
+#define ULPI_OTG_DISCHRGVBUS		(1 << 3)
+#define ULPI_OTG_CHRGVBUS		(1 << 4)
+#define ULPI_OTG_DRVVBUS		(1 << 5)
+#define ULPI_OTG_DRVVBUS_EXT		(1 << 6)
+#define ULPI_OTG_EXTVBUSIND		(1 << 7)
+
+#define ULPI_IC_6PIN_SERIAL		(1 << 8)
+#define ULPI_IC_3PIN_SERIAL		(1 << 9)
+#define ULPI_IC_CARKIT			(1 << 10)
+#define ULPI_IC_CLKSUSPM		(1 << 11)
+#define ULPI_IC_AUTORESUME		(1 << 12)
+#define ULPI_IC_EXTVBUS_INDINV		(1 << 13)
+#define ULPI_IC_IND_PASSTHRU		(1 << 14)
+#define ULPI_IC_PROTECT_DIS		(1 << 15)
+
+#define ULPI_FC_HS			(1 << 16)
+#define ULPI_FC_FS			(1 << 17)
+#define ULPI_FC_LS			(1 << 18)
+#define ULPI_FC_FS4LS			(1 << 19)
+#define ULPI_FC_TERMSEL			(1 << 20)
+#define ULPI_FC_OP_NORM			(1 << 21)
+#define ULPI_FC_OP_NODRV		(1 << 22)
+#define ULPI_FC_OP_DIS_NRZI		(1 << 23)
+#define ULPI_FC_OP_NSYNC_NEOP		(1 << 24)
+#define ULPI_FC_RST			(1 << 25)
+#define ULPI_FC_SUSPM			(1 << 26)
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -58,6 +94,10 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Register Bits
+ */
+
 /* Function Control */
 #define ULPI_FUNC_CTRL_XCVRSEL			(1 << 0)
 #define  ULPI_FUNC_CTRL_XCVRSEL_MASK		(3 << 0)