aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-01-27 10:21:23 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-27 10:21:23 -0800
commitafba9fdd0bc76de323628ad9a25b20310d05031c (patch)
tree8b961788bf41178f29ca8519839447cf2ef835d4 /usb
parent1bb63250ce140bce4ce684ec6b733e4af723d803 (diff)
downloadpatches-afba9fdd0bc76de323628ad9a25b20310d05031c.tar.gz
more usb and pci patches
Diffstat (limited to 'usb')
-rw-r--r--usb/recognize-three-more-usb-peripheral-controllers.patch106
-rw-r--r--usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch32
-rw-r--r--usb/usb-ohci-uses-driver-model-wakeup-flags.patch228
-rw-r--r--usb/usb-remove-usbcore-specific-wakeup-flags.patch181
-rw-r--r--usb/usb-usbcore-sets-up-root-hubs-earlier.patch198
5 files changed, 745 insertions, 0 deletions
diff --git a/usb/recognize-three-more-usb-peripheral-controllers.patch b/usb/recognize-three-more-usb-peripheral-controllers.patch
new file mode 100644
index 00000000000000..118bfd93273c39
--- /dev/null
+++ b/usb/recognize-three-more-usb-peripheral-controllers.patch
@@ -0,0 +1,106 @@
+From david-b@pacbell.net Wed Jan 25 08:57:17 2006
+From: David Brownell <david-b@pacbell.net>
+To: Greg KH <greg@kroah.com>
+Subject: [patch 2.6.16-rc1] recognize three more usb peripheral controllers
+Date: Wed, 25 Jan 2006 08:45:59 -0800
+Cc: "Kamat, Nishant" <nskamat@ti.com>, Kevin Hilman <khilman@mvista.com>, Tony Lindgren <tony@atomide.com>
+Message-Id: <200601250845.59331.david-b@pacbell.net>
+
+This adds declarations for three USB peripheral controllers:
+
+ - Two high speed USB cores that can be licensed from Mentor Graphics
+ to be integrated into silicon:
+
+ * "musbhsfc" is for peripherals only, as found in for example the
+ IBM/AMCC 44EP processors.
+
+ * "musbhdrc" is OTG-capable (dual role), and is found in various
+ products including OMAP 2430 and the new DaVinci SOCs.
+
+ The "musbh" standing for "Mentor USB Highspeed", the rest standing
+ for "Function Controller" or "Dual Role Controller" (OTG-capable).
+
+ - The full speed controller on the FreeScale MPC8272.
+
+Adding these definitions just allows gadget driver code to handle any
+controller-specific logic; controller drivers are quite separate.
+
+
+Signed-off-by: David Brownell <david-b@pacbell.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/ether.c | 8 ++++++++
+ drivers/usb/gadget/gadget_chips.h | 30 ++++++++++++++++++++++++++++--
+ 2 files changed, 36 insertions(+), 2 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/gadget/gadget_chips.h
++++ gregkh-2.6/drivers/usb/gadget/gadget_chips.h
+@@ -3,9 +3,9 @@
+ * gadget drivers or other code that needs to deal with them, and which
+ * autoconfigures instead of using early binding to the hardware.
+ *
+- * This could eventually work like the ARM mach_is_*() stuff, driven by
++ * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
+ * some config file that gets updated as new hardware is supported.
+- * (And avoiding the runtime comparisons in typical one-choice cases.)
++ * (And avoiding all runtime comparisons in typical one-choice configs!)
+ *
+ * NOTE: some of these controller drivers may not be available yet.
+ */
+@@ -93,6 +93,26 @@
+ #define gadget_is_imx(g) 0
+ #endif
+
++/* Mentor high speed function controller */
++#ifdef CONFIG_USB_GADGET_MUSBHSFC
++#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
++#else
++#define gadget_is_musbhsfc(g) 0
++#endif
++
++/* Mentor high speed "dual role" controller, peripheral mode */
++#ifdef CONFIG_USB_GADGET_MUSBHDRC
++#define gadget_is_musbhdrc(g) !strcmp("musbhdrc_udc", (g)->name)
++#else
++#define gadget_is_musbhdrc(g) 0
++#endif
++
++#ifdef CONFIG_USB_GADGET_MPC8272
++#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name)
++#else
++#define gadget_is_mpc8272(g) 0
++#endif
++
+ // CONFIG_USB_GADGET_SX2
+ // CONFIG_USB_GADGET_AU1X00
+ // ...
+@@ -143,5 +163,11 @@ static inline int usb_gadget_controller_
+ return 0x13;
+ else if (gadget_is_imx(gadget))
+ return 0x14;
++ else if (gadget_is_musbhsfc(gadget))
++ return 0x15;
++ else if (gadget_is_musbhdrc(gadget))
++ return 0x16;
++ else if (gadget_is_mpc8272(gadget))
++ return 0x17;
+ return -ENOENT;
+ }
+--- gregkh-2.6.orig/drivers/usb/gadget/ether.c
++++ gregkh-2.6/drivers/usb/gadget/ether.c
+@@ -253,6 +253,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethern
+ #define DEV_CONFIG_CDC
+ #endif
+
++#ifdef CONFIG_USB_GADGET_MUSBHSFC
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_MUSBHDRC
++#define DEV_CONFIG_CDC
++#endif
++
+
+ /* For CDC-incapable hardware, choose the simple cdc subset.
+ * Anything that talks bulk (without notable bugs) can do this.
diff --git a/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch b/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch
new file mode 100644
index 00000000000000..39e777d5c9bded
--- /dev/null
+++ b/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch
@@ -0,0 +1,32 @@
+From linux-usb-devel-admin@lists.sourceforge.net Tue Jan 24 08:41:21 2006
+From: Kumar Gala <galak@kernel.crashing.org>
+To: linux-usb-devel@lists.sourceforge.net
+Subject: USB: Fix masking bug initialization of Freescale EHCI controller
+Cc: Kumar Gala <galak@gate.crashing.org>, dbrownell@users.sourceforge.net, Randy Vinson <rvinson@mvista.com>
+Content-Disposition: inline
+Message-Id: <200601240811.27539.david-b@pacbell.net>
+Date: Tue, 24 Jan 2006 08:11:27 -0800
+
+In setting up the of PHY we masked off too many bits, instead just
+initialize PORTSC for the type of PHY we are using.
+
+Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
+Acked-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-fsl.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/host/ehci-fsl.c
++++ gregkh-2.6/drivers/usb/host/ehci-fsl.c
+@@ -160,8 +160,7 @@ static void mpc83xx_setup_phy(struct ehc
+ enum fsl_usb2_phy_modes phy_mode,
+ unsigned int port_offset)
+ {
+- u32 portsc = readl(&ehci->regs->port_status[port_offset]);
+- portsc &= ~PORT_PTS_MSK;
++ u32 portsc = 0;
+ switch (phy_mode) {
+ case FSL_USB2_PHY_ULPI:
+ portsc |= PORT_PTS_ULPI;
diff --git a/usb/usb-ohci-uses-driver-model-wakeup-flags.patch b/usb/usb-ohci-uses-driver-model-wakeup-flags.patch
new file mode 100644
index 00000000000000..19c597db48d6f1
--- /dev/null
+++ b/usb/usb-ohci-uses-driver-model-wakeup-flags.patch
@@ -0,0 +1,228 @@
+From david-b@pacbell.net Mon Jan 23 16:29:40 2006
+From: David Brownell <david-b@pacbell.net>
+To: Greg KH <greg@kroah.com>
+Subject: USB: ohci uses driver model wakeup flags
+Date: Mon, 23 Jan 2006 15:28:07 -0800
+Content-Disposition: inline
+Message-Id: <200601231528.07476.david-b@pacbell.net>
+
+This makes OHCI use the driver model wakeup control bits for its root hub
+(e.g. disable on amd756, because of chip erratum) and for the controller
+itself. It no longer uses the hcd glue bits with those roles, and depends
+on the previous patch making the root hub available earlier.
+
+Note that on most platforms (boot code properly setting the RWC bit) this
+gives a partial workaround for the way PCI isn't currently flagging devices
+that support PME# signals. (Because of odd PCI init sequencing on PPC.)
+That's because many OHCI controllers support "legacy PCI PM" ... without
+involving any PCI PM capability.
+
+USB wakeup from STR, if it works on your system, may still involve
+tweaking things by hand in /proc/acpi/wakeup.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ohci-hcd.c | 49 ++++++++++++++++++++++++--------------------
+ drivers/usb/host/ohci-hub.c | 12 +++++-----
+ drivers/usb/host/ohci-pci.c | 15 +++++++++++--
+ 3 files changed, 46 insertions(+), 30 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c
++++ gregkh-2.6/drivers/usb/host/ohci-hcd.c
+@@ -443,11 +443,16 @@ ohci_reboot (struct notifier_block *bloc
+ static int ohci_init (struct ohci_hcd *ohci)
+ {
+ int ret;
++ struct usb_hcd *hcd = ohci_to_hcd(ohci);
+
+ disable (ohci);
+- ohci->regs = ohci_to_hcd(ohci)->regs;
++ ohci->regs = hcd->regs;
+ ohci->next_statechange = jiffies;
+
++ /* REVISIT this BIOS handshake is now moved into PCI "quirks", and
++ * was never needed for most non-PCI systems ... remove the code?
++ */
++
+ #ifndef IR_DISABLE
+ /* SMM owns the HC? not for long! */
+ if (!no_handshake && ohci_readl (ohci,
+@@ -478,8 +483,10 @@ static int ohci_init (struct ohci_hcd *o
+
+ /* Disable HC interrupts */
+ ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+- // flush the writes
+- (void) ohci_readl (ohci, &ohci->regs->control);
++
++ /* flush the writes, and save key bits like RWC */
++ if (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_RWC)
++ ohci->hc_control |= OHCI_CTRL_RWC;
+
+ /* Read the number of ports unless overridden */
+ if (ohci->num_ports == 0)
+@@ -488,16 +495,19 @@ static int ohci_init (struct ohci_hcd *o
+ if (ohci->hcca)
+ return 0;
+
+- ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller,
++ ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+ sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+ if (!ohci->hcca)
+ return -ENOMEM;
+
+ if ((ret = ohci_mem_init (ohci)) < 0)
+- ohci_stop (ohci_to_hcd(ohci));
++ ohci_stop (hcd);
++ else {
++ register_reboot_notifier (&ohci->reboot_notifier);
++ create_debug_files (ohci);
++ }
+
+ return ret;
+-
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -510,6 +520,7 @@ static int ohci_run (struct ohci_hcd *oh
+ {
+ u32 mask, temp;
+ int first = ohci->fminterval == 0;
++ struct usb_hcd *hcd = ohci_to_hcd(ohci);
+
+ disable (ohci);
+
+@@ -525,18 +536,17 @@ static int ohci_run (struct ohci_hcd *oh
+ /* also: power/overcurrent flags in roothub.a */
+ }
+
+- /* Reset USB nearly "by the book". RemoteWakeupConnected
+- * saved if boot firmware (BIOS/SMM/...) told us it's connected
+- * (for OHCI integrated on mainboard, it normally is)
++ /* Reset USB nearly "by the book". RemoteWakeupConnected was
++ * saved if boot firmware (BIOS/SMM/...) told us it's connected,
++ * or if bus glue did the same (e.g. for PCI add-in cards with
++ * PCI PM support).
+ */
+- ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
+ ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
+- ohci->hc_control);
+-
+- if (ohci->hc_control & OHCI_CTRL_RWC
+- && !(ohci->flags & OHCI_QUIRK_AMD756))
+- ohci_to_hcd(ohci)->can_wakeup = 1;
++ ohci_readl (ohci, &ohci->regs->control));
++ if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
++ && !device_may_wakeup(hcd->self.controller))
++ device_init_wakeup(hcd->self.controller, 1);
+
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ case OHCI_USB_OPER:
+@@ -632,7 +642,7 @@ retry:
+ ohci->hc_control &= OHCI_CTRL_RWC;
+ ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+- ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
++ hcd->state = HC_STATE_RUNNING;
+
+ /* wake on ConnectStatusChange, matching external hubs */
+ ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
+@@ -667,15 +677,10 @@ retry:
+
+ // POTPGT delay is bits 24-31, in 2 ms units.
+ mdelay ((temp >> 23) & 0x1fe);
+- ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
++ hcd->state = HC_STATE_RUNNING;
+
+ ohci_dump (ohci, 1);
+
+- if (ohci_to_hcd(ohci)->self.root_hub == NULL) {
+- register_reboot_notifier (&ohci->reboot_notifier);
+- create_debug_files (ohci);
+- }
+-
+ return 0;
+ }
+
+--- gregkh-2.6.orig/drivers/usb/host/ohci-pci.c
++++ gregkh-2.6/drivers/usb/host/ohci-pci.c
+@@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd)
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
+
+- if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) {
++ /* REVISIT this whole block should move to reset(), which handles
++ * all the other one-time init.
++ */
++ if (hcd->self.controller) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+ /* AMD 756, for most chips (early revs), corrupts register
+@@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd)
+ && pdev->device == 0x740c) {
+ ohci->flags = OHCI_QUIRK_AMD756;
+ ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
+- // also somewhat erratum 10 (suspend/resume issues)
++ /* also erratum 10 (suspend/resume issues) */
++ device_init_wakeup(&hcd->self.root_hub->dev, 0);
+ }
+
+ /* FIXME for some of the early AMD 760 southbridges, OHCI
+@@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd)
+ ohci_dbg (ohci,
+ "enabled Compaq ZFMicro chipset quirk\n");
+ }
++
++ /* RWC may not be set for add-in PCI cards, since boot
++ * firmware probably ignored them. This transfers PCI
++ * PM wakeup capabilities (once the PCI layer is fixed).
++ */
++ if (device_may_wakeup(&pdev->dev))
++ ohci->hc_control |= OHCI_CTRL_RWC;
+ }
+
+ /* NOTE: there may have already been a first reset, to
+--- gregkh-2.6.orig/drivers/usb/host/ohci-hub.c
++++ gregkh-2.6/drivers/usb/host/ohci-hub.c
+@@ -107,7 +107,7 @@ static int ohci_bus_suspend (struct usb_
+ &ohci->regs->intrstatus);
+
+ /* maybe resume can wake root hub */
+- if (hcd->remote_wakeup)
++ if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
+ ohci->hc_control |= OHCI_CTRL_RWE;
+ else
+ ohci->hc_control &= ~OHCI_CTRL_RWE;
+@@ -246,9 +246,9 @@ static int ohci_bus_resume (struct usb_h
+ (void) ohci_readl (ohci, &ohci->regs->control);
+ msleep (3);
+
+- temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+- if (hcd->can_wakeup)
+- temp |= OHCI_CTRL_RWC;
++ temp = ohci->hc_control;
++ temp &= OHCI_CTRL_RWC;
++ temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci->hc_control = temp;
+ ohci_writel (ohci, temp, &ohci->regs->control);
+ (void) ohci_readl (ohci, &ohci->regs->control);
+@@ -302,7 +302,7 @@ ohci_hub_status_data (struct usb_hcd *hc
+ {
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int i, changed = 0, length = 1;
+- int can_suspend = hcd->can_wakeup;
++ int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave (&ohci->lock, flags);
+@@ -354,7 +354,7 @@ ohci_hub_status_data (struct usb_hcd *hc
+ */
+ if (!(status & RH_PS_CCS))
+ continue;
+- if ((status & RH_PS_PSS) && hcd->remote_wakeup)
++ if ((status & RH_PS_PSS) && can_suspend)
+ continue;
+ can_suspend = 0;
+ }
diff --git a/usb/usb-remove-usbcore-specific-wakeup-flags.patch b/usb/usb-remove-usbcore-specific-wakeup-flags.patch
new file mode 100644
index 00000000000000..7d14440236eea5
--- /dev/null
+++ b/usb/usb-remove-usbcore-specific-wakeup-flags.patch
@@ -0,0 +1,181 @@
+From david-b@pacbell.net Tue Jan 24 08:40:38 2006
+From: David Brownell <david-b@pacbell.net>
+Subject: USB: remove usbcore-specific wakeup flags
+Date: Tue, 24 Jan 2006 08:40:27 -0800
+Cc: Alan Stern <stern@rowland.harvard.edu>, Greg KH <greg@kroah.com>
+Message-Id: <200601240840.27533.david-b@pacbell.net>
+
+
+This makes usbcore use the driver model wakeup flags for host controllers
+and for their root hubs. Since previous patches have removed all users of
+the HCD flags they replace, this converts the last users of those flags.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd-pci.c | 11 ++++++++---
+ drivers/usb/core/hcd.c | 40 ++++++++++++++++++++++++++--------------
+ drivers/usb/core/hcd.h | 2 --
+ drivers/usb/core/hub.c | 22 ++++++++++++++--------
+ 4 files changed, 48 insertions(+), 27 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/core/hcd.h
++++ gregkh-2.6/drivers/usb/core/hcd.h
+@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv point
+ #define HCD_FLAG_HW_ACCESSIBLE 0x00000001
+ #define HCD_FLAG_SAW_IRQ 0x00000002
+
+- unsigned can_wakeup:1; /* hw supports wakeup? */
+- unsigned remote_wakeup:1;/* sw should use wakeup? */
+ unsigned rh_registered:1;/* is root hub registered? */
+
+ /* The next flag is a stopgap, to be removed when all the HCDs
+--- gregkh-2.6.orig/drivers/usb/core/hcd.c
++++ gregkh-2.6/drivers/usb/core/hcd.c
+@@ -367,21 +367,39 @@ static int rh_call_control (struct usb_h
+
+ /* DEVICE REQUESTS */
+
++ /* The root hub's remote wakeup enable bit is implemented using
++ * driver model wakeup flags. If this system supports wakeup
++ * through USB, userspace may change the default "allow wakeup"
++ * policy through sysfs or these calls.
++ *
++ * Most root hubs support wakeup from downstream devices, for
++ * runtime power management (disabling USB clocks and reducing
++ * VBUS power usage). However, not all of them do so; silicon,
++ * board, and BIOS bugs here are not uncommon, so these can't
++ * be treated quite like external hubs.
++ *
++ * Likewise, not all root hubs will pass wakeup events upstream,
++ * to wake up the whole system. So don't assume root hub and
++ * controller capabilities are identical.
++ */
++
+ case DeviceRequest | USB_REQ_GET_STATUS:
+- tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
++ tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev)
++ << USB_DEVICE_REMOTE_WAKEUP)
+ | (1 << USB_DEVICE_SELF_POWERED);
+ tbuf [1] = 0;
+ len = 2;
+ break;
+ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+ if (wValue == USB_DEVICE_REMOTE_WAKEUP)
+- hcd->remote_wakeup = 0;
++ device_set_wakeup_enable(&hcd->self.root_hub->dev, 0);
+ else
+ goto error;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_FEATURE:
+- if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP)
+- hcd->remote_wakeup = 1;
++ if (device_can_wakeup(&hcd->self.root_hub->dev)
++ && wValue == USB_DEVICE_REMOTE_WAKEUP)
++ device_set_wakeup_enable(&hcd->self.root_hub->dev, 1);
+ else
+ goto error;
+ break;
+@@ -410,7 +428,7 @@ static int rh_call_control (struct usb_h
+ bufp = fs_rh_config_descriptor;
+ len = sizeof fs_rh_config_descriptor;
+ }
+- if (hcd->can_wakeup)
++ if (device_can_wakeup(&hcd->self.root_hub->dev))
+ patch_wakeup = 1;
+ break;
+ case USB_DT_STRING << 8:
+@@ -1802,16 +1820,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ device_init_wakeup(&rhdev->dev,
+ device_can_wakeup(hcd->self.controller));
+
+- // ... all these hcd->*_wakeup flags will vanish
+- hcd->can_wakeup = device_can_wakeup(hcd->self.controller);
+-
+- /* hcd->driver->reset() reported can_wakeup, probably with
+- * assistance from board's boot firmware.
+- * NOTE: normal devices won't enable wakeup by default.
+- */
+- if (hcd->can_wakeup)
++ /* NOTE: root hub and controller capabilities may not be the same */
++ if (device_can_wakeup(hcd->self.controller)
++ && device_can_wakeup(&hcd->self.root_hub->dev))
+ dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
+- hcd->remote_wakeup = hcd->can_wakeup;
+
+ /* enable irqs just before we start the controller */
+ if (hcd->driver->irq) {
+--- gregkh-2.6.orig/drivers/usb/core/hcd-pci.c
++++ gregkh-2.6/drivers/usb/core/hcd-pci.c
+@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev
+ */
+ retval = pci_set_power_state (dev, PCI_D3hot);
+ if (retval == 0) {
+- dev_dbg (hcd->self.controller, "--> PCI D3\n");
++ int wake = device_can_wakeup(&hcd->self.root_hub->dev);
++
++ wake = wake && device_may_wakeup(hcd->self.controller);
++
++ dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
++ wake ? "/wakeup" : "");
+
+ /* Ignore these return values. We rely on pci code to
+ * reject requests the hardware can't implement, rather
+ * than coding the same thing.
+ */
+- (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+- (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
++ (void) pci_enable_wake (dev, PCI_D3hot, wake);
++ (void) pci_enable_wake (dev, PCI_D3cold, wake);
+ } else {
+ dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+ retval);
+--- gregkh-2.6.orig/drivers/usb/core/hub.c
++++ gregkh-2.6/drivers/usb/core/hub.c
+@@ -1006,12 +1006,18 @@ void usb_set_device_state(struct usb_dev
+ ; /* do nothing */
+ else if (new_state != USB_STATE_NOTATTACHED) {
+ udev->state = new_state;
+- if (new_state == USB_STATE_CONFIGURED)
+- device_init_wakeup(&udev->dev,
+- (udev->actconfig->desc.bmAttributes
+- & USB_CONFIG_ATT_WAKEUP));
+- else if (new_state != USB_STATE_SUSPENDED)
+- device_init_wakeup(&udev->dev, 0);
++
++ /* root hub wakeup capabilities are managed out-of-band
++ * and may involve silicon errata ... ignore them here.
++ */
++ if (udev->parent) {
++ if (new_state == USB_STATE_CONFIGURED)
++ device_init_wakeup(&udev->dev,
++ (udev->actconfig->desc.bmAttributes
++ & USB_CONFIG_ATT_WAKEUP));
++ else if (new_state != USB_STATE_SUSPENDED)
++ device_init_wakeup(&udev->dev, 0);
++ }
+ } else
+ recursively_mark_NOTATTACHED(udev);
+ spin_unlock_irqrestore(&device_state_lock, flags);
+@@ -1875,9 +1881,9 @@ int usb_resume_device(struct usb_device
+ if (udev->state == USB_STATE_NOTATTACHED)
+ return -ENODEV;
+
+-#ifdef CONFIG_USB_SUSPEND
+ /* selective resume of one downstream hub-to-device port */
+ if (udev->parent) {
++#ifdef CONFIG_USB_SUSPEND
+ if (udev->state == USB_STATE_SUSPENDED) {
+ // NOTE swsusp may bork us, device state being wrong...
+ // NOTE this fails if parent is also suspended...
+@@ -1885,8 +1891,8 @@ int usb_resume_device(struct usb_device
+ udev->portnum, udev);
+ } else
+ status = 0;
+- } else
+ #endif
++ } else
+ status = finish_device_resume(udev);
+ if (status < 0)
+ dev_dbg(&udev->dev, "can't resume, status %d\n",
diff --git a/usb/usb-usbcore-sets-up-root-hubs-earlier.patch b/usb/usb-usbcore-sets-up-root-hubs-earlier.patch
new file mode 100644
index 00000000000000..aa8de1aa0d2672
--- /dev/null
+++ b/usb/usb-usbcore-sets-up-root-hubs-earlier.patch
@@ -0,0 +1,198 @@
+From david-b@pacbell.net Mon Jan 23 16:29:38 2006
+From: David Brownell <david-b@pacbell.net>
+To: Greg KH <greg@kroah.com>
+Subject: USB: usbcore sets up root hubs earlier
+Date: Mon, 23 Jan 2006 15:25:40 -0800
+Message-Id: <200601231525.41094.david-b@pacbell.net>
+
+Make the HCD initialization sequence more sane ... notably, setting up
+root hubs before HCDs are asked to do their one-time init. Among other
+things, that lets the HCDs do custom root hub init along with all the
+other one-time initialization done in the (now misnamed) reset() method.
+
+This also copies the controller wakeup flags into the root hub; it's
+done a bit later than would be ideal, but that'll be necessary until
+the PCI code initializes them correctly. (The PCI patch breaks on PPC
+due to how it sequences PCI initialization.)
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd.c | 104 +++++++++++++++++++++++++------------------------
+ 1 file changed, 55 insertions(+), 49 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/core/hcd.c
++++ gregkh-2.6/drivers/usb/core/hcd.c
+@@ -823,18 +823,17 @@ static void usb_deregister_bus (struct u
+
+ /**
+ * register_root_hub - called by usb_add_hcd() to register a root hub
+- * @usb_dev: the usb root hub device to be registered.
+ * @hcd: host controller for this root hub
+ *
+ * This function registers the root hub with the USB subsystem. It sets up
+- * the device properly in the device tree and stores the root_hub pointer
+- * in the bus structure, then calls usb_new_device() to register the usb
+- * device. It also assigns the root hub's USB address (always 1).
++ * the device properly in the device tree and then calls usb_new_device()
++ * to register the usb device. It also assigns the root hub's USB address
++ * (always 1).
+ */
+-static int register_root_hub (struct usb_device *usb_dev,
+- struct usb_hcd *hcd)
++static int register_root_hub(struct usb_hcd *hcd)
+ {
+ struct device *parent_dev = hcd->self.controller;
++ struct usb_device *usb_dev = hcd->self.root_hub;
+ const int devnum = 1;
+ int retval;
+
+@@ -846,12 +845,10 @@ static int register_root_hub (struct usb
+ usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
+
+ mutex_lock(&usb_bus_list_lock);
+- usb_dev->bus->root_hub = usb_dev;
+
+ usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
+ retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
+ if (retval != sizeof usb_dev->descriptor) {
+- usb_dev->bus->root_hub = NULL;
+ mutex_unlock(&usb_bus_list_lock);
+ dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
+ usb_dev->dev.bus_id, retval);
+@@ -860,7 +857,6 @@ static int register_root_hub (struct usb
+
+ retval = usb_new_device (usb_dev);
+ if (retval) {
+- usb_dev->bus->root_hub = NULL;
+ dev_err (parent_dev, "can't register root hub for %s, %d\n",
+ usb_dev->dev.bus_id, retval);
+ }
+@@ -1770,12 +1766,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
+
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+- /* till now HC has been in an indeterminate state ... */
+- if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
+- dev_err(hcd->self.controller, "can't reset\n");
+- return retval;
+- }
+-
++ /* HC is in reset state, but accessible. Now do the one-time init,
++ * bottom up so that hcds can customize the root hubs before khubd
++ * starts talking to them. (Note, bus id is assigned early too.)
++ */
+ if ((retval = hcd_buffer_create(hcd)) != 0) {
+ dev_dbg(hcd->self.controller, "pool alloc failed\n");
+ return retval;
+@@ -1784,6 +1778,42 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ if ((retval = usb_register_bus(&hcd->self)) < 0)
+ goto err_register_bus;
+
++ if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
++ dev_err(hcd->self.controller, "unable to allocate root hub\n");
++ retval = -ENOMEM;
++ goto err_allocate_root_hub;
++ }
++ rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
++ USB_SPEED_FULL;
++ hcd->self.root_hub = rhdev;
++
++ /* "reset" is misnamed; its role is now one-time init. the controller
++ * should already have been reset (and boot firmware kicked off etc).
++ */
++ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
++ dev_err(hcd->self.controller, "can't setup\n");
++ goto err_hcd_driver_setup;
++ }
++
++ /* wakeup flag init is in transition; for now we can't rely on PCI to
++ * initialize these bits properly, so we let reset() override it.
++ * This init should _precede_ the reset() once PCI behaves.
++ */
++ device_init_wakeup(&rhdev->dev,
++ device_can_wakeup(hcd->self.controller));
++
++ // ... all these hcd->*_wakeup flags will vanish
++ hcd->can_wakeup = device_can_wakeup(hcd->self.controller);
++
++ /* hcd->driver->reset() reported can_wakeup, probably with
++ * assistance from board's boot firmware.
++ * NOTE: normal devices won't enable wakeup by default.
++ */
++ if (hcd->can_wakeup)
++ dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
++ hcd->remote_wakeup = hcd->can_wakeup;
++
++ /* enable irqs just before we start the controller */
+ if (hcd->driver->irq) {
+ char buf[8], *bufp = buf;
+
+@@ -1815,56 +1845,32 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ (unsigned long long)hcd->rsrc_start);
+ }
+
+- /* Allocate the root hub before calling hcd->driver->start(),
+- * but don't register it until afterward so that the hardware
+- * is running.
+- */
+- if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
+- dev_err(hcd->self.controller, "unable to allocate root hub\n");
+- retval = -ENOMEM;
+- goto err_allocate_root_hub;
+- }
+-
+- /* Although in principle hcd->driver->start() might need to use rhdev,
+- * none of the current drivers do.
+- */
+ if ((retval = hcd->driver->start(hcd)) < 0) {
+ dev_err(hcd->self.controller, "startup error %d\n", retval);
+ goto err_hcd_driver_start;
+ }
+
+- /* hcd->driver->start() reported can_wakeup, probably with
+- * assistance from board's boot firmware.
+- * NOTE: normal devices won't enable wakeup by default.
+- */
+- if (hcd->can_wakeup)
+- dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
+- hcd->remote_wakeup = hcd->can_wakeup;
+-
+- rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+- USB_SPEED_FULL;
++ /* starting here, usbcore will pay attention to this root hub */
+ rhdev->bus_mA = min(500u, hcd->power_budget);
+- if ((retval = register_root_hub(rhdev, hcd)) != 0)
++ if ((retval = register_root_hub(hcd)) != 0)
+ goto err_register_root_hub;
+
+ if (hcd->uses_new_polling && hcd->poll_rh)
+ usb_hcd_poll_rh_status(hcd);
+ return retval;
+
+- err_register_root_hub:
++err_register_root_hub:
+ hcd->driver->stop(hcd);
+-
+- err_hcd_driver_start:
+- usb_put_dev(rhdev);
+-
+- err_allocate_root_hub:
++err_hcd_driver_start:
+ if (hcd->irq >= 0)
+ free_irq(irqnum, hcd);
+-
+- err_request_irq:
++err_request_irq:
++err_hcd_driver_setup:
++ hcd->self.root_hub = NULL;
++ usb_put_dev(rhdev);
++err_allocate_root_hub:
+ usb_deregister_bus(&hcd->self);
+-
+- err_register_bus:
++err_register_bus:
+ hcd_buffer_destroy(hcd);
+ return retval;
+ }