diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/usb/core/hub.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 3 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 77 |
4 files changed, 46 insertions, 42 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 840727948d84..f78bd124d290 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -1669,7 +1669,6 @@ int usb_suspend_device(struct usb_device *udev) | |||
| 1669 | return 0; | 1669 | return 0; |
| 1670 | #endif | 1670 | #endif |
| 1671 | } | 1671 | } |
| 1672 | EXPORT_SYMBOL_GPL(usb_suspend_device); | ||
| 1673 | 1672 | ||
| 1674 | /* | 1673 | /* |
| 1675 | * If the USB "suspend" state is in use (rather than "global suspend"), | 1674 | * If the USB "suspend" state is in use (rather than "global suspend"), |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index af3c05eb86fc..f15144e96e14 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -636,9 +636,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 636 | * stop that signaling. | 636 | * stop that signaling. |
| 637 | */ | 637 | */ |
| 638 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | 638 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); |
| 639 | mod_timer (&hcd->rh_timer, | ||
| 640 | ehci->reset_done [i] + 1); | ||
| 641 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); | 639 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); |
| 640 | usb_hcd_resume_root_hub(hcd); | ||
| 642 | } | 641 | } |
| 643 | } | 642 | } |
| 644 | 643 | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 88cb4ada686e..82caf336e9b6 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -94,6 +94,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
| 94 | msleep(5); | 94 | msleep(5); |
| 95 | spin_lock_irq (&ehci->lock); | 95 | spin_lock_irq (&ehci->lock); |
| 96 | 96 | ||
| 97 | /* Ideally and we've got a real resume here, and no port's power | ||
| 98 | * was lost. (For PCI, that means Vaux was maintained.) But we | ||
| 99 | * could instead be restoring a swsusp snapshot -- so that BIOS was | ||
| 100 | * the last user of the controller, not reset/pm hardware keeping | ||
| 101 | * state we gave to it. | ||
| 102 | */ | ||
| 103 | |||
| 97 | /* re-init operational registers in case we lost power */ | 104 | /* re-init operational registers in case we lost power */ |
| 98 | if (readl (&ehci->regs->intr_enable) == 0) { | 105 | if (readl (&ehci->regs->intr_enable) == 0) { |
| 99 | /* at least some APM implementations will try to deliver | 106 | /* at least some APM implementations will try to deliver |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dfd9bd0b1828..0f2be91e5e0e 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -235,10 +235,11 @@ static void ehci_pci_stop (struct usb_hcd *hcd) | |||
| 235 | 235 | ||
| 236 | /* suspend/resume, section 4.3 */ | 236 | /* suspend/resume, section 4.3 */ |
| 237 | 237 | ||
| 238 | /* These routines rely on the bus (pci, platform, etc) | 238 | /* These routines rely on the PCI bus glue |
| 239 | * to handle powerdown and wakeup, and currently also on | 239 | * to handle powerdown and wakeup, and currently also on |
| 240 | * transceivers that don't need any software attention to set up | 240 | * transceivers that don't need any software attention to set up |
| 241 | * the right sort of wakeup. | 241 | * the right sort of wakeup. |
| 242 | * Also they depend on separate root hub suspend/resume. | ||
| 242 | */ | 243 | */ |
| 243 | 244 | ||
| 244 | static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | 245 | static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) |
| @@ -246,17 +247,9 @@ static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
| 246 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 247 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 247 | 248 | ||
| 248 | if (time_before (jiffies, ehci->next_statechange)) | 249 | if (time_before (jiffies, ehci->next_statechange)) |
| 249 | msleep (100); | 250 | msleep (10); |
| 250 | |||
| 251 | #ifdef CONFIG_USB_SUSPEND | ||
| 252 | (void) usb_suspend_device (hcd->self.root_hub); | ||
| 253 | #else | ||
| 254 | usb_lock_device (hcd->self.root_hub); | ||
| 255 | (void) ehci_bus_suspend (hcd); | ||
| 256 | usb_unlock_device (hcd->self.root_hub); | ||
| 257 | #endif | ||
| 258 | 251 | ||
| 259 | // save (PCI) FLADJ in case of Vaux power loss | 252 | // could save FLADJ in case of Vaux power loss |
| 260 | // ... we'd only use it to handle clock skew | 253 | // ... we'd only use it to handle clock skew |
| 261 | 254 | ||
| 262 | return 0; | 255 | return 0; |
| @@ -269,13 +262,18 @@ static int ehci_pci_resume (struct usb_hcd *hcd) | |||
| 269 | struct usb_device *root = hcd->self.root_hub; | 262 | struct usb_device *root = hcd->self.root_hub; |
| 270 | int retval = -EINVAL; | 263 | int retval = -EINVAL; |
| 271 | 264 | ||
| 272 | // maybe restore (PCI) FLADJ | 265 | // maybe restore FLADJ |
| 273 | 266 | ||
| 274 | if (time_before (jiffies, ehci->next_statechange)) | 267 | if (time_before (jiffies, ehci->next_statechange)) |
| 275 | msleep (100); | 268 | msleep (100); |
| 276 | 269 | ||
| 270 | /* If CF is clear, we lost PCI Vaux power and need to restart. */ | ||
| 271 | if (readl (&ehci->regs->configured_flag) != cpu_to_le32(FLAG_CF)) | ||
| 272 | goto restart; | ||
| 273 | |||
| 277 | /* If any port is suspended (or owned by the companion), | 274 | /* If any port is suspended (or owned by the companion), |
| 278 | * we know we can/must resume the HC (and mustn't reset it). | 275 | * we know we can/must resume the HC (and mustn't reset it). |
| 276 | * We just defer that to the root hub code. | ||
| 279 | */ | 277 | */ |
| 280 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { | 278 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { |
| 281 | u32 status; | 279 | u32 status; |
| @@ -283,42 +281,43 @@ static int ehci_pci_resume (struct usb_hcd *hcd) | |||
| 283 | status = readl (&ehci->regs->port_status [port]); | 281 | status = readl (&ehci->regs->port_status [port]); |
| 284 | if (!(status & PORT_POWER)) | 282 | if (!(status & PORT_POWER)) |
| 285 | continue; | 283 | continue; |
| 286 | if (status & (PORT_SUSPEND | PORT_OWNER)) { | 284 | if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { |
| 287 | down (&hcd->self.root_hub->serialize); | 285 | usb_hcd_resume_root_hub(hcd); |
| 288 | retval = ehci_bus_resume (hcd); | 286 | return 0; |
| 289 | up (&hcd->self.root_hub->serialize); | ||
| 290 | break; | ||
| 291 | } | 287 | } |
| 288 | } | ||
| 289 | |||
| 290 | restart: | ||
| 291 | ehci_dbg(ehci, "lost power, restarting\n"); | ||
| 292 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { | ||
| 293 | port--; | ||
| 292 | if (!root->children [port]) | 294 | if (!root->children [port]) |
| 293 | continue; | 295 | continue; |
| 294 | dbg_port (ehci, __FUNCTION__, port + 1, status); | ||
| 295 | usb_set_device_state (root->children[port], | 296 | usb_set_device_state (root->children[port], |
| 296 | USB_STATE_NOTATTACHED); | 297 | USB_STATE_NOTATTACHED); |
| 297 | } | 298 | } |
| 298 | 299 | ||
| 299 | /* Else reset, to cope with power loss or flush-to-storage | 300 | /* Else reset, to cope with power loss or flush-to-storage |
| 300 | * style "resume" having activated BIOS during reboot. | 301 | * style "resume" having let BIOS kick in during reboot. |
| 301 | */ | 302 | */ |
| 302 | if (port == 0) { | 303 | (void) ehci_halt (ehci); |
| 303 | (void) ehci_halt (ehci); | 304 | (void) ehci_reset (ehci); |
| 304 | (void) ehci_reset (ehci); | 305 | (void) ehci_pci_reset (hcd); |
| 305 | (void) ehci_pci_reset (hcd); | 306 | |
| 306 | 307 | /* emptying the schedule aborts any urbs */ | |
| 307 | /* emptying the schedule aborts any urbs */ | 308 | spin_lock_irq (&ehci->lock); |
| 308 | spin_lock_irq (&ehci->lock); | 309 | if (ehci->reclaim) |
| 309 | if (ehci->reclaim) | 310 | ehci->reclaim_ready = 1; |
| 310 | ehci->reclaim_ready = 1; | 311 | ehci_work (ehci, NULL); |
| 311 | ehci_work (ehci, NULL); | 312 | spin_unlock_irq (&ehci->lock); |
| 312 | spin_unlock_irq (&ehci->lock); | 313 | |
| 313 | 314 | /* restart; khubd will disconnect devices */ | |
| 314 | /* restart; khubd will disconnect devices */ | 315 | retval = ehci_run (hcd); |
| 315 | retval = ehci_run (hcd); | 316 | |
| 316 | 317 | /* here we "know" root ports should always stay powered; | |
| 317 | /* here we "know" root ports should always stay powered; | 318 | * but some controllers may lose all power. |
| 318 | * but some controllers may lose all power. | 319 | */ |
| 319 | */ | 320 | ehci_port_power (ehci, 1); |
| 320 | ehci_port_power (ehci, 1); | ||
| 321 | } | ||
| 322 | 321 | ||
| 323 | return retval; | 322 | return retval; |
| 324 | } | 323 | } |
