diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-05-27 18:21:56 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:46 -0400 |
commit | b18ffd49e86102a9ed0a1cc83fdafe3891e844e5 (patch) | |
tree | 78b60211d13839baaa92128e1b583dc12139392c /drivers/usb/host/ehci-hcd.c | |
parent | 5effabbe9e6e0089f7afdde35cb51e8c8b4cf6bc (diff) |
USB: EHCI: update toggle state for linked QHs
This patch (as1245) fixes a bug in ehci-hcd. When an URB is queued
for an endpoint whose QH is already in the LINKED state, the QH
doesn't get refreshed. As a result, if usb_clear_halt() was called
during the time that the QH was linked but idle, the data toggle value
in the QH doesn't get reset.
The symptom is that after a clear_halt, data gets lost and transfers
time out. This problem is starting to show up now because the
"ehci-hcd unlink speedups" patch causes QHs with no queued URBs to
remain linked for a suitable time.
The patch utilizes the new endpoint_reset mechanism to fix the
problem. When an endpoint is reset, the new method forcibly unlinks
the QH (if necessary) and safely updates the toggle value. This
allows qh_update() to be simplified and avoids using usb_device's
toggle bits in a rather unintuitive way.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
Tested-by: David <david@unsolicited.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.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a2ca9cbf2809..2b72473544d3 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1024,6 +1024,51 @@ done: | |||
1024 | return; | 1024 | return; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | static void | ||
1028 | ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | ||
1029 | { | ||
1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
1031 | struct ehci_qh *qh; | ||
1032 | int eptype = usb_endpoint_type(&ep->desc); | ||
1033 | |||
1034 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | ||
1035 | return; | ||
1036 | |||
1037 | rescan: | ||
1038 | spin_lock_irq(&ehci->lock); | ||
1039 | qh = ep->hcpriv; | ||
1040 | |||
1041 | /* For Bulk and Interrupt endpoints we maintain the toggle state | ||
1042 | * in the hardware; the toggle bits in udev aren't used at all. | ||
1043 | * When an endpoint is reset by usb_clear_halt() we must reset | ||
1044 | * the toggle bit in the QH. | ||
1045 | */ | ||
1046 | if (qh) { | ||
1047 | if (!list_empty(&qh->qtd_list)) { | ||
1048 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | ||
1049 | } else if (qh->qh_state == QH_STATE_IDLE) { | ||
1050 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | ||
1051 | } else { | ||
1052 | /* It's not safe to write into the overlay area | ||
1053 | * while the QH is active. Unlink it first and | ||
1054 | * wait for the unlink to complete. | ||
1055 | */ | ||
1056 | if (qh->qh_state == QH_STATE_LINKED) { | ||
1057 | if (eptype == USB_ENDPOINT_XFER_BULK) { | ||
1058 | unlink_async(ehci, qh); | ||
1059 | } else { | ||
1060 | intr_deschedule(ehci, qh); | ||
1061 | (void) qh_schedule(ehci, qh); | ||
1062 | } | ||
1063 | } | ||
1064 | spin_unlock_irq(&ehci->lock); | ||
1065 | schedule_timeout_uninterruptible(1); | ||
1066 | goto rescan; | ||
1067 | } | ||
1068 | } | ||
1069 | spin_unlock_irq(&ehci->lock); | ||
1070 | } | ||
1071 | |||
1027 | static int ehci_get_frame (struct usb_hcd *hcd) | 1072 | static int ehci_get_frame (struct usb_hcd *hcd) |
1028 | { | 1073 | { |
1029 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 1074 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |