aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-09-12 07:02:26 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-09-12 07:02:26 -0400
commitddd559b13f6d2fe3ad68c4b3f5235fd3c2eae4e3 (patch)
treed827bca3fc825a0ac33efbcd493713be40fcc812 /drivers/usb/host/ehci-hcd.c
parentcf7a2b4fb6a9b86779930a0a123b0df41aa9208f (diff)
parentf17a1f06d2fa93f4825be572622eb02c4894db4e (diff)
Merge branch 'devel-stable' into devel
Conflicts: MAINTAINERS arch/arm/mm/fault.c
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c37
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
1072static int ehci_get_frame (struct usb_hcd *hcd) 1071static int ehci_get_frame (struct usb_hcd *hcd)