aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c52
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 *);
45static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); 45static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
46static int ohci_restart (struct ohci_hcd *ohci); 46static int ohci_restart (struct ohci_hcd *ohci);
47 47
48static int ohci_hub_suspend (struct usb_hcd *hcd) 48static 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
120done: 121done:
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 */
136static int ohci_hub_resume (struct usb_hcd *hcd) 138static 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
280static 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
291static 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;