aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-04-03 18:03:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:48 -0400
commit43bbb7e015c4380064796c5868b536437b165615 (patch)
tree6f4b8e184904917677ce00f600ebf3c8839f47f0 /drivers/usb/host/ohci-hub.c
parent7be7d7418776a41badce7ca00246e270d408e4b9 (diff)
USB: OHCI: host-controller resumes leave root hub suspended
Drivers in the ohci-hcd family should perform certain tasks whenever their controller device is resumed. These include checking for loss of power during suspend, turning on port power, and enabling interrupt requests. Until now these jobs have been carried out when the root hub is resumed, not when the controller is. Many drivers work around the resulting awkwardness by automatically resuming their root hub whenever the controller is resumed. But this is wasteful and unnecessary. To simplify the situation, this patch (as1066) adds a new core routine, ohci_finish_controller_resume(), which can be used by all the OHCI-variant drivers. They can call the new routine instead of resuming their root hubs. And ohci-pci.c can call it instead of using its own special-purpose handler. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index c638e6b33c43..28d6d775eb5f 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -326,6 +326,49 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
326 return rc; 326 return rc;
327} 327}
328 328
329/* Carry out the final steps of resuming the controller device */
330static void ohci_finish_controller_resume(struct usb_hcd *hcd)
331{
332 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
333 int port;
334 bool need_reinit = false;
335
336 /* See if the controller is already running or has been reset */
337 ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
338 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
339 need_reinit = true;
340 } else {
341 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
342 case OHCI_USB_OPER:
343 case OHCI_USB_RESET:
344 need_reinit = true;
345 }
346 }
347
348 /* If needed, reinitialize and suspend the root hub */
349 if (need_reinit) {
350 spin_lock_irq(&ohci->lock);
351 hcd->state = HC_STATE_RESUMING;
352 ohci_rh_resume(ohci);
353 hcd->state = HC_STATE_QUIESCING;
354 ohci_rh_suspend(ohci, 0);
355 hcd->state = HC_STATE_SUSPENDED;
356 spin_unlock_irq(&ohci->lock);
357 }
358
359 /* Normally just turn on port power and enable interrupts */
360 else {
361 ohci_dbg(ohci, "powerup ports\n");
362 for (port = 0; port < ohci->num_ports; port++)
363 ohci_writel(ohci, RH_PS_PPS,
364 &ohci->regs->roothub.portstatus[port]);
365
366 ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
367 ohci_readl(ohci, &ohci->regs->intrenable);
368 msleep(20);
369 }
370}
371
329/* Carry out polling-, autostop-, and autoresume-related state changes */ 372/* Carry out polling-, autostop-, and autoresume-related state changes */
330static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, 373static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
331 int any_connected) 374 int any_connected)