aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-hcd.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a02dcff5eb21..369a8a5ea7bb 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -331,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
331 &ehci->regs->port_status[port]); 331 &ehci->regs->port_status[port]);
332} 332}
333 333
334/* ehci_shutdown kick in for silicon on any bus (not just pci, etc). 334/*
335 * This forcibly disables dma and IRQs, helping kexec and other cases 335 * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
336 * where the next system software may expect clean state. 336 * Should be called with ehci->lock held.
337 */ 337 */
338static void 338static void ehci_silence_controller(struct ehci_hcd *ehci)
339ehci_shutdown (struct usb_hcd *hcd)
340{ 339{
341 struct ehci_hcd *ehci; 340 ehci_halt(ehci);
342
343 ehci = hcd_to_ehci (hcd);
344 (void) ehci_halt (ehci);
345 ehci_turn_off_all_ports(ehci); 341 ehci_turn_off_all_ports(ehci);
346 342
347 /* make BIOS/etc use companion controller during reboot */ 343 /* make BIOS/etc use companion controller during reboot */
@@ -351,6 +347,22 @@ ehci_shutdown (struct usb_hcd *hcd)
351 ehci_readl(ehci, &ehci->regs->configured_flag); 347 ehci_readl(ehci, &ehci->regs->configured_flag);
352} 348}
353 349
350/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
351 * This forcibly disables dma and IRQs, helping kexec and other cases
352 * where the next system software may expect clean state.
353 */
354static void ehci_shutdown(struct usb_hcd *hcd)
355{
356 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
357
358 del_timer_sync(&ehci->watchdog);
359 del_timer_sync(&ehci->iaa_watchdog);
360
361 spin_lock_irq(&ehci->lock);
362 ehci_silence_controller(ehci);
363 spin_unlock_irq(&ehci->lock);
364}
365
354static void ehci_port_power (struct ehci_hcd *ehci, int is_on) 366static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
355{ 367{
356 unsigned port; 368 unsigned port;
@@ -401,15 +413,15 @@ static void ehci_work (struct ehci_hcd *ehci)
401 timer_action (ehci, TIMER_IO_WATCHDOG); 413 timer_action (ehci, TIMER_IO_WATCHDOG);
402} 414}
403 415
416/*
417 * Called when the ehci_hcd module is removed.
418 */
404static void ehci_stop (struct usb_hcd *hcd) 419static void ehci_stop (struct usb_hcd *hcd)
405{ 420{
406 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 421 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
407 422
408 ehci_dbg (ehci, "stop\n"); 423 ehci_dbg (ehci, "stop\n");
409 424
410 /* Turn off port power on all root hub ports. */
411 ehci_port_power (ehci, 0);
412
413 /* no more interrupts ... */ 425 /* no more interrupts ... */
414 del_timer_sync (&ehci->watchdog); 426 del_timer_sync (&ehci->watchdog);
415 del_timer_sync(&ehci->iaa_watchdog); 427 del_timer_sync(&ehci->iaa_watchdog);
@@ -418,13 +430,10 @@ static void ehci_stop (struct usb_hcd *hcd)
418 if (HC_IS_RUNNING (hcd->state)) 430 if (HC_IS_RUNNING (hcd->state))
419 ehci_quiesce (ehci); 431 ehci_quiesce (ehci);
420 432
433 ehci_silence_controller(ehci);
421 ehci_reset (ehci); 434 ehci_reset (ehci);
422 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
423 spin_unlock_irq(&ehci->lock); 435 spin_unlock_irq(&ehci->lock);
424 436
425 /* let companion controllers work when we aren't */
426 ehci_writel(ehci, 0, &ehci->regs->configured_flag);
427
428 remove_companion_file(ehci); 437 remove_companion_file(ehci);
429 remove_debug_files (ehci); 438 remove_debug_files (ehci);
430 439