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; |
