diff options
author | David Brownell <david-b@pacbell.net> | 2005-09-23 01:42:53 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 19:47:40 -0400 |
commit | f197b2c54b9d9a133a9a8ff92f35cadf8945ea14 (patch) | |
tree | a5a4da41e38d8681977a9f3b52fa2e5f1db278ea /drivers/usb/host/ohci-hub.c | |
parent | 5f827ea3c3820cd8e0a1a35e4d275c8b78ee94e1 (diff) |
[PATCH] OHCI PM updates
This simplifies the OHCI root hub suspend logic:
- Uses new usbcore root hub calls to make autosuspend work again:
* Uses a newish usbcore root hub wakeup mechanism,
making requests to khubd not keventd.
* Uses an even newer sibling suspend hook.
- Expect someone always made usbcore call ohci_hub_suspend() before bus
glue fires; and that ohci_hub_resume() is only called after that bus
glue ran. Previously, only CONFIG_USB_SUSPEND promised those things.
(Includes updates to PCI and OMAP bus glue.)
- Handle a not-noticed-before special case during resume from one of
the swsusp snapshots when using "usb-handoff": the controller isn't
left in RESET state. (A bug to fix in the usb-handoff code...)
Also cleans up a minor debug printk glitch, and switches an mdelay over
to an msleep (how did that stick around for so long?).
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ohci-dbg.c | 4 ----
drivers/usb/host/ohci-hcd.c | 2 +-
drivers/usb/host/ohci-hub.c | 42 ++++++++++++------------------------------
drivers/usb/host/ohci-mem.c | 1 -
drivers/usb/host/ohci-omap.c | 36 ++++++++++++------------------------
drivers/usb/host/ohci-pci.c | 40 ++++++++--------------------------------
drivers/usb/host/ohci.h | 1 -
7 files changed, 33 insertions(+), 93 deletions(-)
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 42 |
1 files changed, 12 insertions, 30 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index b96948ea3005..39a60e731ec2 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -73,7 +73,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
73 | ohci_dbg (ohci, "suspend root hub\n"); | 73 | ohci_dbg (ohci, "suspend root hub\n"); |
74 | 74 | ||
75 | /* First stop any processing */ | 75 | /* First stop any processing */ |
76 | hcd->state = HC_STATE_QUIESCING; | ||
77 | if (ohci->hc_control & OHCI_SCHED_ENABLES) { | 76 | if (ohci->hc_control & OHCI_SCHED_ENABLES) { |
78 | int limit; | 77 | int limit; |
79 | 78 | ||
@@ -108,7 +107,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
108 | else | 107 | else |
109 | ohci->hc_control &= ~OHCI_CTRL_RWE; | 108 | ohci->hc_control &= ~OHCI_CTRL_RWE; |
110 | 109 | ||
111 | /* Suspend hub */ | 110 | /* Suspend hub ... this is the "global (to this bus) suspend" mode, |
111 | * which doesn't imply ports will first be individually suspended. | ||
112 | */ | ||
112 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | 113 | ohci->hc_control &= ~OHCI_CTRL_HCFS; |
113 | ohci->hc_control |= OHCI_USB_SUSPEND; | 114 | ohci->hc_control |= OHCI_USB_SUSPEND; |
114 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 115 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
@@ -118,8 +119,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
118 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); | 119 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); |
119 | 120 | ||
120 | done: | 121 | done: |
122 | /* external suspend vs self autosuspend ... same effect */ | ||
121 | if (status == 0) | 123 | if (status == 0) |
122 | hcd->state = HC_STATE_SUSPENDED; | 124 | usb_hcd_suspend_root_hub(hcd); |
123 | spin_unlock_irqrestore (&ohci->lock, flags); | 125 | spin_unlock_irqrestore (&ohci->lock, flags); |
124 | return status; | 126 | return status; |
125 | } | 127 | } |
@@ -146,7 +148,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
146 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 148 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
147 | 149 | ||
148 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { | 150 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { |
149 | /* this can happen after suspend-to-disk */ | 151 | /* this can happen after resuming a swsusp snapshot */ |
150 | if (hcd->state == HC_STATE_RESUMING) { | 152 | if (hcd->state == HC_STATE_RESUMING) { |
151 | ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", | 153 | ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", |
152 | ohci->hc_control); | 154 | ohci->hc_control); |
@@ -169,11 +171,12 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
169 | ohci_info (ohci, "wakeup\n"); | 171 | ohci_info (ohci, "wakeup\n"); |
170 | break; | 172 | break; |
171 | case OHCI_USB_OPER: | 173 | case OHCI_USB_OPER: |
172 | ohci_dbg (ohci, "already resumed\n"); | 174 | /* this can happen after resuming a swsusp snapshot */ |
173 | status = 0; | 175 | ohci_dbg (ohci, "snapshot resume? reinit\n"); |
176 | status = -EBUSY; | ||
174 | break; | 177 | break; |
175 | default: /* RESET, we lost power */ | 178 | default: /* RESET, we lost power */ |
176 | ohci_dbg (ohci, "root hub hardware reset\n"); | 179 | ohci_dbg (ohci, "lost power\n"); |
177 | status = -EBUSY; | 180 | status = -EBUSY; |
178 | } | 181 | } |
179 | spin_unlock_irq (&ohci->lock); | 182 | spin_unlock_irq (&ohci->lock); |
@@ -198,8 +201,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
198 | } | 201 | } |
199 | 202 | ||
200 | /* Some controllers (lucent erratum) need extra-long delays */ | 203 | /* Some controllers (lucent erratum) need extra-long delays */ |
201 | hcd->state = HC_STATE_RESUMING; | 204 | msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); |
202 | mdelay (20 /* usb 11.5.1.10 */ + 15); | ||
203 | 205 | ||
204 | temp = ohci_readl (ohci, &ohci->regs->control); | 206 | temp = ohci_readl (ohci, &ohci->regs->control); |
205 | temp &= OHCI_CTRL_HCFS; | 207 | temp &= OHCI_CTRL_HCFS; |
@@ -273,27 +275,9 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
273 | (void) ohci_readl (ohci, &ohci->regs->control); | 275 | (void) ohci_readl (ohci, &ohci->regs->control); |
274 | } | 276 | } |
275 | 277 | ||
276 | hcd->state = HC_STATE_RUNNING; | ||
277 | return 0; | 278 | return 0; |
278 | } | 279 | } |
279 | 280 | ||
280 | static void ohci_rh_resume (void *_hcd) | ||
281 | { | ||
282 | struct usb_hcd *hcd = _hcd; | ||
283 | |||
284 | usb_lock_device (hcd->self.root_hub); | ||
285 | (void) ohci_hub_resume (hcd); | ||
286 | usb_unlock_device (hcd->self.root_hub); | ||
287 | } | ||
288 | |||
289 | #else | ||
290 | |||
291 | static void ohci_rh_resume (void *_hcd) | ||
292 | { | ||
293 | struct ohci_hcd *ohci = hcd_to_ohci (_hcd); | ||
294 | ohci_dbg(ohci, "rh_resume ??\n"); | ||
295 | } | ||
296 | |||
297 | #endif /* CONFIG_PM */ | 281 | #endif /* CONFIG_PM */ |
298 | 282 | ||
299 | /*-------------------------------------------------------------------------*/ | 283 | /*-------------------------------------------------------------------------*/ |
@@ -367,7 +351,6 @@ done: | |||
367 | #ifdef CONFIG_PM | 351 | #ifdef CONFIG_PM |
368 | /* save power by suspending idle root hubs; | 352 | /* save power by suspending idle root hubs; |
369 | * INTR_RD wakes us when there's work | 353 | * INTR_RD wakes us when there's work |
370 | * NOTE: if we can do this, we don't need a root hub timer! | ||
371 | */ | 354 | */ |
372 | if (can_suspend | 355 | if (can_suspend |
373 | && !changed | 356 | && !changed |
@@ -380,7 +363,6 @@ done: | |||
380 | ) { | 363 | ) { |
381 | ohci_vdbg (ohci, "autosuspend\n"); | 364 | ohci_vdbg (ohci, "autosuspend\n"); |
382 | (void) ohci_hub_suspend (hcd); | 365 | (void) ohci_hub_suspend (hcd); |
383 | hcd->state = HC_STATE_RUNNING; | ||
384 | usb_unlock_device (hcd->self.root_hub); | 366 | usb_unlock_device (hcd->self.root_hub); |
385 | } | 367 | } |
386 | #endif | 368 | #endif |
@@ -554,7 +536,7 @@ static int ohci_hub_control ( | |||
554 | temp = RH_PS_POCI; | 536 | temp = RH_PS_POCI; |
555 | if ((ohci->hc_control & OHCI_CTRL_HCFS) | 537 | if ((ohci->hc_control & OHCI_CTRL_HCFS) |
556 | != OHCI_USB_OPER) | 538 | != OHCI_USB_OPER) |
557 | schedule_work (&ohci->rh_resume); | 539 | usb_hcd_resume_root_hub(hcd); |
558 | break; | 540 | break; |
559 | case USB_PORT_FEAT_C_SUSPEND: | 541 | case USB_PORT_FEAT_C_SUSPEND: |
560 | temp = RH_PS_PSSC; | 542 | temp = RH_PS_PSSC; |