diff options
author | Ming Lei <ming.lei@canonical.com> | 2013-07-03 22:53:09 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-12 11:43:48 -0700 |
commit | 35371e4fbc3e1863a6e7a79b8c17c25cc96a1380 (patch) | |
tree | ae3963c8738008c603176eb0e86eb4dbe908f58a /drivers/usb | |
parent | 85721d45261c4be684730c7509a59daa6cda30d8 (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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7abf1ce3a67..387cedf2b69 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) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); unsigned long flags; - struct ehci_qh *qh, *tmp; + struct ehci_qh *qh; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ @@ -972,17 +972,13 @@ rescan: qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - for (tmp = ehci->async->qh_next.qh; - tmp && tmp != qh; - tmp = tmp->qh_next.qh) - continue; - /* periodic qh self-unlinks on empty, and a COMPLETING qh - * may already be unlinked. - */ - if (tmp) + WARN_ON(!list_empty(&qh->qtd_list)); + if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT) start_unlink_async(ehci, qh); + else + start_unlink_intr(ehci, qh); /* FALL THROUGH */ + case QH_STATE_COMPLETING: /* already in unlinking */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: idle_timeout: |