aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:21:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:50:14 -0400
commitc0c53dbc32ea05a1e1dd9dba4772327da9a11750 (patch)
treec292857a1d2c6e1c4b16bb08649df71fd92178e2 /drivers/usb/host/ehci-hcd.c
parent2f5bb665ba7a14c5842fa2e1cde2be039843a2a2 (diff)
USB: EHCI: add new root-hub state: STOPPING
This patch (as1571) adds a new state for ehci-hcd's root hubs: EHCI_RH_STOPPING. This value is used at times when the root hub is being stopped and we don't know whether or not the hardware has finished all its DMA yet. Although the purpose may not be apparent, this distinction will come in useful later on. Future patches will avoid actions that depend on the root hub being operational (like turning on the async or periodic schedules) when they see the state is EHCI_RH_STOPPING. 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-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8b75e4279a47..bc94822f4c5d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -357,10 +357,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
357{ 357{
358 u32 temp; 358 u32 temp;
359 359
360#ifdef DEBUG
361 if (ehci->rh_state != EHCI_RH_RUNNING) 360 if (ehci->rh_state != EHCI_RH_RUNNING)
362 BUG (); 361 return;
363#endif
364 362
365 /* wait for any schedule enables/disables to take effect */ 363 /* wait for any schedule enables/disables to take effect */
366 temp = (ehci->command << 10) & (STS_ASS | STS_PSS); 364 temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
@@ -494,6 +492,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
494 del_timer_sync(&ehci->iaa_watchdog); 492 del_timer_sync(&ehci->iaa_watchdog);
495 493
496 spin_lock_irq(&ehci->lock); 494 spin_lock_irq(&ehci->lock);
495 ehci->rh_state = EHCI_RH_STOPPING;
497 ehci_silence_controller(ehci); 496 ehci_silence_controller(ehci);
498 spin_unlock_irq(&ehci->lock); 497 spin_unlock_irq(&ehci->lock);
499} 498}
@@ -562,8 +561,7 @@ static void ehci_stop (struct usb_hcd *hcd)
562 del_timer_sync(&ehci->iaa_watchdog); 561 del_timer_sync(&ehci->iaa_watchdog);
563 562
564 spin_lock_irq(&ehci->lock); 563 spin_lock_irq(&ehci->lock);
565 if (ehci->rh_state == EHCI_RH_RUNNING) 564 ehci_quiesce(ehci);
566 ehci_quiesce (ehci);
567 565
568 ehci_silence_controller(ehci); 566 ehci_silence_controller(ehci);
569 ehci_reset (ehci); 567 ehci_reset (ehci);
@@ -951,6 +949,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
951 /* PCI errors [4.15.2.4] */ 949 /* PCI errors [4.15.2.4] */
952 if (unlikely ((status & STS_FATAL) != 0)) { 950 if (unlikely ((status & STS_FATAL) != 0)) {
953 ehci_err(ehci, "fatal error\n"); 951 ehci_err(ehci, "fatal error\n");
952 ehci->rh_state = EHCI_RH_STOPPING;
954 dbg_cmd(ehci, "fatal", cmd); 953 dbg_cmd(ehci, "fatal", cmd);
955 dbg_status(ehci, "fatal", status); 954 dbg_status(ehci, "fatal", status);
956 ehci_halt(ehci); 955 ehci_halt(ehci);
@@ -1026,7 +1025,7 @@ static int ehci_urb_enqueue (
1026static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) 1025static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
1027{ 1026{
1028 /* failfast */ 1027 /* failfast */
1029 if (ehci->rh_state != EHCI_RH_RUNNING && ehci->async_unlink) 1028 if (ehci->rh_state < EHCI_RH_RUNNING && ehci->async_unlink)
1030 end_unlink_async(ehci); 1029 end_unlink_async(ehci);
1031 1030
1032 /* If the QH isn't linked then there's nothing we can do 1031 /* If the QH isn't linked then there's nothing we can do
@@ -1148,7 +1147,7 @@ rescan:
1148 goto idle_timeout; 1147 goto idle_timeout;
1149 } 1148 }
1150 1149
1151 if (ehci->rh_state != EHCI_RH_RUNNING) 1150 if (ehci->rh_state < EHCI_RH_RUNNING)
1152 qh->qh_state = QH_STATE_IDLE; 1151 qh->qh_state = QH_STATE_IDLE;
1153 switch (qh->qh_state) { 1152 switch (qh->qh_state) {
1154 case QH_STATE_LINKED: 1153 case QH_STATE_LINKED: