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:44 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:37 -0400
commita448c9d8c58ff7d3f8cc2a8f835065460099b22d (patch)
tree418610891b8dc271bbd798ff5c47d921be5f806d /drivers/usb/host/ehci-hcd.c
parent3a44494e233c0fdd818d485cfea8998500543589 (diff)
USB: EHCI: change deschedule logic for interrupt QHs
This patch (as1281) changes the way ehci-hcd deschedules interrupt QHs, copying the approach used for async QHs. The caller is no longer responsible for rescheduling the QH if its queue is non-empty; instead the reschedule is done directly by intr_deschedule(), after calling qh_completions(). This is exactly the same as how end_unlink_async() works. ehci_urb_dequeue() and intr_deschedule() now correctly handle the case where they are called while another interrupt URB for the same QH is being given back. This was a surprisingly large blind spot. And scan_periodic() now respects the new needs_rescan flag. 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.c26
1 files changed, 4 insertions, 22 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d7e85b6231b3..4f89d7ffd53a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -934,8 +934,9 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
934 break; 934 break;
935 switch (qh->qh_state) { 935 switch (qh->qh_state) {
936 case QH_STATE_LINKED: 936 case QH_STATE_LINKED:
937 case QH_STATE_COMPLETING:
937 intr_deschedule (ehci, qh); 938 intr_deschedule (ehci, qh);
938 /* FALL THROUGH */ 939 break;
939 case QH_STATE_IDLE: 940 case QH_STATE_IDLE:
940 qh_completions (ehci, qh); 941 qh_completions (ehci, qh);
941 break; 942 break;
@@ -944,23 +945,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
944 qh, qh->qh_state); 945 qh, qh->qh_state);
945 goto done; 946 goto done;
946 } 947 }
947
948 /* reschedule QH iff another request is queued */
949 if (!list_empty (&qh->qtd_list)
950 && HC_IS_RUNNING (hcd->state)) {
951 rc = qh_schedule(ehci, qh);
952
953 /* An error here likely indicates handshake failure
954 * or no space left in the schedule. Neither fault
955 * should happen often ...
956 *
957 * FIXME kill the now-dysfunctional queued urbs
958 */
959 if (rc != 0)
960 ehci_err(ehci,
961 "can't reschedule qh %p, err %d",
962 qh, rc);
963 }
964 break; 948 break;
965 949
966 case PIPE_ISOCHRONOUS: 950 case PIPE_ISOCHRONOUS:
@@ -1079,12 +1063,10 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1079 * while the QH is active. Unlink it now; 1063 * while the QH is active. Unlink it now;
1080 * re-linking will call qh_refresh(). 1064 * re-linking will call qh_refresh().
1081 */ 1065 */
1082 if (eptype == USB_ENDPOINT_XFER_BULK) { 1066 if (eptype == USB_ENDPOINT_XFER_BULK)
1083 unlink_async(ehci, qh); 1067 unlink_async(ehci, qh);
1084 } else { 1068 else
1085 intr_deschedule(ehci, qh); 1069 intr_deschedule(ehci, qh);
1086 (void) qh_schedule(ehci, qh);
1087 }
1088 } 1070 }
1089 } 1071 }
1090 spin_unlock_irqrestore(&ehci->lock, flags); 1072 spin_unlock_irqrestore(&ehci->lock, flags);