diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2b72473544d3..7d03549c3339 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1003,6 +1003,8 @@ idle_timeout: | |||
1003 | schedule_timeout_uninterruptible(1); | 1003 | schedule_timeout_uninterruptible(1); |
1004 | goto rescan; | 1004 | goto rescan; |
1005 | case QH_STATE_IDLE: /* fully unlinked */ | 1005 | case QH_STATE_IDLE: /* fully unlinked */ |
1006 | if (qh->clearing_tt) | ||
1007 | goto idle_timeout; | ||
1006 | if (list_empty (&qh->qtd_list)) { | 1008 | if (list_empty (&qh->qtd_list)) { |
1007 | qh_put (qh); | 1009 | qh_put (qh); |
1008 | break; | 1010 | break; |
@@ -1030,12 +1032,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1032 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1031 | struct ehci_qh *qh; | 1033 | struct ehci_qh *qh; |
1032 | int eptype = usb_endpoint_type(&ep->desc); | 1034 | int eptype = usb_endpoint_type(&ep->desc); |
1035 | int epnum = usb_endpoint_num(&ep->desc); | ||
1036 | int is_out = usb_endpoint_dir_out(&ep->desc); | ||
1037 | unsigned long flags; | ||
1033 | 1038 | ||
1034 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | 1039 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) |
1035 | return; | 1040 | return; |
1036 | 1041 | ||
1037 | rescan: | 1042 | spin_lock_irqsave(&ehci->lock, flags); |
1038 | spin_lock_irq(&ehci->lock); | ||
1039 | qh = ep->hcpriv; | 1043 | qh = ep->hcpriv; |
1040 | 1044 | ||
1041 | /* For Bulk and Interrupt endpoints we maintain the toggle state | 1045 | /* For Bulk and Interrupt endpoints we maintain the toggle state |
@@ -1044,29 +1048,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1044 | * the toggle bit in the QH. | 1048 | * the toggle bit in the QH. |
1045 | */ | 1049 | */ |
1046 | if (qh) { | 1050 | if (qh) { |
1051 | usb_settoggle(qh->dev, epnum, is_out, 0); | ||
1047 | if (!list_empty(&qh->qtd_list)) { | 1052 | if (!list_empty(&qh->qtd_list)) { |
1048 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | 1053 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); |
1049 | } else if (qh->qh_state == QH_STATE_IDLE) { | 1054 | } else if (qh->qh_state == QH_STATE_LINKED) { |
1050 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | 1055 | |
1051 | } else { | 1056 | /* The toggle value in the QH can't be updated |
1052 | /* It's not safe to write into the overlay area | 1057 | * while the QH is active. Unlink it now; |
1053 | * while the QH is active. Unlink it first and | 1058 | * re-linking will call qh_refresh(). |
1054 | * wait for the unlink to complete. | ||
1055 | */ | 1059 | */ |
1056 | if (qh->qh_state == QH_STATE_LINKED) { | 1060 | if (eptype == USB_ENDPOINT_XFER_BULK) { |
1057 | if (eptype == USB_ENDPOINT_XFER_BULK) { | 1061 | unlink_async(ehci, qh); |
1058 | unlink_async(ehci, qh); | 1062 | } else { |
1059 | } else { | 1063 | intr_deschedule(ehci, qh); |
1060 | intr_deschedule(ehci, qh); | 1064 | (void) qh_schedule(ehci, qh); |
1061 | (void) qh_schedule(ehci, qh); | ||
1062 | } | ||
1063 | } | 1065 | } |
1064 | spin_unlock_irq(&ehci->lock); | ||
1065 | schedule_timeout_uninterruptible(1); | ||
1066 | goto rescan; | ||
1067 | } | 1066 | } |
1068 | } | 1067 | } |
1069 | spin_unlock_irq(&ehci->lock); | 1068 | spin_unlock_irqrestore(&ehci->lock, flags); |
1070 | } | 1069 | } |
1071 | 1070 | ||
1072 | static int ehci_get_frame (struct usb_hcd *hcd) | 1071 | static int ehci_get_frame (struct usb_hcd *hcd) |