aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2013-07-03 10:53:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-12 14:43:48 -0400
commit35371e4fbc3e1863a6e7a79b8c17c25cc96a1380 (patch)
treeae3963c8738008c603176eb0e86eb4dbe908f58a
parent85721d45261c4be684730c7509a59daa6cda30d8 (diff)
USB: EHCI: improve ehci_endpoint_disable
The patch does the below improvement: - think QH_STATE_COMPLETING as unlinking state since all URBs on the endpoint should be in unlinking or unlinked when doing endpoint_disable() - add "WARN_ON(!list_empty(&qh->qtd_list));" if qh->qh_state is QH_STATE_LINKED because there shouldn't be any active transfer in qh - when qh->qh_state is QH_STATE_LINKED, the QH(async or periodic) should be in its corresponding list, so the search through the async list isn't necessary. - unlink periodic QH to speed up unlinking if the QH is in linked state Basically, only the last one is related with this patchset because the assumption of "periodic qh self-unlinks on empty" isn't true any more when we introduce unlink-wait for periodic qh. Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ehci-hcd.c16
1 files changed, 6 insertions, 10 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7abf1ce3a670..387cedf2b698 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -942,7 +942,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
942{ 942{
943 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 943 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
944 unsigned long flags; 944 unsigned long flags;
945 struct ehci_qh *qh, *tmp; 945 struct ehci_qh *qh;
946 946
947 /* ASSERT: any requests/urbs are being unlinked */ 947 /* ASSERT: any requests/urbs are being unlinked */
948 /* ASSERT: nobody can be submitting urbs for this any more */ 948 /* ASSERT: nobody can be submitting urbs for this any more */
@@ -972,17 +972,13 @@ rescan:
972 qh->qh_state = QH_STATE_IDLE; 972 qh->qh_state = QH_STATE_IDLE;
973 switch (qh->qh_state) { 973 switch (qh->qh_state) {
974 case QH_STATE_LINKED: 974 case QH_STATE_LINKED:
975 case QH_STATE_COMPLETING: 975 WARN_ON(!list_empty(&qh->qtd_list));
976 for (tmp = ehci->async->qh_next.qh; 976 if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT)
977 tmp && tmp != qh;
978 tmp = tmp->qh_next.qh)
979 continue;
980 /* periodic qh self-unlinks on empty, and a COMPLETING qh
981 * may already be unlinked.
982 */
983 if (tmp)
984 start_unlink_async(ehci, qh); 977 start_unlink_async(ehci, qh);
978 else
979 start_unlink_intr(ehci, qh);
985 /* FALL THROUGH */ 980 /* FALL THROUGH */
981 case QH_STATE_COMPLETING: /* already in unlinking */
986 case QH_STATE_UNLINK: /* wait for hw to finish? */ 982 case QH_STATE_UNLINK: /* wait for hw to finish? */
987 case QH_STATE_UNLINK_WAIT: 983 case QH_STATE_UNLINK_WAIT:
988idle_timeout: 984idle_timeout: