diff options
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index ffc5f27df725..c7880223738a 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -221,6 +221,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
221 | ehci_quiesce(ehci); | 221 | ehci_quiesce(ehci); |
222 | 222 | ||
223 | spin_lock_irq (&ehci->lock); | 223 | spin_lock_irq (&ehci->lock); |
224 | if (ehci->rh_state < EHCI_RH_RUNNING) | ||
225 | goto done; | ||
224 | 226 | ||
225 | /* Once the controller is stopped, port resumes that are already | 227 | /* Once the controller is stopped, port resumes that are already |
226 | * in progress won't complete. Hence if remote wakeup is enabled | 228 | * in progress won't complete. Hence if remote wakeup is enabled |
@@ -306,6 +308,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
306 | ehci_halt (ehci); | 308 | ehci_halt (ehci); |
307 | 309 | ||
308 | spin_lock_irq(&ehci->lock); | 310 | spin_lock_irq(&ehci->lock); |
311 | if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD)) | ||
312 | ehci_handle_controller_death(ehci); | ||
313 | if (ehci->rh_state != EHCI_RH_RUNNING) | ||
314 | goto done; | ||
309 | ehci->rh_state = EHCI_RH_SUSPENDED; | 315 | ehci->rh_state = EHCI_RH_SUSPENDED; |
310 | 316 | ||
311 | end_unlink_async(ehci); | 317 | end_unlink_async(ehci); |
@@ -320,6 +326,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
320 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); | 326 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
321 | ehci_readl(ehci, &ehci->regs->intr_enable); | 327 | ehci_readl(ehci, &ehci->regs->intr_enable); |
322 | 328 | ||
329 | done: | ||
323 | ehci->next_statechange = jiffies + msecs_to_jiffies(10); | 330 | ehci->next_statechange = jiffies + msecs_to_jiffies(10); |
324 | ehci->enabled_hrtimer_events = 0; | 331 | ehci->enabled_hrtimer_events = 0; |
325 | ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; | 332 | ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; |
@@ -342,10 +349,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
342 | if (time_before (jiffies, ehci->next_statechange)) | 349 | if (time_before (jiffies, ehci->next_statechange)) |
343 | msleep(5); | 350 | msleep(5); |
344 | spin_lock_irq (&ehci->lock); | 351 | spin_lock_irq (&ehci->lock); |
345 | if (!HCD_HW_ACCESSIBLE(hcd)) { | 352 | if (!HCD_HW_ACCESSIBLE(hcd) || ehci->shutdown) |
346 | spin_unlock_irq(&ehci->lock); | 353 | goto shutdown; |
347 | return -ESHUTDOWN; | ||
348 | } | ||
349 | 354 | ||
350 | if (unlikely(ehci->debug)) { | 355 | if (unlikely(ehci->debug)) { |
351 | if (!dbgp_reset_prep()) | 356 | if (!dbgp_reset_prep()) |
@@ -384,6 +389,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
384 | spin_unlock_irq(&ehci->lock); | 389 | spin_unlock_irq(&ehci->lock); |
385 | msleep(8); | 390 | msleep(8); |
386 | spin_lock_irq(&ehci->lock); | 391 | spin_lock_irq(&ehci->lock); |
392 | if (ehci->shutdown) | ||
393 | goto shutdown; | ||
387 | 394 | ||
388 | /* clear phy low-power mode before resume */ | 395 | /* clear phy low-power mode before resume */ |
389 | if (ehci->bus_suspended && ehci->has_hostpc) { | 396 | if (ehci->bus_suspended && ehci->has_hostpc) { |
@@ -401,6 +408,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
401 | spin_unlock_irq(&ehci->lock); | 408 | spin_unlock_irq(&ehci->lock); |
402 | msleep(5); | 409 | msleep(5); |
403 | spin_lock_irq(&ehci->lock); | 410 | spin_lock_irq(&ehci->lock); |
411 | if (ehci->shutdown) | ||
412 | goto shutdown; | ||
404 | } | 413 | } |
405 | 414 | ||
406 | /* manually resume the ports we suspended during bus_suspend() */ | 415 | /* manually resume the ports we suspended during bus_suspend() */ |
@@ -421,6 +430,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
421 | spin_unlock_irq(&ehci->lock); | 430 | spin_unlock_irq(&ehci->lock); |
422 | msleep(20); | 431 | msleep(20); |
423 | spin_lock_irq(&ehci->lock); | 432 | spin_lock_irq(&ehci->lock); |
433 | if (ehci->shutdown) | ||
434 | goto shutdown; | ||
424 | } | 435 | } |
425 | 436 | ||
426 | i = HCS_N_PORTS (ehci->hcs_params); | 437 | i = HCS_N_PORTS (ehci->hcs_params); |
@@ -439,10 +450,18 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
439 | ehci_handover_companion_ports(ehci); | 450 | ehci_handover_companion_ports(ehci); |
440 | 451 | ||
441 | /* Now we can safely re-enable irqs */ | 452 | /* Now we can safely re-enable irqs */ |
453 | spin_lock_irq(&ehci->lock); | ||
454 | if (ehci->shutdown) | ||
455 | goto shutdown; | ||
442 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); | 456 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); |
443 | (void) ehci_readl(ehci, &ehci->regs->intr_enable); | 457 | (void) ehci_readl(ehci, &ehci->regs->intr_enable); |
458 | spin_unlock_irq(&ehci->lock); | ||
444 | 459 | ||
445 | return 0; | 460 | return 0; |
461 | |||
462 | shutdown: | ||
463 | spin_unlock_irq(&ehci->lock); | ||
464 | return -ESHUTDOWN; | ||
446 | } | 465 | } |
447 | 466 | ||
448 | #else | 467 | #else |