aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r--drivers/usb/host/ehci-q.c91
1 files changed, 68 insertions, 23 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 68bf81e982d2..e3d2b627bfb3 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -139,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
139 139
140/*-------------------------------------------------------------------------*/ 140/*-------------------------------------------------------------------------*/
141 141
142static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
143
144static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
145 struct usb_host_endpoint *ep)
146{
147 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
148 struct ehci_qh *qh = ep->hcpriv;
149 unsigned long flags;
150
151 spin_lock_irqsave(&ehci->lock, flags);
152 qh->clearing_tt = 0;
153 if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
154 && HC_IS_RUNNING(hcd->state))
155 qh_link_async(ehci, qh);
156 spin_unlock_irqrestore(&ehci->lock, flags);
157}
158
159static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
160 struct urb *urb, u32 token)
161{
162
163 /* If an async split transaction gets an error or is unlinked,
164 * the TT buffer may be left in an indeterminate state. We
165 * have to clear the TT buffer.
166 *
167 * Note: this routine is never called for Isochronous transfers.
168 */
169 if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
170#ifdef DEBUG
171 struct usb_device *tt = urb->dev->tt->hub;
172 dev_dbg(&tt->dev,
173 "clear tt buffer port %d, a%d ep%d t%08x\n",
174 urb->dev->ttport, urb->dev->devnum,
175 usb_pipeendpoint(urb->pipe), token);
176#endif /* DEBUG */
177 if (!ehci_is_TDI(ehci)
178 || urb->dev->tt->hub !=
179 ehci_to_hcd(ehci)->self.root_hub) {
180 if (usb_hub_clear_tt_buffer(urb) == 0)
181 qh->clearing_tt = 1;
182 } else {
183
184 /* REVISIT ARC-derived cores don't clear the root
185 * hub TT buffer in this way...
186 */
187 }
188 }
189}
190
142static int qtd_copy_status ( 191static int qtd_copy_status (
143 struct ehci_hcd *ehci, 192 struct ehci_hcd *ehci,
144 struct urb *urb, 193 struct urb *urb,
@@ -195,28 +244,6 @@ static int qtd_copy_status (
195 usb_pipeendpoint (urb->pipe), 244 usb_pipeendpoint (urb->pipe),
196 usb_pipein (urb->pipe) ? "in" : "out", 245 usb_pipein (urb->pipe) ? "in" : "out",
197 token, status); 246 token, status);
198
199 /* if async CSPLIT failed, try cleaning out the TT buffer */
200 if (status != -EPIPE
201 && urb->dev->tt
202 && !usb_pipeint(urb->pipe)
203 && ((token & QTD_STS_MMF) != 0
204 || QTD_CERR(token) == 0)
205 && (!ehci_is_TDI(ehci)
206 || urb->dev->tt->hub !=
207 ehci_to_hcd(ehci)->self.root_hub)) {
208#ifdef DEBUG
209 struct usb_device *tt = urb->dev->tt->hub;
210 dev_dbg (&tt->dev,
211 "clear tt buffer port %d, a%d ep%d t%08x\n",
212 urb->dev->ttport, urb->dev->devnum,
213 usb_pipeendpoint (urb->pipe), token);
214#endif /* DEBUG */
215 /* REVISIT ARC-derived cores don't clear the root
216 * hub TT buffer in this way...
217 */
218 usb_hub_clear_tt_buffer(urb);
219 }
220 } 247 }
221 248
222 return status; 249 return status;
@@ -407,9 +434,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
407 /* qh unlinked; token in overlay may be most current */ 434 /* qh unlinked; token in overlay may be most current */
408 if (state == QH_STATE_IDLE 435 if (state == QH_STATE_IDLE
409 && cpu_to_hc32(ehci, qtd->qtd_dma) 436 && cpu_to_hc32(ehci, qtd->qtd_dma)
410 == qh->hw_current) 437 == qh->hw_current) {
411 token = hc32_to_cpu(ehci, qh->hw_token); 438 token = hc32_to_cpu(ehci, qh->hw_token);
412 439
440 /* An unlink may leave an incomplete
441 * async transaction in the TT buffer.
442 * We have to clear it.
443 */
444 ehci_clear_tt_buffer(ehci, qh, urb, token);
445 }
446
413 /* force halt for unlinked or blocked qh, so we'll 447 /* force halt for unlinked or blocked qh, so we'll
414 * patch the qh later and so that completions can't 448 * patch the qh later and so that completions can't
415 * activate it while we "know" it's stopped. 449 * activate it while we "know" it's stopped.
@@ -435,6 +469,13 @@ halt:
435 && (qtd->hw_alt_next 469 && (qtd->hw_alt_next
436 & EHCI_LIST_END(ehci))) 470 & EHCI_LIST_END(ehci)))
437 last_status = -EINPROGRESS; 471 last_status = -EINPROGRESS;
472
473 /* As part of low/full-speed endpoint-halt processing
474 * we must clear the TT buffer (11.17.5).
475 */
476 if (unlikely(last_status != -EINPROGRESS &&
477 last_status != -EREMOTEIO))
478 ehci_clear_tt_buffer(ehci, qh, urb, token);
438 } 479 }
439 480
440 /* if we're removing something not at the queue head, 481 /* if we're removing something not at the queue head,
@@ -864,6 +905,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
864 __hc32 dma = QH_NEXT(ehci, qh->qh_dma); 905 __hc32 dma = QH_NEXT(ehci, qh->qh_dma);
865 struct ehci_qh *head; 906 struct ehci_qh *head;
866 907
908 /* Don't link a QH if there's a Clear-TT-Buffer pending */
909 if (unlikely(qh->clearing_tt))
910 return;
911
867 /* (re)start the async schedule? */ 912 /* (re)start the async schedule? */
868 head = ehci->async; 913 head = ehci->async;
869 timer_action_done (ehci, TIMER_ASYNC_OFF); 914 timer_action_done (ehci, TIMER_ASYNC_OFF);