aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 327437af2122..3ea05936851f 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -615,8 +615,19 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
615 615
616static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) 616static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
617{ 617{
618 unsigned wait; 618 unsigned wait;
619 struct ehci_qh_hw *hw = qh->hw; 619 struct ehci_qh_hw *hw = qh->hw;
620 int rc;
621
622 /* If the QH isn't linked then there's nothing we can do
623 * unless we were called during a giveback, in which case
624 * qh_completions() has to deal with it.
625 */
626 if (qh->qh_state != QH_STATE_LINKED) {
627 if (qh->qh_state == QH_STATE_COMPLETING)
628 qh->needs_rescan = 1;
629 return;
630 }
620 631
621 qh_unlink_periodic (ehci, qh); 632 qh_unlink_periodic (ehci, qh);
622 633
@@ -636,6 +647,24 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
636 qh->qh_state = QH_STATE_IDLE; 647 qh->qh_state = QH_STATE_IDLE;
637 hw->hw_next = EHCI_LIST_END(ehci); 648 hw->hw_next = EHCI_LIST_END(ehci);
638 wmb (); 649 wmb ();
650
651 qh_completions(ehci, qh);
652
653 /* reschedule QH iff another request is queued */
654 if (!list_empty(&qh->qtd_list) &&
655 HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
656 rc = qh_schedule(ehci, qh);
657
658 /* An error here likely indicates handshake failure
659 * or no space left in the schedule. Neither fault
660 * should happen often ...
661 *
662 * FIXME kill the now-dysfunctional queued urbs
663 */
664 if (rc != 0)
665 ehci_err(ehci, "can't reschedule qh %p, err %d\n",
666 qh, rc);
667 }
639} 668}
640 669
641/*-------------------------------------------------------------------------*/ 670/*-------------------------------------------------------------------------*/
@@ -2213,7 +2242,8 @@ restart:
2213 type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); 2242 type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
2214 q = q.qh->qh_next; 2243 q = q.qh->qh_next;
2215 modified = qh_completions (ehci, temp.qh); 2244 modified = qh_completions (ehci, temp.qh);
2216 if (unlikely (list_empty (&temp.qh->qtd_list))) 2245 if (unlikely(list_empty(&temp.qh->qtd_list) ||
2246 temp.qh->needs_rescan))
2217 intr_deschedule (ehci, temp.qh); 2247 intr_deschedule (ehci, temp.qh);
2218 qh_put (temp.qh); 2248 qh_put (temp.qh);
2219 break; 2249 break;