aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:23:16 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:56:48 -0400
commit43fe3a99d9caf10b25f9c596e9854cdae30db418 (patch)
tree596812dcd61ba9cbffe0e837d53dd3a2232ad214 /drivers/usb/host/ehci-hub.c
parentc4f3476436f7452b97c8accb5dd7d53219a11a3f (diff)
USB: EHCI: resolve some unlikely races
This patch (as1589) resolves some unlikely races involving system shutdown or controller death in ehci-hcd: Shutdown races with both root-hub resume and controller resume. Controller death races with root-hub suspend. A new bitflag is added to indicate that the controller has been shut down (whether for system shutdown or because it died). Tests are added in the suspend and resume pathways to avoid reactivating the controller after any sort of shutdown. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c27
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