aboutsummaryrefslogtreecommitdiffstats
diff options
-rw-r--r--series20
-rw-r--r--tty/serial-apbuart-let-boards-without-apbuart-boot.patch130
-rw-r--r--tty/serial-isicomm-handle-running-out-of-slots.patch49
-rw-r--r--usb/usb-add-missing-in-map_urb_for_dma.patch43
-rw-r--r--usb/usb-cp210x-remove-redundant-disconnect.patch85
-rw-r--r--usb/usb-ehci-clear-phcd-before-resuming.patch57
-rw-r--r--usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch392
-rw-r--r--usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch61
-rw-r--r--usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch57
-rw-r--r--usb/usb-fix-functionfs-for-config_net-disabled.patch64
-rw-r--r--usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch114
-rw-r--r--usb/usb-io_edgeport-use-kzalloc.patch54
-rw-r--r--usb/usb-ipw-clean-up-dtr-rts-handling.patch94
-rw-r--r--usb/usb-ipw-reimplement-using-generic-framework.patch202
-rw-r--r--usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch46
-rw-r--r--usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch70
-rw-r--r--usb/usb-ir-usb-fix-double-free.patch38
-rw-r--r--usb/usb-ir-usb-fix-set_termios-race.patch117
-rw-r--r--usb/usb-ir-usb-reimplement-using-generic-framework.patch289
-rw-r--r--usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch2
-rw-r--r--usb/usb-remove-usb_find_device.patch89
-rw-r--r--usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch58
22 files changed, 2130 insertions, 1 deletions
diff --git a/series b/series
index 5c607ca92af61d..afff2b2a27851d 100644
--- a/series
+++ b/series
@@ -90,6 +90,8 @@ tty/serial-add-driver-for-the-altera-jtag-uart.patch
tty/serial-add-driver-for-the-altera-uart.patch
tty/tty-fix-obsolete-comment-on-tty_insert_flip_string_fixed_flag.patch
tty/serial-bfin_sport_uart-use-resource-size-to-fix-off-by-one-error.patch
+tty/serial-isicomm-handle-running-out-of-slots.patch
+tty/serial-apbuart-let-boards-without-apbuart-boot.patch
###################################
@@ -258,6 +260,24 @@ usb/usb-gadget-f_fs.c-needs-to-include-pagemap.h.patch
usb/usb-xhci-transfer-ring-link-trb-activation-change.patch
usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch
usb/usb-fix-interface-runtime-pm-settings.patch
+usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch
+usb/usb-add-missing-in-map_urb_for_dma.patch
+usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch
+usb/usb-remove-usb_find_device.patch
+usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch
+usb/usb-fix-functionfs-for-config_net-disabled.patch
+usb/usb-ehci-clear-phcd-before-resuming.patch
+usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch
+usb/usb-ir-usb-fix-double-free.patch
+usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch
+usb/usb-ir-usb-fix-set_termios-race.patch
+usb/usb-ir-usb-reimplement-using-generic-framework.patch
+usb/usb-ipw-clean-up-dtr-rts-handling.patch
+usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch
+usb/usb-ipw-reimplement-using-generic-framework.patch
+usb/usb-io_edgeport-use-kzalloc.patch
+usb/usb-cp210x-remove-redundant-disconnect.patch
+usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch
# this goes in last.
usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch
diff --git a/tty/serial-apbuart-let-boards-without-apbuart-boot.patch b/tty/serial-apbuart-let-boards-without-apbuart-boot.patch
new file mode 100644
index 00000000000000..a1acb9e93dceae
--- /dev/null
+++ b/tty/serial-apbuart-let-boards-without-apbuart-boot.patch
@@ -0,0 +1,130 @@
+From avorontsov@mvista.com Fri May 14 12:17:06 2010
+From: Anton Vorontsov <avorontsov@mvista.com>
+Date: Fri, 14 May 2010 18:19:49 +0400
+Subject: serial: apbuart: Let boards without apbuart boot
+To: David Miller <davem@davemloft.net>, Greg Kroah-Hartman <gregkh@suse.de>
+Cc: Kristoffer Glembo <kristoffer@gaisler.com>, linux-kernel@vger.kernel.org
+Message-ID: <20100514141949.GA9244@oksana.dev.rtsoft.ru>
+Content-Disposition: inline
+
+
+This patch fixes the following oops:
+
+ Unable to handle kernel paging request for data at address 0x00000000
+ Faulting instruction address: 0xc016dea8
+ Oops: Kernel access of bad area, sig: 11 [#1]
+ P1020 RDB
+ last sysfs file:
+ NIP: c016dea8 LR: c016dea0 CTR: c0010948
+ REGS: c033fea0 TRAP: 0300 Not tainted (2.6.34-rc7-00108-g83b5177-dirty)
+ [...]
+ NIP [c016dea8] grlib_apbuart_configure+0xd0/0x3bc
+ LR [c016dea0] grlib_apbuart_configure+0xc8/0x3bc
+ Call Trace:
+ [c033ff50] [c016dea0] grlib_apbuart_configure+0xc8/0x3bc (unreliable)
+ [c033ffa0] [c0316144] apbuart_console_init+0x10/0x34
+ [c033ffb0] [c0314a10] console_init+0x40/0x5c
+
+There's no apbuart on P1020 boards, and what's worse, there's no
+clock-frequency property for it. The driver didn't handle this
+case, which resulted in the oops above. Once we fix this, the
+next oops pops up:
+
+ Unable to handle kernel paging request for data at address 0x00000030
+ Faulting instruction address: 0xc0166ecc
+ Oops: Kernel access of bad area, sig: 11 [#1]
+ P1020 RDB
+ [...]
+ NIP [c0166ecc] uart_set_options+0xd0/0x164
+ LR [c0166e38] uart_set_options+0x3c/0x164
+ Call Trace:
+ [c033fef0] [c0330000] 0xc0330000 (unreliable)
+ [c033ff50] [c03160dc] apbuart_console_setup+0xa8/0x100
+ [c033ff70] [c003d668] register_console+0x338/0x3ec
+ [c033ffa0] [c0316154] apbuart_console_init+0x20/0x34
+ [c033ffb0] [c0314a10] console_init+0x40/0x5c
+ [c033ffc0] [c0300968] start_kernel+0x12c/0x234
+ [c033fff0] [c0000398] skpinv+0x2b0/0x2ec
+
+And that one is because the driver tries to register the console
+even if there were no matches in grlib_apbuart_configure().
+
+While at it, also annotate grlib_apbuart_configure() with __init,
+that fixes several section mismatches:
+
+ Section mismatch in reference from the function
+ grlib_apbuart_configure() to the variable .init.data:apbuart_match
+ The function grlib_apbuart_configure() references the variable
+ __initdata apbuart_match.
+
+Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/apbuart.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/drivers/serial/apbuart.c
++++ b/drivers/serial/apbuart.c
+@@ -520,11 +520,16 @@ static struct console grlib_apbuart_cons
+ };
+
+
+-static void grlib_apbuart_configure(void);
++static int __init grlib_apbuart_configure(void);
+
+ static int __init apbuart_console_init(void)
+ {
+- grlib_apbuart_configure();
++ int ret;
++
++ ret = grlib_apbuart_configure();
++ if (ret)
++ return ret;
++
+ register_console(&grlib_apbuart_console);
+ return 0;
+ }
+@@ -593,7 +598,7 @@ static struct of_platform_driver grlib_a
+ };
+
+
+-static void grlib_apbuart_configure(void)
++static int __init grlib_apbuart_configure(void)
+ {
+ static int enum_done;
+ struct device_node *np, *rp;
+@@ -606,12 +611,14 @@ static void grlib_apbuart_configure(void
+ struct amba_prom_registers *regs;
+
+ if (enum_done)
+- return;
++ return -ENODEV;
+
+ /* Get bus frequency */
+ rp = of_find_node_by_path("/");
+ rp = of_get_next_child(rp, NULL);
+ prop = of_get_property(rp, "clock-frequency", NULL);
++ if (!prop)
++ return -ENODEV;
+ freq_khz = *prop;
+
+ line = 0;
+@@ -629,7 +636,7 @@ static void grlib_apbuart_configure(void
+ d = *device;
+
+ if (!irqs || !regs)
+- return;
++ return -ENODEV;
+
+ grlib_apbuart_nodes[line] = np;
+
+@@ -658,6 +665,8 @@ static void grlib_apbuart_configure(void
+ enum_done = 1;
+
+ grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
++
++ return line ? 0 : -ENODEV;
+ }
+
+ static int __init grlib_apbuart_init(void)
diff --git a/tty/serial-isicomm-handle-running-out-of-slots.patch b/tty/serial-isicomm-handle-running-out-of-slots.patch
new file mode 100644
index 00000000000000..3495882381d85b
--- /dev/null
+++ b/tty/serial-isicomm-handle-running-out-of-slots.patch
@@ -0,0 +1,49 @@
+From error27@gmail.com Fri May 14 12:00:10 2010
+From: Dan Carpenter <error27@gmail.com>
+Date: Fri, 7 May 2010 10:30:41 +0200
+Subject: serial: isicomm: handle running out of slots
+To: Jiri Slaby <jirislaby@gmail.com>
+Cc: Alan Cox <alan@linux.intel.com>, Greg Kroah-Hartman <gregkh@suse.de>, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org
+Message-ID: <20100507083041.GU27064@bicker>
+Content-Disposition: inline
+
+
+This patch makes it return -ENODEV if we run out of empty slots in the
+probe function. It's unlikely to happen, but it makes the static
+checkers happy.
+
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/isicom.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/isicom.c
++++ b/drivers/char/isicom.c
+@@ -1573,11 +1573,16 @@ static int __devinit isicom_probe(struct
+ dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
+
+ /* allot the first empty slot in the array */
+- for (index = 0; index < BOARD_COUNT; index++)
++ for (index = 0; index < BOARD_COUNT; index++) {
+ if (isi_card[index].base == 0) {
+ board = &isi_card[index];
+ break;
+ }
++ }
++ if (index == BOARD_COUNT) {
++ retval = -ENODEV;
++ goto err_disable;
++ }
+
+ board->index = index;
+ board->base = pci_resource_start(pdev, 3);
+@@ -1624,6 +1629,7 @@ errunrr:
+ errdec:
+ board->base = 0;
+ card_count--;
++err_disable:
+ pci_disable_device(pdev);
+ err:
+ return retval;
diff --git a/usb/usb-add-missing-in-map_urb_for_dma.patch b/usb/usb-add-missing-in-map_urb_for_dma.patch
new file mode 100644
index 00000000000000..9a6f985ac57f52
--- /dev/null
+++ b/usb/usb-add-missing-in-map_urb_for_dma.patch
@@ -0,0 +1,43 @@
+From tom.leiming@gmail.com Fri May 14 12:02:26 2010
+From: tom.leiming@gmail.com
+Date: Wed, 12 May 2010 23:38:12 +0800
+Subject: USB: add missing "{}" in map_urb_for_dma
+To: greg@kroah.com, stern@rowland.harvard.edu
+Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com>
+Message-ID: <1273678692-19602-1-git-send-email-tom.leiming@gmail.com>
+
+
+From: Ming Lei <tom.leiming@gmail.com>
+
+Obviously, {} is needed in the branch of
+ "else if (hcd->driver->flags & HCD_LOCAL_MEM)"
+for handling of setup packet mapping.
+
+Signed-off-by: Ming Lei <tom.leiming@gmail.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1327,7 +1327,7 @@ static int map_urb_for_dma(struct usb_hc
+ urb->setup_dma))
+ return -EAGAIN;
+ urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
+- } else if (hcd->driver->flags & HCD_LOCAL_MEM)
++ } else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+ ret = hcd_alloc_coherent(
+ urb->dev->bus, mem_flags,
+ &urb->setup_dma,
+@@ -1337,6 +1337,7 @@ static int map_urb_for_dma(struct usb_hc
+ if (ret)
+ return ret;
+ urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
++ }
+ }
+
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
diff --git a/usb/usb-cp210x-remove-redundant-disconnect.patch b/usb/usb-cp210x-remove-redundant-disconnect.patch
new file mode 100644
index 00000000000000..4b5a8e4aa4c8ac
--- /dev/null
+++ b/usb/usb-cp210x-remove-redundant-disconnect.patch
@@ -0,0 +1,85 @@
+From jhovold@gmail.com Fri May 14 12:15:54 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 22:25:09 +0200
+Subject: USB: cp210x: remove redundant disconnect()
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273782309-18670-1-git-send-email-jhovold@gmail.com>
+
+
+Remove cp210x_disconnect which is used to kill traffic although this is
+already handled by the generic framework.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/cp210x.c | 29 -----------------------------
+ 1 file changed, 29 deletions(-)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -34,7 +34,6 @@
+ * Function Prototypes
+ */
+ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
+-static void cp210x_cleanup(struct usb_serial_port *);
+ static void cp210x_close(struct usb_serial_port *);
+ static void cp210x_get_termios(struct tty_struct *,
+ struct usb_serial_port *port);
+@@ -49,7 +48,6 @@ static int cp210x_tiocmset_port(struct u
+ unsigned int, unsigned int);
+ static void cp210x_break_ctl(struct tty_struct *, int);
+ static int cp210x_startup(struct usb_serial *);
+-static void cp210x_disconnect(struct usb_serial *);
+ static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
+ static int cp210x_carrier_raised(struct usb_serial_port *p);
+
+@@ -147,7 +145,6 @@ static struct usb_serial_driver cp210x_d
+ .tiocmget = cp210x_tiocmget,
+ .tiocmset = cp210x_tiocmset,
+ .attach = cp210x_startup,
+- .disconnect = cp210x_disconnect,
+ .dtr_rts = cp210x_dtr_rts,
+ .carrier_raised = cp210x_carrier_raised
+ };
+@@ -391,21 +388,6 @@ static int cp210x_open(struct tty_struct
+ return 0;
+ }
+
+-static void cp210x_cleanup(struct usb_serial_port *port)
+-{
+- struct usb_serial *serial = port->serial;
+-
+- dbg("%s - port %d", __func__, port->number);
+-
+- if (serial->dev) {
+- /* shutdown any bulk reads that might be going on */
+- if (serial->num_bulk_out)
+- usb_kill_urb(port->write_urb);
+- if (serial->num_bulk_in)
+- usb_kill_urb(port->read_urb);
+- }
+-}
+-
+ static void cp210x_close(struct usb_serial_port *port)
+ {
+ dbg("%s - port %d", __func__, port->number);
+@@ -794,17 +776,6 @@ static int cp210x_startup(struct usb_ser
+ return 0;
+ }
+
+-static void cp210x_disconnect(struct usb_serial *serial)
+-{
+- int i;
+-
+- dbg("%s", __func__);
+-
+- /* Stop reads and writes on all ports */
+- for (i = 0; i < serial->num_ports; ++i)
+- cp210x_cleanup(serial->port[i]);
+-}
+-
+ static int __init cp210x_init(void)
+ {
+ int retval;
diff --git a/usb/usb-ehci-clear-phcd-before-resuming.patch b/usb/usb-ehci-clear-phcd-before-resuming.patch
new file mode 100644
index 00000000000000..c7c4e71bcce302
--- /dev/null
+++ b/usb/usb-ehci-clear-phcd-before-resuming.patch
@@ -0,0 +1,57 @@
+From alek.du@intel.com Fri May 14 12:11:52 2010
+From: "Du, Alek" <alek.du@intel.com>
+Date: Mon, 10 May 2010 11:17:49 +0800
+Subject: USB: EHCI: clear PHCD before resuming
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Message-ID: <20100510111749.6c8c7df8@dxy2>
+
+
+From: Alek Du <alek.du@intel.com>
+
+This is a bug fix for PHCD (phy clock disable) low power feature:
+After PHCD is set, any write to PORTSC register is illegal, so when
+resume ports, clear PHCD bit first.
+
+Signed-off-by: Alek Du <alek.du@intel.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-hub.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -294,6 +294,16 @@ static int ehci_bus_resume (struct usb_h
+ /* manually resume the ports we suspended during bus_suspend() */
+ i = HCS_N_PORTS (ehci->hcs_params);
+ while (i--) {
++ /* clear phy low power mode before resume */
++ if (ehci->has_hostpc) {
++ u32 __iomem *hostpc_reg =
++ (u32 __iomem *)((u8 *)ehci->regs
++ + HOSTPC0 + 4 * (i & 0xff));
++ temp = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp & ~HOSTPC_PHCD,
++ hostpc_reg);
++ mdelay(5);
++ }
+ temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ if (test_bit(i, &ehci->bus_suspended) &&
+@@ -678,6 +688,13 @@ static int ehci_hub_control (
+ if (temp & PORT_SUSPEND) {
+ if ((temp & PORT_PE) == 0)
+ goto error;
++ /* clear phy low power mode before resume */
++ if (hostpc_reg) {
++ temp1 = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
++ hostpc_reg);
++ mdelay(5);
++ }
+ /* resume signaling for 20 msec */
+ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ ehci_writel(ehci, temp | PORT_RESUME,
diff --git a/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch b/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch
new file mode 100644
index 00000000000000..9a1d0af1f37221
--- /dev/null
+++ b/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch
@@ -0,0 +1,392 @@
+From stern@rowland.harvard.edu Fri May 14 12:12:30 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 12 May 2010 18:21:35 -0400 (EDT)
+Subject: USB: EHCI: fix controller wakeup flag settings during suspend
+To: Greg KH <greg@kroah.com>
+Cc: Ondrej Zary <linux@rainbow-software.org>, Alek Du <alek.du@intel.com>, USB list <linux-usb@vger.kernel.org>
+Message-ID: <Pine.LNX.4.44L0.1005121818360.1353-100000@iolanthe.rowland.org>
+
+
+This patch (as1380) fixes a bug in the wakeup settings for EHCI host
+controllers. When the controller is suspended, if it isn't enabled
+for remote wakeup then we have to turn off all the port wakeup flags.
+Disabling PCI PME# isn't good enough, because some systems (Intel)
+evidently use alternate wakeup signalling paths.
+
+In addition, the patch improves the handling of the Intel Moorestown
+hardware by performing various power-up and power-down delays just
+once instead of once for each port (i.e., the delays are moved outside
+of the port loops). This requires extra code, but the total delay
+time is reduced.
+
+There are also a few additional minor cleanups.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-by: Ondrej Zary <linux@rainbow-software.org>
+CC: Alek Du <alek.du@intel.com>
+CC: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-au1xxx.c | 16 ---
+ drivers/usb/host/ehci-fsl.c | 2
+ drivers/usb/host/ehci-hub.c | 173 +++++++++++++++++++++++++++++------------
+ drivers/usb/host/ehci-pci.c | 15 ---
+ drivers/usb/host/ehci.h | 10 ++
+ 5 files changed, 145 insertions(+), 71 deletions(-)
+
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -224,26 +224,17 @@ static int ehci_hcd_au1xxx_drv_suspend(s
+ msleep(10);
+
+ /* Root hub was already suspended. Disable irq emission and
+- * mark HW unaccessible, bail out if RH has been resumed. Use
+- * the spinlock to properly synchronize with possible pending
+- * RH suspend or resume activity.
+- *
+- * This is still racy as hcd->state is manipulated outside of
+- * any locks =P But that will be a different fix.
++ * mark HW unaccessible. The PM and USB cores make sure that
++ * the root hub is either suspended or stopped.
+ */
+ spin_lock_irqsave(&ehci->lock, flags);
+- if (hcd->state != HC_STATE_SUSPENDED) {
+- rc = -EINVAL;
+- goto bail;
+- }
++ ehci_prepare_ports_for_controller_suspend(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
+
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ au1xxx_stop_ehc();
+-
+-bail:
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ // could save FLADJ in case of Vaux power loss
+@@ -273,6 +264,7 @@ static int ehci_hcd_au1xxx_drv_resume(st
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
++ ehci_prepare_ports_for_controller_resume(ehci);
+ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct d
+ struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+ void __iomem *non_ehci = hcd->regs;
+
++ ehci_prepare_ports_for_controller_suspend(ehci);
+ if (!fsl_deep_sleep())
+ return 0;
+
+@@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct de
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ void __iomem *non_ehci = hcd->regs;
+
++ ehci_prepare_ports_for_controller_resume(ehci);
+ if (!fsl_deep_sleep())
+ return 0;
+
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -106,12 +106,75 @@ static void ehci_handover_companion_port
+ ehci->owned_ports = 0;
+ }
+
++static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
++ bool suspending)
++{
++ int port;
++ u32 temp;
++
++ /* If remote wakeup is enabled for the root hub but disabled
++ * for the controller, we must adjust all the port wakeup flags
++ * 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))
++ return;
++
++ /* clear phy low-power mode before changing wakeup flags */
++ if (ehci->has_hostpc) {
++ port = HCS_N_PORTS(ehci->hcs_params);
++ while (port--) {
++ u32 __iomem *hostpc_reg;
++
++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++ + HOSTPC0 + 4 * port);
++ temp = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
++ }
++ msleep(5);
++ }
++
++ port = HCS_N_PORTS(ehci->hcs_params);
++ while (port--) {
++ u32 __iomem *reg = &ehci->regs->port_status[port];
++ u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
++ u32 t2 = t1 & ~PORT_WAKE_BITS;
++
++ /* If we are suspending the controller, clear the flags.
++ * If we are resuming the controller, set the wakeup flags.
++ */
++ if (!suspending) {
++ if (t1 & PORT_CONNECT)
++ t2 |= PORT_WKOC_E | PORT_WKDISC_E;
++ else
++ t2 |= PORT_WKOC_E | PORT_WKCONN_E;
++ }
++ ehci_vdbg(ehci, "port %d, %08x -> %08x\n",
++ port + 1, t1, t2);
++ ehci_writel(ehci, t2, reg);
++ }
++
++ /* enter phy low-power mode again */
++ if (ehci->has_hostpc) {
++ port = HCS_N_PORTS(ehci->hcs_params);
++ while (port--) {
++ u32 __iomem *hostpc_reg;
++
++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++ + HOSTPC0 + 4 * port);
++ temp = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
++ }
++ }
++}
++
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ int port;
+ int mask;
+- u32 __iomem *hostpc_reg = NULL;
++ int changed;
+
+ ehci_dbg(ehci, "suspend root hub\n");
+
+@@ -155,15 +218,13 @@ static int ehci_bus_suspend (struct usb_
+ */
+ ehci->bus_suspended = 0;
+ ehci->owned_ports = 0;
++ changed = 0;
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ u32 __iomem *reg = &ehci->regs->port_status [port];
+ u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+- u32 t2 = t1;
++ u32 t2 = t1 & ~PORT_WAKE_BITS;
+
+- if (ehci->has_hostpc)
+- hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
+- + HOSTPC0 + 4 * (port & 0xff));
+ /* keep track of which ports we suspend */
+ if (t1 & PORT_OWNER)
+ set_bit(port, &ehci->owned_ports);
+@@ -172,40 +233,45 @@ static int ehci_bus_suspend (struct usb_
+ set_bit(port, &ehci->bus_suspended);
+ }
+
+- /* enable remote wakeup on all ports */
++ /* enable remote wakeup on all ports, if told to do so */
+ if (hcd->self.root_hub->do_remote_wakeup) {
+ /* only enable appropriate wake bits, otherwise the
+ * hardware can not go phy low power mode. If a race
+ * condition happens here(connection change during bits
+ * set), the port change detection will finally fix it.
+ */
+- if (t1 & PORT_CONNECT) {
++ if (t1 & PORT_CONNECT)
+ t2 |= PORT_WKOC_E | PORT_WKDISC_E;
+- t2 &= ~PORT_WKCONN_E;
+- } else {
++ else
+ t2 |= PORT_WKOC_E | PORT_WKCONN_E;
+- t2 &= ~PORT_WKDISC_E;
+- }
+- } else
+- t2 &= ~PORT_WAKE_BITS;
++ }
+
+ if (t1 != t2) {
+ ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+ port + 1, t1, t2);
+ ehci_writel(ehci, t2, reg);
+- if (hostpc_reg) {
+- u32 t3;
++ changed = 1;
++ }
++ }
+
+- spin_unlock_irq(&ehci->lock);
+- msleep(5);/* 5ms for HCD enter low pwr mode */
+- spin_lock_irq(&ehci->lock);
+- t3 = ehci_readl(ehci, hostpc_reg);
+- ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
+- t3 = ehci_readl(ehci, hostpc_reg);
+- ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
++ if (changed && ehci->has_hostpc) {
++ spin_unlock_irq(&ehci->lock);
++ msleep(5); /* 5 ms for HCD to enter low-power mode */
++ spin_lock_irq(&ehci->lock);
++
++ port = HCS_N_PORTS(ehci->hcs_params);
++ while (port--) {
++ u32 __iomem *hostpc_reg;
++ u32 t3;
++
++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++ + HOSTPC0 + 4 * port);
++ t3 = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
++ t3 = ehci_readl(ehci, hostpc_reg);
++ ehci_dbg(ehci, "Port %d phy low-power mode %s\n",
+ port, (t3 & HOSTPC_PHCD) ?
+ "succeeded" : "failed");
+- }
+ }
+ }
+
+@@ -291,19 +357,28 @@ static int ehci_bus_resume (struct usb_h
+ msleep(8);
+ spin_lock_irq(&ehci->lock);
+
++ /* clear phy low-power mode before resume */
++ if (ehci->bus_suspended && ehci->has_hostpc) {
++ i = HCS_N_PORTS(ehci->hcs_params);
++ while (i--) {
++ if (test_bit(i, &ehci->bus_suspended)) {
++ u32 __iomem *hostpc_reg;
++
++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++ + HOSTPC0 + 4 * i);
++ temp = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp & ~HOSTPC_PHCD,
++ hostpc_reg);
++ }
++ }
++ spin_unlock_irq(&ehci->lock);
++ msleep(5);
++ spin_lock_irq(&ehci->lock);
++ }
++
+ /* manually resume the ports we suspended during bus_suspend() */
+ i = HCS_N_PORTS (ehci->hcs_params);
+ while (i--) {
+- /* clear phy low power mode before resume */
+- if (ehci->has_hostpc) {
+- u32 __iomem *hostpc_reg =
+- (u32 __iomem *)((u8 *)ehci->regs
+- + HOSTPC0 + 4 * (i & 0xff));
+- temp = ehci_readl(ehci, hostpc_reg);
+- ehci_writel(ehci, temp & ~HOSTPC_PHCD,
+- hostpc_reg);
+- mdelay(5);
+- }
+ temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ if (test_bit(i, &ehci->bus_suspended) &&
+@@ -685,23 +760,25 @@ static int ehci_hub_control (
+ goto error;
+ if (ehci->no_selective_suspend)
+ break;
+- if (temp & PORT_SUSPEND) {
+- if ((temp & PORT_PE) == 0)
+- goto error;
+- /* clear phy low power mode before resume */
+- if (hostpc_reg) {
+- temp1 = ehci_readl(ehci, hostpc_reg);
+- ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
++ if (!(temp & PORT_SUSPEND))
++ break;
++ if ((temp & PORT_PE) == 0)
++ goto error;
++
++ /* clear phy low-power mode before resume */
++ if (hostpc_reg) {
++ temp1 = ehci_readl(ehci, hostpc_reg);
++ ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
+ hostpc_reg);
+- mdelay(5);
+- }
+- /* resume signaling for 20 msec */
+- temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+- ehci_writel(ehci, temp | PORT_RESUME,
+- status_reg);
+- ehci->reset_done [wIndex] = jiffies
+- + msecs_to_jiffies (20);
++ spin_unlock_irqrestore(&ehci->lock, flags);
++ msleep(5);/* wait to leave low-power mode */
++ spin_lock_irqsave(&ehci->lock, flags);
+ }
++ /* resume signaling for 20 msec */
++ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
++ ehci_writel(ehci, temp | PORT_RESUME, status_reg);
++ ehci->reset_done[wIndex] = jiffies
++ + msecs_to_jiffies(20);
+ break;
+ case USB_PORT_FEAT_C_SUSPEND:
+ clear_bit(wIndex, &ehci->port_c_suspend);
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -287,23 +287,15 @@ static int ehci_pci_suspend(struct usb_h
+ msleep(10);
+
+ /* Root hub was already suspended. Disable irq emission and
+- * mark HW unaccessible, bail out if RH has been resumed. Use
+- * the spinlock to properly synchronize with possible pending
+- * RH suspend or resume activity.
+- *
+- * This is still racy as hcd->state is manipulated outside of
+- * any locks =P But that will be a different fix.
++ * mark HW unaccessible. The PM and USB cores make sure that
++ * the root hub is either suspended or stopped.
+ */
+ spin_lock_irqsave (&ehci->lock, flags);
+- if (hcd->state != HC_STATE_SUSPENDED) {
+- rc = -EINVAL;
+- goto bail;
+- }
++ ehci_prepare_ports_for_controller_suspend(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
+
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+- bail:
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+ // could save FLADJ in case of Vaux power loss
+@@ -333,6 +325,7 @@ static int ehci_pci_resume(struct usb_hc
+ !hibernated) {
+ int mask = INTR_MASK;
+
++ ehci_prepare_ports_for_controller_resume(ehci);
+ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -536,6 +536,16 @@ struct ehci_fstn {
+
+ /*-------------------------------------------------------------------------*/
+
++/* 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_resume(ehci) \
++ ehci_adjust_port_wakeup_flags(ehci, false);
++
++/*-------------------------------------------------------------------------*/
++
+ #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
+
+ /*
diff --git a/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch b/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch
new file mode 100644
index 00000000000000..b7406d082f8cd7
--- /dev/null
+++ b/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch
@@ -0,0 +1,61 @@
+From gadiyar@ti.com Fri May 14 11:59:46 2010
+From: Anand Gadiyar <gadiyar@ti.com>
+Date: Thu, 6 May 2010 20:09:48 +0530
+Subject: USB: ehci-omap: Fix resume failures after bus suspend
+To: linux-usb@vger.kernel.org, Greg KH <gregkh@suse.de>
+Cc: Anand Gadiyar <gadiyar@ti.com>
+Message-ID: <1273156788-22853-1-git-send-email-gadiyar@ti.com>
+
+
+An undocumented "feature" in the OMAP3 EHCI controller causes
+suspended ports to be taken out of suspend when the USBCMD.Run/Stop
+bit is cleared (this bit is normally cleared when ehci_bus_suspend
+is called).
+
+This "feature" breaks suspend-resume if the root-hub is allowed
+to suspend. (The controller thinks it is in resume, and the PHY
+thinks it is still in suspend).
+
+There is an undocumented register bit that can be used to disable
+this feature and restore normal behavior. Set this bit so
+suspend-resume can work normally.
+
+Tested on OMAP3 SDPs with the NXP ISP1504 and NXP ISP1703 PHYs.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-omap.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -116,6 +116,8 @@
+ #define OMAP_UHH_DEBUG_CSR (0x44)
+
+ /* EHCI Register Set */
++#define EHCI_INSNREG04 (0xA0)
++#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
+ #define EHCI_INSNREG05_ULPI (0xA4)
+ #define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31
+ #define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24
+@@ -382,6 +384,18 @@ static int omap_start_ehc(struct ehci_hc
+ dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
+
+
++ /*
++ * An undocumented "feature" in the OMAP3 EHCI controller,
++ * causes suspended ports to be taken out of suspend when
++ * the USBCMD.Run/Stop bit is cleared (for example when
++ * we do ehci_bus_suspend).
++ * This breaks suspend-resume if the root-hub is allowed
++ * to suspend. Writing 1 to this undocumented register bit
++ * disables this feature and restores normal behavior.
++ */
++ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
++ EHCI_INSNREG04_DISABLE_UNSUSPEND);
++
+ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
+ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
+ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
diff --git a/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch b/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch
new file mode 100644
index 00000000000000..3eb636f26a5c3a
--- /dev/null
+++ b/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch
@@ -0,0 +1,57 @@
+From avorontsov@mvista.com Fri May 14 12:16:13 2010
+From: Anton Vorontsov <avorontsov@mvista.com>
+Date: Fri, 14 May 2010 18:33:18 +0400
+Subject: USB: FHCI: cq_get() should check kfifo_out()'s return value
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, linuxppc-dev@ozlabs.org
+Message-ID: <20100514143318.GA14034@oksana.dev.rtsoft.ru>
+Content-Disposition: inline
+
+
+Since commit 7acd72eb85f1c7a15e8b5eb554994949241737f1 ("kfifo: rename
+kfifo_put... into kfifo_in... and kfifo_get... into kfifo_out..."),
+kfifo_out() is marked __must_check, and that causes gcc to produce
+lots of warnings like this:
+
+ CC drivers/usb/host/fhci-mem.o
+In file included from drivers/usb/host/fhci-hcd.c:34:
+drivers/usb/host/fhci.h: In function 'cq_get':
+drivers/usb/host/fhci.h:520: warning: ignoring return value of 'kfifo_out', declared with attribute warn_unused_result
+...
+
+This patch fixes the issue by properly checking the return value.
+
+Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
+Cc: stable <stable@kernel.org> [.33 and .34]
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/fhci.h | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/fhci.h
++++ b/drivers/usb/host/fhci.h
+@@ -20,6 +20,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/types.h>
++#include <linux/bug.h>
+ #include <linux/spinlock.h>
+ #include <linux/interrupt.h>
+ #include <linux/kfifo.h>
+@@ -515,9 +516,13 @@ static inline int cq_put(struct kfifo *k
+
+ static inline void *cq_get(struct kfifo *kfifo)
+ {
+- void *p = NULL;
++ unsigned int sz;
++ void *p;
++
++ sz = kfifo_out(kfifo, (void *)&p, sizeof(p));
++ if (sz != sizeof(p))
++ return NULL;
+
+- kfifo_out(kfifo, (void *)&p, sizeof(p));
+ return p;
+ }
+
diff --git a/usb/usb-fix-functionfs-for-config_net-disabled.patch b/usb/usb-fix-functionfs-for-config_net-disabled.patch
new file mode 100644
index 00000000000000..9dd4e706bc8078
--- /dev/null
+++ b/usb/usb-fix-functionfs-for-config_net-disabled.patch
@@ -0,0 +1,64 @@
+From randy.dunlap@oracle.com Fri May 14 12:09:56 2010
+From: Randy Dunlap <randy.dunlap@oracle.com>
+Date: Thu, 13 May 2010 09:41:12 -0700
+Subject: USB: fix functionfs for CONFIG_NET disabled
+To: Stephen Rothwell <sfr@canb.auug.org.au>, gregkh@suse.de, Michal Nazarewicz <m.nazarewicz@samsung.com>
+Message-ID: <20100513094112.86acf7c2.randy.dunlap@oracle.com>
+
+
+From: Randy Dunlap <randy.dunlap@oracle.com>
+
+Fix functionfs build to handle CONFIG_NET not enabled, to prevent
+these build errors:
+
+ERROR: "netif_carrier_on" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "netif_carrier_off" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_realloc_headroom" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_trim" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "netif_rx" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "alloc_etherdev_mq" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "ethtool_op_get_link" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "free_netdev" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "register_netdev" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_push" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_pull" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "dev_kfree_skb_any" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_queue_tail" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "__alloc_skb" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "eth_type_trans" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "eth_validate_addr" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_dequeue" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "unregister_netdev" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "__netif_schedule" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "skb_put" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "eth_mac_addr" [drivers/usb/gadget/g_ffs.ko] undefined!
+ERROR: "dev_get_stats" [drivers/usb/gadget/g_ffs.ko] undefined!
+
+Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
+Acked-by: Michał Nazarewicz <m.nazarewicz@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -726,7 +726,7 @@ config USB_FUNCTIONFS
+
+ config USB_FUNCTIONFS_ETH
+ bool "Include CDC ECM (Ethernet) function"
+- depends on USB_FUNCTIONFS
++ 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
+@@ -734,7 +734,7 @@ config USB_FUNCTIONFS_ETH
+
+ config USB_FUNCTIONFS_RNDIS
+ bool "Include RNDIS (Ethernet) function"
+- depends on USB_FUNCTIONFS
++ 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
diff --git a/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch b/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch
new file mode 100644
index 00000000000000..b1426e2211d562
--- /dev/null
+++ b/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch
@@ -0,0 +1,114 @@
+From m.nazarewicz@samsung.com Fri May 14 12:03:03 2010
+From: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Date: Wed, 12 May 2010 12:51:13 +0200
+Subject: USB: gadget: f_mass_storage: fix in error recovery
+To: linux-usb@vger.kernel.org
+Cc: Kyungmin Park <kyungmin.park@samsung.com>, Marek Szyprowski <m.szyprowski@samsung.com>, Viral Mehta <Viral.Mehta@lntinfotech.com>, linux-kernel@vger.kernel.org, Michal Nazarewicz <mina86@mina86.com>
+Message-ID: <1148fb1fcb3a9864a2a12fbbf2e3444827c9ed4a.1273661077.git.mina86@mina86.com>
+
+
+In to places in fsg_common_init() an unconditional call to kfree()
+on common was performed in error recovery which is not a valid
+behaviour since fsg_common structure is not always allocated by
+fsg_common_init().
+
+To fix, the calls has been replaced with a goto to a proper error
+recovery which does the correct thing.
+
+Also, refactored fsg_common_release() function.
+
+Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
+Reviewed-by: Viral Mehta <viral.mehta@lntinfotech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/f_mass_storage.c | 55 +++++++++++++++++-------------------
+ 1 file changed, 27 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -2742,10 +2742,8 @@ static struct fsg_common *fsg_common_ini
+ /* Maybe allocate device-global string IDs, and patch descriptors */
+ if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
+ rc = usb_string_id(cdev);
+- if (rc < 0) {
+- kfree(common);
+- return ERR_PTR(rc);
+- }
++ if (unlikely(rc < 0))
++ goto error_release;
+ fsg_strings[FSG_STRING_INTERFACE].id = rc;
+ fsg_intf_desc.iInterface = rc;
+ }
+@@ -2753,9 +2751,9 @@ static struct fsg_common *fsg_common_ini
+ /* Create the LUNs, open their backing files, and register the
+ * LUN devices in sysfs. */
+ curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
+- if (!curlun) {
+- kfree(common);
+- return ERR_PTR(-ENOMEM);
++ if (unlikely(!curlun)) {
++ rc = -ENOMEM;
++ goto error_release;
+ }
+ common->luns = curlun;
+
+@@ -2914,11 +2912,7 @@ error_release:
+
+ static void fsg_common_release(struct kref *ref)
+ {
+- struct fsg_common *common =
+- container_of(ref, struct fsg_common, ref);
+- unsigned i = common->nluns;
+- struct fsg_lun *lun = common->luns;
+- struct fsg_buffhd *bh;
++ struct fsg_common *common = container_of(ref, struct fsg_common, ref);
+
+ /* If the thread isn't already dead, tell it to exit now */
+ if (common->state != FSG_STATE_TERMINATED) {
+@@ -2929,24 +2923,29 @@ static void fsg_common_release(struct kr
+ complete(&common->thread_notifier);
+ }
+
+- /* Beware tempting for -> do-while optimization: when in error
+- * recovery nluns may be zero. */
+-
+- for (; i; --i, ++lun) {
+- device_remove_file(&lun->dev, &dev_attr_ro);
+- device_remove_file(&lun->dev, &dev_attr_file);
+- fsg_lun_close(lun);
+- device_unregister(&lun->dev);
++ if (likely(common->luns)) {
++ struct fsg_lun *lun = common->luns;
++ unsigned i = common->nluns;
++
++ /* In error recovery common->nluns may be zero. */
++ for (; i; --i, ++lun) {
++ device_remove_file(&lun->dev, &dev_attr_ro);
++ device_remove_file(&lun->dev, &dev_attr_file);
++ fsg_lun_close(lun);
++ device_unregister(&lun->dev);
++ }
++
++ kfree(common->luns);
++ }
++
++ {
++ struct fsg_buffhd *bh = common->buffhds;
++ unsigned i = FSG_NUM_BUFFERS;
++ do {
++ kfree(bh->buf);
++ } while (++bh, --i);
+ }
+
+- kfree(common->luns);
+-
+- i = FSG_NUM_BUFFERS;
+- bh = common->buffhds;
+- do {
+- kfree(bh->buf);
+- } while (++bh, --i);
+-
+ if (common->free_storage_on_release)
+ kfree(common);
+ }
diff --git a/usb/usb-io_edgeport-use-kzalloc.patch b/usb/usb-io_edgeport-use-kzalloc.patch
new file mode 100644
index 00000000000000..8618a0acaacdda
--- /dev/null
+++ b/usb/usb-io_edgeport-use-kzalloc.patch
@@ -0,0 +1,54 @@
+From julia@diku.dk Fri May 14 12:15:34 2010
+From: Julia Lawall <julia@diku.dk>
+Date: Thu, 13 May 2010 22:00:40 +0200 (CEST)
+Subject: USB: io_edgeport: Use kzalloc
+To: Greg Kroah-Hartman <gregkh@suse.de>, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org
+Message-ID: <Pine.LNX.4.64.1005132200240.6282@ask.diku.dk>
+
+
+From: Julia Lawall <julia@diku.dk>
+
+Use kzalloc rather than the combination of kmalloc and memset.
+
+The semantic patch that makes this change is as follows:
+(http://coccinelle.lip6.fr/)
+
+// <smpl>
+@@
+expression x,size,flags;
+statement S;
+@@
+
+-x = kmalloc(size,flags);
++x = kzalloc(size,flags);
+ if (x == NULL) S
+-memset(x, 0, size);
+// </smpl>
+
+Signed-off-by: Julia Lawall <julia@diku.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/io_edgeport.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -3020,7 +3020,7 @@ static int edge_startup(struct usb_seria
+
+ /* set up our port private structures */
+ for (i = 0; i < serial->num_ports; ++i) {
+- edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL);
++ edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
+ if (edge_port == NULL) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
+@@ -3033,7 +3033,6 @@ static int edge_startup(struct usb_seria
+ kfree(edge_serial);
+ return -ENOMEM;
+ }
+- memset(edge_port, 0, sizeof(struct edgeport_port));
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->port = serial->port[i];
+ usb_set_serial_port_data(serial->port[i], edge_port);
diff --git a/usb/usb-ipw-clean-up-dtr-rts-handling.patch b/usb/usb-ipw-clean-up-dtr-rts-handling.patch
new file mode 100644
index 00000000000000..7c14644eb7b281
--- /dev/null
+++ b/usb/usb-ipw-clean-up-dtr-rts-handling.patch
@@ -0,0 +1,94 @@
+From jhovold@gmail.com Fri May 14 12:14:47 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:33:08 +0200
+Subject: USB: ipw: clean up dtr-rts handling
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273779190-8652-2-git-send-email-jhovold@gmail.com>
+
+
+No need to raise dtr/rts in open as this is taken care of by tty layer.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ipw.c | 43 ++++++-------------------------------------
+ 1 file changed, 6 insertions(+), 37 deletions(-)
+
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -267,35 +267,6 @@ static int ipw_open(struct tty_struct *t
+ dev_err(&port->dev,
+ "initial flowcontrol failed (error = %d)\n", result);
+
+-
+- /*--5: raise the dtr */
+- dbg("%s:raising dtr", __func__);
+- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+- IPW_SIO_SET_PIN,
+- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+- IPW_PIN_SETDTR,
+- 0,
+- NULL,
+- 0,
+- 200000);
+- if (result < 0)
+- dev_err(&port->dev,
+- "setting dtr failed (error = %d)\n", result);
+-
+- /*--6: raise the rts */
+- dbg("%s:raising rts", __func__);
+- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+- IPW_SIO_SET_PIN,
+- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+- IPW_PIN_SETRTS,
+- 0,
+- NULL,
+- 0,
+- 200000);
+- if (result < 0)
+- dev_err(&port->dev,
+- "setting dtr failed (error = %d)\n", result);
+-
+ kfree(buf_flow_init);
+ return 0;
+ }
+@@ -305,8 +276,8 @@ static void ipw_dtr_rts(struct usb_seria
+ struct usb_device *dev = port->serial->dev;
+ int result;
+
+- /*--1: drop the dtr */
+- dbg("%s:dropping dtr", __func__);
++ dbg("%s: on = %d", __func__, on);
++
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -316,22 +287,20 @@ static void ipw_dtr_rts(struct usb_seria
+ 0,
+ 200000);
+ if (result < 0)
+- dev_err(&port->dev, "dropping dtr failed (error = %d)\n",
++ dev_err(&port->dev, "setting dtr failed (error = %d)\n",
+ result);
+
+- /*--2: drop the rts */
+- dbg("%s:dropping rts", __func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
+- USB_RECIP_INTERFACE | USB_DIR_OUT,
++ USB_RECIP_INTERFACE | USB_DIR_OUT,
+ on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
+ 0,
+ NULL,
+ 0,
+ 200000);
+ if (result < 0)
+- dev_err(&port->dev,
+- "dropping rts failed (error = %d)\n", result);
++ dev_err(&port->dev, "setting rts failed (error = %d)\n",
++ result);
+ }
+
+ static void ipw_close(struct usb_serial_port *port)
diff --git a/usb/usb-ipw-reimplement-using-generic-framework.patch b/usb/usb-ipw-reimplement-using-generic-framework.patch
new file mode 100644
index 00000000000000..5a9b38101ecb66
--- /dev/null
+++ b/usb/usb-ipw-reimplement-using-generic-framework.patch
@@ -0,0 +1,202 @@
+From jhovold@gmail.com Fri May 14 12:15:10 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:33:10 +0200
+Subject: USB: ipw: reimplement using generic framework
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273779190-8652-4-git-send-email-jhovold@gmail.com>
+
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ipw.c | 128 +----------------------------------------------
+ 1 file changed, 4 insertions(+), 124 deletions(-)
+
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -34,7 +34,6 @@
+ * DCD, DTR, RTS, CTS which are currently faked.
+ * It's good enough for PPP at this point. It's based off all kinds of
+ * code found in usb/serial and usb/class
+- *
+ */
+
+ #include <linux/kernel.h>
+@@ -52,7 +51,7 @@
+ /*
+ * Version Information
+ */
+-#define DRIVER_VERSION "v0.3"
++#define DRIVER_VERSION "v0.4"
+ #define DRIVER_AUTHOR "Roelf Diedericks"
+ #define DRIVER_DESC "IPWireless tty driver"
+
+@@ -65,8 +64,6 @@
+ /* Message sizes */
+ #define EVENT_BUFFER_SIZE 0xFF
+ #define CHAR2INT16(c1, c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
+-#define NUM_BULK_URBS 24
+-#define NUM_CONTROL_URBS 16
+
+ /* vendor/product pairs that are known work with this driver*/
+ #define IPW_VID 0x0bc3
+@@ -151,47 +148,6 @@ static struct usb_driver usb_ipw_driver
+
+ static int debug;
+
+-static void ipw_read_bulk_callback(struct urb *urb)
+-{
+- struct usb_serial_port *port = urb->context;
+- unsigned char *data = urb->transfer_buffer;
+- struct tty_struct *tty;
+- int result;
+- int status = urb->status;
+-
+- dbg("%s - port %d", __func__, port->number);
+-
+- if (status) {
+- dbg("%s - nonzero read bulk status received: %d",
+- __func__, status);
+- return;
+- }
+-
+- usb_serial_debug_data(debug, &port->dev, __func__,
+- urb->actual_length, data);
+-
+- tty = tty_port_tty_get(&port->port);
+- if (tty && urb->actual_length) {
+- tty_insert_flip_string(tty, data, urb->actual_length);
+- tty_flip_buffer_push(tty);
+- }
+- tty_kref_put(tty);
+-
+- /* Continue trying to always read */
+- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- ipw_read_bulk_callback, port);
+- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+- if (result)
+- dev_err(&port->dev,
+- "%s - failed resubmitting read urb, error %d\n",
+- __func__, result);
+- return;
+-}
+-
+ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+ struct usb_device *dev = port->serial->dev;
+@@ -229,15 +185,7 @@ static int ipw_open(struct tty_struct *t
+
+ /*--2: Start reading from the device */
+ dbg("%s: setting up bulk read callback", __func__);
+- usb_fill_bulk_urb(port->read_urb, dev,
+- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+- port->bulk_in_buffer,
+- port->bulk_in_size,
+- ipw_read_bulk_callback, port);
+- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+- if (result < 0)
+- dbg("%s - usb_submit_urb(read bulk) failed with status %d",
+- __func__, result);
++ usb_serial_generic_open(tty, port);
+
+ /*--3: Tell the modem to open the floodgates on the rx bulk channel */
+ dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__);
+@@ -337,72 +285,7 @@ static void ipw_close(struct usb_serial_
+ dev_err(&port->dev,
+ "Disabling bulk RxRead failed (error = %d)\n", result);
+
+- /* shutdown any in-flight urbs that we know about */
+- usb_kill_urb(port->read_urb);
+- usb_kill_urb(port->write_urb);
+-}
+-
+-static void ipw_write_bulk_callback(struct urb *urb)
+-{
+- struct usb_serial_port *port = urb->context;
+- int status = urb->status;
+-
+- dbg("%s", __func__);
+-
+- port->write_urb_busy = 0;
+-
+- if (status)
+- dbg("%s - nonzero write bulk status received: %d",
+- __func__, status);
+-
+- usb_serial_port_softint(port);
+-}
+-
+-static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count)
+-{
+- struct usb_device *dev = port->serial->dev;
+- int ret;
+-
+- dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
+- count, in_interrupt());
+-
+- if (count == 0) {
+- dbg("%s - write request of 0 bytes", __func__);
+- return 0;
+- }
+-
+- spin_lock_bh(&port->lock);
+- if (port->write_urb_busy) {
+- spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __func__);
+- return 0;
+- }
+- port->write_urb_busy = 1;
+- spin_unlock_bh(&port->lock);
+-
+- count = min(count, port->bulk_out_size);
+- memcpy(port->bulk_out_buffer, buf, count);
+-
+- dbg("%s count now:%d", __func__, count);
+-
+- usb_fill_bulk_urb(port->write_urb, dev,
+- usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
+- port->write_urb->transfer_buffer,
+- count,
+- ipw_write_bulk_callback,
+- port);
+-
+- ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+- if (ret != 0) {
+- port->write_urb_busy = 0;
+- dbg("%s - usb_submit_urb(write bulk) failed with error = %d",
+- __func__, ret);
+- return ret;
+- }
+-
+- dbg("%s returning %d", __func__, count);
+- return count;
++ usb_serial_generic_close(port);
+ }
+
+ static struct usb_serial_driver ipw_device = {
+@@ -411,15 +294,12 @@ static struct usb_serial_driver ipw_devi
+ .name = "ipw",
+ },
+ .description = "IPWireless converter",
+- .usb_driver = &usb_ipw_driver,
++ .usb_driver = &usb_ipw_driver,
+ .id_table = usb_ipw_ids,
+ .num_ports = 1,
+ .open = ipw_open,
+ .close = ipw_close,
+ .dtr_rts = ipw_dtr_rts,
+- .write = ipw_write,
+- .write_bulk_callback = ipw_write_bulk_callback,
+- .read_bulk_callback = ipw_read_bulk_callback,
+ };
+
+
diff --git a/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch b/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch
new file mode 100644
index 00000000000000..704c6ae63d0f15
--- /dev/null
+++ b/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch
@@ -0,0 +1,46 @@
+From jhovold@gmail.com Fri May 14 12:14:59 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:33:09 +0200
+Subject: USB: ipw: remove dummy port_probe and port_remove
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273779190-8652-3-git-send-email-jhovold@gmail.com>
+
+
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ipw.c | 13 -------------
+ 1 file changed, 13 deletions(-)
+
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -405,17 +405,6 @@ static int ipw_write(struct tty_struct *
+ return count;
+ }
+
+-static int ipw_probe(struct usb_serial_port *port)
+-{
+- return 0;
+-}
+-
+-static int ipw_disconnect(struct usb_serial_port *port)
+-{
+- usb_set_serial_port_data(port, NULL);
+- return 0;
+-}
+-
+ static struct usb_serial_driver ipw_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+@@ -428,8 +417,6 @@ static struct usb_serial_driver ipw_devi
+ .open = ipw_open,
+ .close = ipw_close,
+ .dtr_rts = ipw_dtr_rts,
+- .port_probe = ipw_probe,
+- .port_remove = ipw_disconnect,
+ .write = ipw_write,
+ .write_bulk_callback = ipw_write_bulk_callback,
+ .read_bulk_callback = ipw_read_bulk_callback,
diff --git a/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch b/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch
new file mode 100644
index 00000000000000..4be66aee3c3846
--- /dev/null
+++ b/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch
@@ -0,0 +1,70 @@
+From jhovold@gmail.com Fri May 14 12:13:44 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:02:01 +0200
+Subject: USB: ir-usb: allow custom bulk buffer size without reallocation
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273777323-32136-3-git-send-email-jhovold@gmail.com>
+
+
+Use usb_serial_driver bulk_in_size and bulk_out_size to make sure
+buffers of appropriate sizes are allocated in the first place rather than
+reallocating them at every open.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ir-usb.c | 30 +++++-------------------------
+ 1 file changed, 5 insertions(+), 25 deletions(-)
+
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -297,35 +297,10 @@ static int ir_startup(struct usb_serial
+
+ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+- char *buffer;
+ int result = 0;
+
+ dbg("%s - port %d", __func__, port->number);
+
+- if (buffer_size) {
+- /* override the default buffer sizes */
+- buffer = kmalloc(buffer_size, GFP_KERNEL);
+- if (!buffer) {
+- dev_err(&port->dev, "%s - out of memory.\n", __func__);
+- return -ENOMEM;
+- }
+- kfree(port->read_urb->transfer_buffer);
+- port->read_urb->transfer_buffer = buffer;
+- port->read_urb->transfer_buffer_length = buffer_size;
+- port->bulk_in_buffer = buffer;
+-
+- buffer = kmalloc(buffer_size, GFP_KERNEL);
+- if (!buffer) {
+- dev_err(&port->dev, "%s - out of memory.\n", __func__);
+- return -ENOMEM;
+- }
+- kfree(port->write_urb->transfer_buffer);
+- port->write_urb->transfer_buffer = buffer;
+- port->write_urb->transfer_buffer_length = buffer_size;
+- port->bulk_out_buffer = buffer;
+- port->bulk_out_size = buffer_size;
+- }
+-
+ /* Start reading from the device */
+ usb_fill_bulk_urb(
+ port->read_urb,
+@@ -585,6 +560,11 @@ static int __init ir_init(void)
+ {
+ int retval;
+
++ if (buffer_size) {
++ ir_device.bulk_in_size = buffer_size;
++ ir_device.bulk_out_size = buffer_size;
++ }
++
+ retval = usb_serial_register(&ir_device);
+ if (retval)
+ goto failed_usb_serial_register;
diff --git a/usb/usb-ir-usb-fix-double-free.patch b/usb/usb-ir-usb-fix-double-free.patch
new file mode 100644
index 00000000000000..35a1db88587b6a
--- /dev/null
+++ b/usb/usb-ir-usb-fix-double-free.patch
@@ -0,0 +1,38 @@
+From jhovold@gmail.com Fri May 14 12:13:32 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:02:00 +0200
+Subject: USB: ir-usb: fix double free
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>, stable <stable@kernel.org>
+Message-ID: <1273777323-32136-2-git-send-email-jhovold@gmail.com>
+
+
+If the user specifies a custom bulk buffer size we get a double free at
+port release.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ir-usb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -312,6 +312,7 @@ static int ir_open(struct tty_struct *tt
+ kfree(port->read_urb->transfer_buffer);
+ port->read_urb->transfer_buffer = buffer;
+ port->read_urb->transfer_buffer_length = buffer_size;
++ port->bulk_in_buffer = buffer;
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+@@ -321,6 +322,7 @@ static int ir_open(struct tty_struct *tt
+ kfree(port->write_urb->transfer_buffer);
+ port->write_urb->transfer_buffer = buffer;
+ port->write_urb->transfer_buffer_length = buffer_size;
++ port->bulk_out_buffer = buffer;
+ port->bulk_out_size = buffer_size;
+ }
+
diff --git a/usb/usb-ir-usb-fix-set_termios-race.patch b/usb/usb-ir-usb-fix-set_termios-race.patch
new file mode 100644
index 00000000000000..672dc765a6b166
--- /dev/null
+++ b/usb/usb-ir-usb-fix-set_termios-race.patch
@@ -0,0 +1,117 @@
+From jhovold@gmail.com Fri May 14 12:14:20 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:02:02 +0200
+Subject: USB: ir-usb: fix set_termios race
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273777323-32136-4-git-send-email-jhovold@gmail.com>
+
+
+Use dynamically allocated urb for baudrate changes rather than
+unconditionally submitting the port write urb which may already be in
+use.
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ir-usb.c | 63 ++++++++++++++++++++++++++++++++------------
+ 1 file changed, 47 insertions(+), 16 deletions(-)
+
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -469,9 +469,23 @@ static void ir_read_bulk_callback(struct
+ return;
+ }
+
++static void ir_set_termios_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = urb->context;
++ int status = urb->status;
++
++ dbg("%s - port %d", __func__, port->number);
++
++ kfree(urb->transfer_buffer);
++
++ if (status)
++ dbg("%s - non-zero urb status: %d", __func__, status);
++}
++
+ static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+ {
++ struct urb *urb;
+ unsigned char *transfer_buffer;
+ int result;
+ speed_t baud;
+@@ -525,35 +539,52 @@ static void ir_set_termios(struct tty_st
+ else
+ ir_xbof = ir_xbof_change(xbof) ;
+
+- /* FIXME need to check to see if our write urb is busy right
+- * now, or use a urb pool.
+- *
++ /* Only speed changes are supported */
++ tty_termios_copy_hw(tty->termios, old_termios);
++ tty_encode_baud_rate(tty, baud, baud);
++
++ /*
+ * send the baud change out on an "empty" data packet
+ */
+- transfer_buffer = port->write_urb->transfer_buffer;
++ urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!urb) {
++ dev_err(&port->dev, "%s - no more urbs\n", __func__);
++ return;
++ }
++ transfer_buffer = kmalloc(1, GFP_KERNEL);
++ if (!transfer_buffer) {
++ dev_err(&port->dev, "%s - out of memory\n", __func__);
++ goto err_buf;
++ }
++
+ *transfer_buffer = ir_xbof | ir_baud;
+
+ usb_fill_bulk_urb(
+- port->write_urb,
++ urb,
+ port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+- port->write_urb->transfer_buffer,
++ transfer_buffer,
+ 1,
+- ir_write_bulk_callback,
++ ir_set_termios_callback,
+ port);
+
+- port->write_urb->transfer_flags = URB_ZERO_PACKET;
++ urb->transfer_flags = URB_ZERO_PACKET;
++
++ result = usb_submit_urb(urb, GFP_KERNEL);
++ if (result) {
++ dev_err(&port->dev, "%s - failed to submit urb: %d\n",
++ __func__, result);
++ goto err_subm;
++ }
+
+- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+- if (result)
+- dev_err(&port->dev,
+- "%s - failed submitting write urb, error %d\n",
+- __func__, result);
++ usb_free_urb(urb);
+
+- /* Only speed changes are supported */
+- tty_termios_copy_hw(tty->termios, old_termios);
+- tty_encode_baud_rate(tty, baud, baud);
++ return;
++err_subm:
++ kfree(transfer_buffer);
++err_buf:
++ usb_free_urb(urb);
+ }
+
+ static int __init ir_init(void)
diff --git a/usb/usb-ir-usb-reimplement-using-generic-framework.patch b/usb/usb-ir-usb-reimplement-using-generic-framework.patch
new file mode 100644
index 00000000000000..ee40a8bc2d3916
--- /dev/null
+++ b/usb/usb-ir-usb-reimplement-using-generic-framework.patch
@@ -0,0 +1,289 @@
+From jhovold@gmail.com Fri May 14 12:14:33 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Thu, 13 May 2010 21:02:03 +0200
+Subject: USB: ir-usb: reimplement using generic framework
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1273777323-32136-5-git-send-email-jhovold@gmail.com>
+
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ir-usb.c | 197 ++++++++------------------------------------
+ 1 file changed, 38 insertions(+), 159 deletions(-)
+
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -3,6 +3,7 @@
+ *
+ * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com)
++ * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -72,8 +73,8 @@
+ /*
+ * Version Information
+ */
+-#define DRIVER_VERSION "v0.4"
+-#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
++#define DRIVER_VERSION "v0.5"
++#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>"
+ #define DRIVER_DESC "USB IR Dongle driver"
+
+ static int debug;
+@@ -87,11 +88,9 @@ static int xbof = -1;
+
+ static int ir_startup (struct usb_serial *serial);
+ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port);
+-static void ir_close(struct usb_serial_port *port);
+-static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count);
+-static void ir_write_bulk_callback (struct urb *urb);
+-static void ir_read_bulk_callback (struct urb *urb);
++static int ir_prepare_write_buffer(struct usb_serial_port *port,
++ void *dest, size_t size);
++static void ir_process_read_urb(struct urb *urb);
+ static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+
+@@ -130,10 +129,8 @@ static struct usb_serial_driver ir_devic
+ .set_termios = ir_set_termios,
+ .attach = ir_startup,
+ .open = ir_open,
+- .close = ir_close,
+- .write = ir_write,
+- .write_bulk_callback = ir_write_bulk_callback,
+- .read_bulk_callback = ir_read_bulk_callback,
++ .prepare_write_buffer = ir_prepare_write_buffer,
++ .process_read_urb = ir_process_read_urb,
+ };
+
+ static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
+@@ -198,7 +195,6 @@ error:
+ return NULL;
+ }
+
+-
+ static u8 ir_xbof_change(u8 xbof)
+ {
+ u8 result;
+@@ -237,7 +233,6 @@ static u8 ir_xbof_change(u8 xbof)
+ return(result);
+ }
+
+-
+ static int ir_startup(struct usb_serial *serial)
+ {
+ struct usb_irda_cs_descriptor *irda_desc;
+@@ -297,60 +292,21 @@ static int ir_startup(struct usb_serial
+
+ static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+- int result = 0;
++ int i;
+
+ dbg("%s - port %d", __func__, port->number);
+
+- /* Start reading from the device */
+- usb_fill_bulk_urb(
+- port->read_urb,
+- port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- ir_read_bulk_callback,
+- port);
+- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+- if (result)
+- dev_err(&port->dev,
+- "%s - failed submitting read urb, error %d\n",
+- __func__, result);
++ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
++ port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
+
+- return result;
++ /* Start reading from the device */
++ return usb_serial_generic_open(tty, port);
+ }
+
+-static void ir_close(struct usb_serial_port *port)
++static int ir_prepare_write_buffer(struct usb_serial_port *port,
++ void *dest, size_t size)
+ {
+- dbg("%s - port %d", __func__, port->number);
+-
+- /* shutdown our bulk read */
+- usb_kill_urb(port->read_urb);
+-}
+-
+-static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count)
+-{
+- unsigned char *transfer_buffer;
+- int result;
+- int transfer_size;
+-
+- dbg("%s - port = %d, count = %d", __func__, port->number, count);
+-
+- if (count == 0)
+- return 0;
+-
+- spin_lock_bh(&port->lock);
+- if (port->write_urb_busy) {
+- spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __func__);
+- return 0;
+- }
+- port->write_urb_busy = 1;
+- spin_unlock_bh(&port->lock);
+-
+- transfer_buffer = port->write_urb->transfer_buffer;
+- transfer_size = min(count, port->bulk_out_size - 1);
++ unsigned char *buf = dest;
+
+ /*
+ * The first byte of the packet we send to the device contains an
+@@ -359,114 +315,37 @@ static int ir_write(struct tty_struct *t
+ *
+ * See section 5.4.2.2 of the USB IrDA spec.
+ */
+- *transfer_buffer = ir_xbof | ir_baud;
+- ++transfer_buffer;
+-
+- memcpy(transfer_buffer, buf, transfer_size);
+-
+- usb_fill_bulk_urb(
+- port->write_urb,
+- port->serial->dev,
+- usb_sndbulkpipe(port->serial->dev,
+- port->bulk_out_endpointAddress),
+- port->write_urb->transfer_buffer,
+- transfer_size + 1,
+- ir_write_bulk_callback,
+- port);
+-
+- port->write_urb->transfer_flags = URB_ZERO_PACKET;
+-
+- result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+- if (result) {
+- port->write_urb_busy = 0;
+- dev_err(&port->dev,
+- "%s - failed submitting write urb, error %d\n",
+- __func__, result);
+- } else
+- result = transfer_size;
++ *buf = ir_xbof | ir_baud;
+
+- return result;
++ return kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
++ &port->lock);
+ }
+
+-static void ir_write_bulk_callback(struct urb *urb)
++static void ir_process_read_urb(struct urb *urb)
+ {
+ struct usb_serial_port *port = urb->context;
+- int status = urb->status;
+-
+- dbg("%s - port %d", __func__, port->number);
++ unsigned char *data = urb->transfer_buffer;
++ struct tty_struct *tty;
+
+- port->write_urb_busy = 0;
+- if (status) {
+- dbg("%s - nonzero write bulk status received: %d",
+- __func__, status);
++ if (!urb->actual_length)
+ return;
+- }
+-
+- usb_serial_debug_data(
+- debug,
+- &port->dev,
+- __func__,
+- urb->actual_length,
+- urb->transfer_buffer);
+-
+- usb_serial_port_softint(port);
+-}
+-
+-static void ir_read_bulk_callback(struct urb *urb)
+-{
+- struct usb_serial_port *port = urb->context;
+- struct tty_struct *tty;
+- unsigned char *data = urb->transfer_buffer;
+- int result;
+- int status = urb->status;
++ /*
++ * The first byte of the packet we get from the device
++ * contains a busy indicator and baud rate change.
++ * See section 5.4.1.2 of the USB IrDA spec.
++ */
++ if (*data & 0x0f)
++ ir_baud = *data & 0x0f;
+
+- dbg("%s - port %d", __func__, port->number);
++ if (urb->actual_length == 1)
++ return;
+
+- switch (status) {
+- case 0: /* Successful */
+- /*
+- * The first byte of the packet we get from the device
+- * contains a busy indicator and baud rate change.
+- * See section 5.4.1.2 of the USB IrDA spec.
+- */
+- if ((*data & 0x0f) > 0)
+- ir_baud = *data & 0x0f;
+- usb_serial_debug_data(debug, &port->dev, __func__,
+- urb->actual_length, data);
+- tty = tty_port_tty_get(&port->port);
+- tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+- tty_flip_buffer_push(tty);
+- tty_kref_put(tty);
+-
+- /*
+- * No break here.
+- * We want to resubmit the urb so we can read
+- * again.
+- */
+-
+- case -EPROTO: /* taking inspiration from pl2303.c */
+- /* Continue trying to always read */
+- usb_fill_bulk_urb(
+- port->read_urb,
+- port->serial->dev,
+- usb_rcvbulkpipe(port->serial->dev,
+- port->bulk_in_endpointAddress),
+- port->read_urb->transfer_buffer,
+- port->read_urb->transfer_buffer_length,
+- ir_read_bulk_callback,
+- port);
+-
+- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+- if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+- __func__, result);
+- break ;
+- default:
+- dbg("%s - nonzero read bulk status received: %d",
+- __func__, status);
+- break ;
+- }
+- return;
++ tty = tty_port_tty_get(&port->port);
++ if (!tty)
++ return;
++ tty_insert_flip_string(tty, data + 1, urb->actual_length - 1);
++ tty_flip_buffer_push(tty);
++ tty_kref_put(tty);
+ }
+
+ static void ir_set_termios_callback(struct urb *urb)
diff --git a/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch b/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch
index 0bce486dbc5af5..6f043bdc7d0313 100644
--- a/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch
+++ b/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch
@@ -16,7 +16,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
-@@ -1373,18 +1373,6 @@ void *usb_alloc_coherent(struct usb_devi
+@@ -1372,18 +1372,6 @@ void *usb_alloc_coherent(struct usb_devi
void usb_free_coherent(struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
diff --git a/usb/usb-remove-usb_find_device.patch b/usb/usb-remove-usb_find_device.patch
new file mode 100644
index 00000000000000..4a36c165479885
--- /dev/null
+++ b/usb/usb-remove-usb_find_device.patch
@@ -0,0 +1,89 @@
+From tom.leiming@gmail.com Fri May 14 12:03:50 2010
+From: tom.leiming@gmail.com
+Date: Wed, 12 May 2010 23:38:46 +0800
+Subject: USB: remove usb_find_device
+To: greg@kroah.com, stern@rowland.harvard.edu
+Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com>
+Message-ID: <1273678726-19664-1-git-send-email-tom.leiming@gmail.com>
+
+
+From: Ming Lei <tom.leiming@gmail.com>
+
+Now on one uses this function and it seems useless,
+so remove usb_find_device.
+
+[tom@tom linux-2.6-next]$ grep -r -n -I usb_find_device ./
+drivers/media/dvb/dvb-usb/dvb-usb-init.c:160:static struct
+dvb_usb_device_description * dvb_usb_find_device(struct usb_device
+*udev,struct dvb_usb_device_properties *props, int *cold)
+
+drivers/media/dvb/dvb-usb/dvb-usb-init.c:230: if ((desc =
+dvb_usb_find_device(udev,props,&cold)) == NULL) {
+
+drivers/usb/core/usb.c:630: * usb_find_device - find a specific usb device in the system
+drivers/usb/core/usb.c:642:struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
+
+Signed-off-by: Ming Lei <tom.leiming@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/usb.c | 37 -------------------------------------
+ include/linux/usb.h | 1 -
+ 2 files changed, 38 deletions(-)
+
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -627,43 +627,6 @@ exit:
+ }
+
+ /**
+- * usb_find_device - find a specific usb device in the system
+- * @vendor_id: the vendor id of the device to find
+- * @product_id: the product id of the device to find
+- *
+- * Returns a pointer to a struct usb_device if such a specified usb
+- * device is present in the system currently. The usage count of the
+- * device will be incremented if a device is found. Make sure to call
+- * usb_put_dev() when the caller is finished with the device.
+- *
+- * If a device with the specified vendor and product id is not found,
+- * NULL is returned.
+- */
+-struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
+-{
+- struct list_head *buslist;
+- struct usb_bus *bus;
+- struct usb_device *dev = NULL;
+-
+- mutex_lock(&usb_bus_list_lock);
+- for (buslist = usb_bus_list.next;
+- buslist != &usb_bus_list;
+- buslist = buslist->next) {
+- bus = container_of(buslist, struct usb_bus, bus_list);
+- if (!bus->root_hub)
+- continue;
+- usb_lock_device(bus->root_hub);
+- dev = match_device(bus->root_hub, vendor_id, product_id);
+- usb_unlock_device(bus->root_hub);
+- if (dev)
+- goto exit;
+- }
+-exit:
+- mutex_unlock(&usb_bus_list_lock);
+- return dev;
+-}
+-
+-/**
+ * usb_get_current_frame_number - return current bus frame number
+ * @dev: the device whose bus is being queried
+ *
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -510,7 +510,6 @@ extern int usb_lock_device_for_reset(str
+ extern int usb_reset_device(struct usb_device *dev);
+ extern void usb_queue_reset_device(struct usb_interface *dev);
+
+-extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
diff --git a/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch b/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch
new file mode 100644
index 00000000000000..3a413909bfc695
--- /dev/null
+++ b/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch
@@ -0,0 +1,58 @@
+From wgulland@vmware.com Fri May 14 12:05:05 2010
+From: William Gulland <wgulland@vmware.com>
+Date: Wed, 12 May 2010 10:20:34 -0700
+Subject: USB: xhci: Remove the arbitrary limit of 15 xHCI ports
+To: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Message-ID: <1273684834.11403.7.camel@wgulland-ubuntu>
+
+
+Our virtual xHCI device can have as many ports as we like - I've tested
+this patch with 31.
+
+Signed-off-by: William Gulland <wgulland@vmware.com>
+Cc: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hub.c | 15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -298,7 +298,6 @@ error:
+ * Returns 0 if the status hasn't changed, or the number of bytes in buf.
+ * Ports are 0-indexed from the HCD point of view,
+ * and 1-indexed from the USB core pointer of view.
+- * xHCI instances can have up to 127 ports, so FIXME if you see more than 15.
+ *
+ * Note that the status change bits will be cleared as soon as a port status
+ * change event is generated, so we use the saved status from that event.
+@@ -315,14 +314,9 @@ int xhci_hub_status_data(struct usb_hcd
+ ports = HCS_MAX_PORTS(xhci->hcs_params1);
+
+ /* Initial status is no changes */
+- buf[0] = 0;
++ retval = (ports + 8) / 8;
++ memset(buf, 0, retval);
+ status = 0;
+- if (ports > 7) {
+- buf[1] = 0;
+- retval = 2;
+- } else {
+- retval = 1;
+- }
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ /* For each port, did anything change? If so, set that bit in buf. */
+@@ -331,10 +325,7 @@ int xhci_hub_status_data(struct usb_hcd
+ NUM_PORT_REGS*i;
+ temp = xhci_readl(xhci, addr);
+ if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) {
+- if (i < 7)
+- buf[0] |= 1 << (i + 1);
+- else
+- buf[1] |= 1 << (i - 7);
++ buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
+ status = 1;
+ }
+ }