diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-27 10:21:23 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-27 10:21:23 -0800 |
commit | afba9fdd0bc76de323628ad9a25b20310d05031c (patch) | |
tree | 8b961788bf41178f29ca8519839447cf2ef835d4 /usb | |
parent | 1bb63250ce140bce4ce684ec6b733e4af723d803 (diff) | |
download | patches-afba9fdd0bc76de323628ad9a25b20310d05031c.tar.gz |
more usb and pci patches
Diffstat (limited to 'usb')
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 0000000000000..118bfd93273c3 --- /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 0000000000000..39e777d5c9bde --- /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 0000000000000..19c597db48d6f --- /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 0000000000000..7d14440236eea --- /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 0000000000000..aa8de1aa0d267 --- /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; + } |