diff options
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 52 |
1 files changed, 17 insertions, 35 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index ce7b28da7a15..e01e77bc324b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | /*-------------------------------------------------------------------------*/ | 37 | /*-------------------------------------------------------------------------*/ |
38 | 38 | ||
39 | #if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) | 39 | #ifdef CONFIG_PM |
40 | 40 | ||
41 | #define OHCI_SCHED_ENABLES \ | 41 | #define OHCI_SCHED_ENABLES \ |
42 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) | 42 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) |
@@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *); | |||
45 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); | 45 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); |
46 | static int ohci_restart (struct ohci_hcd *ohci); | 46 | static int ohci_restart (struct ohci_hcd *ohci); |
47 | 47 | ||
48 | static int ohci_hub_suspend (struct usb_hcd *hcd) | 48 | static int ohci_bus_suspend (struct usb_hcd *hcd) |
49 | { | 49 | { |
50 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 50 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
51 | int status = 0; | 51 | int status = 0; |
@@ -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 | } |
@@ -133,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed) | |||
133 | } | 135 | } |
134 | 136 | ||
135 | /* caller has locked the root hub */ | 137 | /* caller has locked the root hub */ |
136 | static int ohci_hub_resume (struct usb_hcd *hcd) | 138 | static int ohci_bus_resume (struct usb_hcd *hcd) |
137 | { | 139 | { |
138 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 140 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
139 | u32 temp, enables; | 141 | u32 temp, enables; |
@@ -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,28 +275,10 @@ 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 | #endif /* CONFIG_PM */ |
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_USB_SUSPEND || CONFIG_PM */ | ||
298 | 282 | ||
299 | /*-------------------------------------------------------------------------*/ | 283 | /*-------------------------------------------------------------------------*/ |
300 | 284 | ||
@@ -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 |
@@ -379,8 +362,7 @@ done: | |||
379 | && usb_trylock_device (hcd->self.root_hub) | 362 | && usb_trylock_device (hcd->self.root_hub) |
380 | ) { | 363 | ) { |
381 | ohci_vdbg (ohci, "autosuspend\n"); | 364 | ohci_vdbg (ohci, "autosuspend\n"); |
382 | (void) ohci_hub_suspend (hcd); | 365 | (void) ohci_bus_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; |