diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-06-11 14:56:22 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-07-12 18:16:36 -0400 |
commit | a455212d19d312f6a99b3a4a86fb79fb91dd76c7 (patch) | |
tree | cfd1cf74b6e51623813be2ec65e42f3756598252 /drivers/usb/host/ehci-hcd.c | |
parent | 9525dcb30f5f412748f58a0537002ea47cfe55de (diff) |
USB: EHCI: update toggle state for linked QHs
This is an update to the "usb-ehci-update-toggle-state-for-linked-qhs"
patch. Since an HCD's endpoint_reset method can be called in
interrupt context, it mustn't assume that interrupts are enabled or
that it can sleep.
So we revert to the original way of refreshing QHs' toggle bits. Now
the endpoint_reset method merely clears the toggle flag in the device
structure (as was done before) and starts an async QH unlink. When the
QH is linked again, after the unlink finishes and an URB is queued,
the qh_refresh() routine will update the QH's toggle bit.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: David <david@unsolicited.net>
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.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2b72473544d3..99c75603ec87 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1030,12 +1030,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1031 | struct ehci_qh *qh; | 1031 | struct ehci_qh *qh; |
1032 | int eptype = usb_endpoint_type(&ep->desc); | 1032 | int eptype = usb_endpoint_type(&ep->desc); |
1033 | int epnum = usb_endpoint_num(&ep->desc); | ||
1034 | int is_out = usb_endpoint_dir_out(&ep->desc); | ||
1035 | unsigned long flags; | ||
1033 | 1036 | ||
1034 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | 1037 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) |
1035 | return; | 1038 | return; |
1036 | 1039 | ||
1037 | rescan: | 1040 | spin_lock_irqsave(&ehci->lock, flags); |
1038 | spin_lock_irq(&ehci->lock); | ||
1039 | qh = ep->hcpriv; | 1041 | qh = ep->hcpriv; |
1040 | 1042 | ||
1041 | /* For Bulk and Interrupt endpoints we maintain the toggle state | 1043 | /* For Bulk and Interrupt endpoints we maintain the toggle state |
@@ -1044,29 +1046,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1044 | * the toggle bit in the QH. | 1046 | * the toggle bit in the QH. |
1045 | */ | 1047 | */ |
1046 | if (qh) { | 1048 | if (qh) { |
1049 | usb_settoggle(qh->dev, epnum, is_out, 0); | ||
1047 | if (!list_empty(&qh->qtd_list)) { | 1050 | if (!list_empty(&qh->qtd_list)) { |
1048 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | 1051 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); |
1049 | } else if (qh->qh_state == QH_STATE_IDLE) { | 1052 | } else if (qh->qh_state == QH_STATE_LINKED) { |
1050 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | 1053 | |
1051 | } else { | 1054 | /* The toggle value in the QH can't be updated |
1052 | /* It's not safe to write into the overlay area | 1055 | * while the QH is active. Unlink it now; |
1053 | * while the QH is active. Unlink it first and | 1056 | * re-linking will call qh_refresh(). |
1054 | * wait for the unlink to complete. | ||
1055 | */ | 1057 | */ |
1056 | if (qh->qh_state == QH_STATE_LINKED) { | 1058 | if (eptype == USB_ENDPOINT_XFER_BULK) { |
1057 | if (eptype == USB_ENDPOINT_XFER_BULK) { | 1059 | unlink_async(ehci, qh); |
1058 | unlink_async(ehci, qh); | 1060 | } else { |
1059 | } else { | 1061 | intr_deschedule(ehci, qh); |
1060 | intr_deschedule(ehci, qh); | 1062 | (void) qh_schedule(ehci, qh); |
1061 | (void) qh_schedule(ehci, qh); | ||
1062 | } | ||
1063 | } | 1063 | } |
1064 | spin_unlock_irq(&ehci->lock); | ||
1065 | schedule_timeout_uninterruptible(1); | ||
1066 | goto rescan; | ||
1067 | } | 1064 | } |
1068 | } | 1065 | } |
1069 | spin_unlock_irq(&ehci->lock); | 1066 | spin_unlock_irqrestore(&ehci->lock, flags); |
1070 | } | 1067 | } |
1071 | 1068 | ||
1072 | static int ehci_get_frame (struct usb_hcd *hcd) | 1069 | static int ehci_get_frame (struct usb_hcd *hcd) |