aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-08-19 12:22:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:37 -0400
commit3a44494e233c0fdd818d485cfea8998500543589 (patch)
tree04b66268a2efc1236d3f9e477a04dc2d3ec87582 /drivers/usb/host/ehci-hcd.c
parent04c4ab17c7c39603c5017bee20d3b8ccb2f19816 (diff)
USB: EHCI: rescan the queue after an unlink
This patch (as1280) fixes an obscure bug in ehci-hcd's dequeuing logic for async URBs. If a later URB is unlinked and the completion routine unlinks an earlier URB, then the earlier URB won't be given back in a timely manner because the endpoint queue isn't rescanned as it should be. Similar bugs occur if an endpoint is reset or a halt is cleared while a completion routine is running, because the subroutines don't test for the COMPLETING state. All these problems are solved by adding a new needs_rescan flag to the ehci_qh structure. If the flag is set while scanning through an idle QH, the scan will be repeated. If the QH isn't idle then an unlink cycle will be initiated, and the proper action will be taken when it becomes idle. Also, an unnecessary test is removed from qh_link_async(): That routine is never called if the QH's state isn't IDLE. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6887aac5e73d..d7e85b6231b3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -863,12 +863,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
863 if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim) 863 if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
864 end_unlink_async(ehci); 864 end_unlink_async(ehci);
865 865
866 /* if it's not linked then there's nothing to do */ 866 /* If the QH isn't linked then there's nothing we can do
867 if (qh->qh_state != QH_STATE_LINKED) 867 * unless we were called during a giveback, in which case
868 ; 868 * qh_completions() has to deal with it.
869 */
870 if (qh->qh_state != QH_STATE_LINKED) {
871 if (qh->qh_state == QH_STATE_COMPLETING)
872 qh->needs_rescan = 1;
873 return;
874 }
869 875
870 /* defer till later if busy */ 876 /* defer till later if busy */
871 else if (ehci->reclaim) { 877 if (ehci->reclaim) {
872 struct ehci_qh *last; 878 struct ehci_qh *last;
873 879
874 for (last = ehci->reclaim; 880 for (last = ehci->reclaim;
@@ -1001,6 +1007,7 @@ rescan:
1001 qh->qh_state = QH_STATE_IDLE; 1007 qh->qh_state = QH_STATE_IDLE;
1002 switch (qh->qh_state) { 1008 switch (qh->qh_state) {
1003 case QH_STATE_LINKED: 1009 case QH_STATE_LINKED:
1010 case QH_STATE_COMPLETING:
1004 for (tmp = ehci->async->qh_next.qh; 1011 for (tmp = ehci->async->qh_next.qh;
1005 tmp && tmp != qh; 1012 tmp && tmp != qh;
1006 tmp = tmp->qh_next.qh) 1013 tmp = tmp->qh_next.qh)
@@ -1065,7 +1072,8 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1065 usb_settoggle(qh->dev, epnum, is_out, 0); 1072 usb_settoggle(qh->dev, epnum, is_out, 0);
1066 if (!list_empty(&qh->qtd_list)) { 1073 if (!list_empty(&qh->qtd_list)) {
1067 WARN_ONCE(1, "clear_halt for a busy endpoint\n"); 1074 WARN_ONCE(1, "clear_halt for a busy endpoint\n");
1068 } else if (qh->qh_state == QH_STATE_LINKED) { 1075 } else if (qh->qh_state == QH_STATE_LINKED ||
1076 qh->qh_state == QH_STATE_COMPLETING) {
1069 1077
1070 /* The toggle value in the QH can't be updated 1078 /* The toggle value in the QH can't be updated
1071 * while the QH is active. Unlink it now; 1079 * while the QH is active. Unlink it now;