diff options
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 35 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 19 |
2 files changed, 34 insertions, 20 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) |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3192f683f807..1976b1b3778c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); | 93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); |
94 | qh->hw_alt_next = EHCI_LIST_END(ehci); | 94 | qh->hw_alt_next = EHCI_LIST_END(ehci); |
95 | 95 | ||
96 | /* Except for control endpoints, we make hardware maintain data | ||
97 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | ||
98 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | ||
99 | * ever clear it. | ||
100 | */ | ||
101 | if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { | ||
102 | unsigned is_out, epnum; | ||
103 | |||
104 | is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); | ||
105 | epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; | ||
106 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | ||
107 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | ||
108 | usb_settoggle (qh->dev, epnum, is_out, 1); | ||
109 | } | ||
110 | } | ||
111 | |||
96 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | 112 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ |
97 | wmb (); | 113 | wmb (); |
98 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); | 114 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
@@ -834,6 +850,7 @@ done: | |||
834 | qh->qh_state = QH_STATE_IDLE; | 850 | qh->qh_state = QH_STATE_IDLE; |
835 | qh->hw_info1 = cpu_to_hc32(ehci, info1); | 851 | qh->hw_info1 = cpu_to_hc32(ehci, info1); |
836 | qh->hw_info2 = cpu_to_hc32(ehci, info2); | 852 | qh->hw_info2 = cpu_to_hc32(ehci, info2); |
853 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | ||
837 | qh_refresh (ehci, qh); | 854 | qh_refresh (ehci, qh); |
838 | return qh; | 855 | return qh; |
839 | } | 856 | } |
@@ -864,7 +881,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
864 | } | 881 | } |
865 | } | 882 | } |
866 | 883 | ||
867 | /* clear halt and maybe recover from silicon quirk */ | 884 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ |
868 | if (qh->qh_state == QH_STATE_IDLE) | 885 | if (qh->qh_state == QH_STATE_IDLE) |
869 | qh_refresh (ehci, qh); | 886 | qh_refresh (ehci, qh); |
870 | 887 | ||