Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[pandora-kernel.git] / drivers / usb / host / ehci-q.c
index fe99895..42abd0f 100644 (file)
@@ -315,7 +315,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        int                     stopped;
        unsigned                count = 0;
        u8                      state;
-       const __le32            halt = HALT_BIT(ehci);
        struct ehci_qh_hw       *hw = qh->hw;
 
        if (unlikely (list_empty (&qh->qtd_list)))
@@ -422,7 +421,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                        && !(qtd->hw_alt_next
                                                & EHCI_LIST_END(ehci))) {
                                stopped = 1;
-                               goto halt;
                        }
 
                /* stop scanning when we reach qtds the hc is using */
@@ -456,16 +454,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                 */
                                ehci_clear_tt_buffer(ehci, qh, urb, token);
                        }
-
-                       /* force halt for unlinked or blocked qh, so we'll
-                        * patch the qh later and so that completions can't
-                        * activate it while we "know" it's stopped.
-                        */
-                       if ((halt & hw->hw_token) == 0) {
-halt:
-                               hw->hw_token |= halt;
-                               wmb ();
-                       }
                }
 
                /* unless we already know the urb's status, collect qtd status
@@ -1259,24 +1247,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 static void scan_async (struct ehci_hcd *ehci)
 {
+       bool                    stopped;
        struct ehci_qh          *qh;
        enum ehci_timer_action  action = TIMER_IO_WATCHDOG;
 
        ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
        timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
+       stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
        qh = ehci->async->qh_next.qh;
        if (likely (qh != NULL)) {
                do {
                        /* clean any finished work for this qh */
-                       if (!list_empty (&qh->qtd_list)
-                                       && qh->stamp != ehci->stamp) {
+                       if (!list_empty(&qh->qtd_list) && (stopped ||
+                                       qh->stamp != ehci->stamp)) {
                                int temp;
 
                                /* unlinks could happen here; completion
                                 * reporting drops the lock.  rescan using
                                 * the latest schedule, but don't rescan
-                                * qhs we already finished (no looping).
+                                * qhs we already finished (no looping)
+                                * unless the controller is stopped.
                                 */
                                qh = qh_get (qh);
                                qh->stamp = ehci->stamp;
@@ -1297,9 +1288,9 @@ rescan:
                         */
                        if (list_empty(&qh->qtd_list)
                                        && qh->qh_state == QH_STATE_LINKED) {
-                               if (!ehci->reclaim
-                                       && ((ehci->stamp - qh->stamp) & 0x1fff)
-                                               >= (EHCI_SHRINK_FRAMES * 8))
+                               if (!ehci->reclaim && (stopped ||
+                                       ((ehci->stamp - qh->stamp) & 0x1fff)
+                                               >= EHCI_SHRINK_FRAMES * 8))
                                        start_unlink_async(ehci, qh);
                                else
                                        action = TIMER_ASYNC_SHRINK;