On Thu, 12 May 2005, David Brownell wrote: > > And here's a suggestion for a solution. Make usb_hcd_resume_root_hub > > conditional on CONFIG_PM rather than CONFIG_USB_SUSPEND (i.e., use your > > patch), and make khubd call the hub_resume method directly if > > root_hub->state != USB_STATE_SUSPENDED -- which will always be the case if > > !CONFIG_USB_SUSPEND. This means also changing OHCI so that it leaves the > > state equal to USB_STATE_CONFIGURED when autosuspending. How does that > > sound? > > Simplest to just _always_ call hub_resume(). After all, the HCD would > not have told usbcore to wake the hub up if it didn't need it ... :)
Here's an updated version of your patch. I won't be able to try it out but it looks okay. The only modification is the new hunk at the end of the patch. It should be easy to tell if it works: Just plug in a USB device to an otherwise unconnected controller and see if anything happens! Alan Stern This updates OHCI to use the new usbcore resume_root_hub() mechanism, and fixes that mechanism so it's available with CONFIG_PM. It also continues getting rid of some #ifdefs of the form (PM || USB_SUSPEND); they're superfluous: USB_SUSPEND is a strict superset of PM. It also updates the resume_root_hub implementation. If the root hub was suspended by calling through usb_suspend_device() then it is resumed by calling usb_resume_device(), as usual. But if the root hub was suspended some other way, the code now calls the hub_resume() method directly. Signed-off-by: David Brownell <[EMAIL PROTECTED]> Signed-off-by: Alan Stern <[EMAIL PROTECTED]> Index: usb-2.6/drivers/usb/core/hcd.c =================================================================== --- usb-2.6.orig/drivers/usb/core/hcd.c +++ usb-2.6/drivers/usb/core/hcd.c @@ -1437,7 +1437,7 @@ rescan: /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM static int hcd_hub_suspend (struct usb_bus *bus) { @@ -1477,13 +1477,9 @@ void usb_hcd_resume_root_hub (struct usb usb_resume_root_hub (hcd->self.root_hub); spin_unlock_irqrestore (&hcd_root_hub_lock, flags); } +EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); -#else -void usb_hcd_resume_root_hub (struct usb_hcd *hcd) -{ -} #endif -EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); /*-------------------------------------------------------------------------*/ @@ -1536,7 +1532,7 @@ static struct usb_operations usb_hcd_ope .buffer_alloc = hcd_buffer_alloc, .buffer_free = hcd_buffer_free, .disable = hcd_endpoint_disable, -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM .hub_suspend = hcd_hub_suspend, .hub_resume = hcd_hub_resume, #endif Index: usb-2.6/drivers/usb/host/ohci-hub.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-hub.c +++ usb-2.6/drivers/usb/host/ohci-hub.c @@ -36,7 +36,7 @@ /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -277,24 +277,7 @@ static int ohci_hub_resume (struct usb_h return 0; } -static void ohci_rh_resume (void *_hcd) -{ - struct usb_hcd *hcd = _hcd; - - usb_lock_device (hcd->self.root_hub); - (void) ohci_hub_resume (hcd); - usb_unlock_device (hcd->self.root_hub); -} - -#else - -static void ohci_rh_resume (void *_hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (_hcd); - ohci_dbg(ohci, "rh_resume ??\n"); -} - -#endif /* CONFIG_USB_SUSPEND || CONFIG_PM */ +#endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ @@ -553,7 +536,7 @@ static int ohci_hub_control ( temp = RH_PS_POCI; if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) - schedule_work (&ohci->rh_resume); + usb_hcd_resume_root_hub(hcd); break; case USB_PORT_FEAT_C_SUSPEND: temp = RH_PS_PSSC; Index: usb-2.6/drivers/usb/host/ohci-mem.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-mem.c +++ usb-2.6/drivers/usb/host/ohci-mem.c @@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_h ohci->next_statechange = jiffies; spin_lock_init (&ohci->lock); INIT_LIST_HEAD (&ohci->pending); - INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); ohci->reboot_notifier.notifier_call = ohci_reboot; } Index: usb-2.6/drivers/usb/host/ohci.h =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci.h +++ usb-2.6/drivers/usb/host/ohci.h @@ -388,7 +388,6 @@ struct ohci_hcd { unsigned long next_statechange; /* suspend/resume */ u32 fminterval; /* saved register */ - struct work_struct rh_resume; struct notifier_block reboot_notifier; unsigned long flags; /* for HC bugs */ Index: usb-2.6/drivers/usb/host/ohci-hcd.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-hcd.c +++ usb-2.6/drivers/usb/host/ohci-hcd.c @@ -719,7 +719,10 @@ static irqreturn_t ohci_irq (struct usb_ if (ints & OHCI_INTR_RD) { ohci_vdbg (ohci, "resume detect\n"); if (hcd->state != HC_STATE_QUIESCING) - schedule_work(&ohci->rh_resume); + usb_hcd_resume_root_hub(hcd); + /* in case root is autosuspended */ + ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); + ints &= ~OHCI_INTR_RD; } if (ints & OHCI_INTR_WDH) { Index: usb-2.6/drivers/usb/core/hub.c =================================================================== --- usb-2.6.orig/drivers/usb/core/hub.c +++ usb-2.6/drivers/usb/core/hub.c @@ -1977,14 +1977,6 @@ static int hub_resume(struct usb_interfa return 0; } -void usb_resume_root_hub(struct usb_device *hdev) -{ - struct usb_hub *hub = hdev_to_hub(hdev); - - hub->resume_root_hub = 1; - kick_khubd(hub); -} - #else /* !CONFIG_USB_SUSPEND */ int usb_suspend_device(struct usb_device *udev, pm_message_t state) @@ -2006,6 +1998,17 @@ int usb_resume_device(struct usb_device EXPORT_SYMBOL(usb_suspend_device); EXPORT_SYMBOL(usb_resume_device); +#ifdef CONFIG_PM + +void usb_resume_root_hub(struct usb_device *hdev) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + hub->resume_root_hub = 1; + kick_khubd(hub); +} + +#endif /* CONFIG_PM */ /* USB 2.0 spec, 7.1.7.3 / fig 7-29: @@ -2645,8 +2648,19 @@ static void hub_events(void) spin_unlock_irq(&hub_event_lock); /* Is this is a root hub wanting to be resumed? */ - if (i) - usb_resume_device(hdev); + if (i) { + + /* If the device was suspended by usb_suspend_device() + * then resume it by calling usb_resume_device() */ + if (hdev->state == USB_STATE_SUSPENDED) + usb_resume_device(hdev); + + /* Otherwise call the hub_resume() method directly */ + else if (locktree(hdev) >= 0) { + hdev->bus->op->hub_resume(hdev->bus); + usb_unlock_device(hdev); + } + } /* Lock the device, then check to see if we were * disconnected while waiting for the lock to succeed. */ ------------------------------------------------------- This SF.Net email is sponsored by Oracle Space Sweepstakes Want to be the first software developer in space? Enter now for the Oracle Space Sweepstakes! http://ads.osdn.com/?ad_id=7412&alloc_id=16344&op=click _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel