aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-hcd.c18
-rw-r--r--drivers/usb/host/ehci-q.c43
-rw-r--r--drivers/usb/host/ehci.h1
3 files changed, 50 insertions, 12 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6887aac5e73d..d7e85b6231b3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -863,12 +863,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
863 if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim) 863 if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
864 end_unlink_async(ehci); 864 end_unlink_async(ehci);
865 865
866 /* if it's not linked then there's nothing to do */ 866 /* If the QH isn't linked then there's nothing we can do
867 if (qh->qh_state != QH_STATE_LINKED) 867 * unless we were called during a giveback, in which case
868 ; 868 * qh_completions() has to deal with it.
869 */
870 if (qh->qh_state != QH_STATE_LINKED) {
871 if (qh->qh_state == QH_STATE_COMPLETING)
872 qh->needs_rescan = 1;
873 return;
874 }
869 875
870 /* defer till later if busy */ 876 /* defer till later if busy */
871 else if (ehci->reclaim) { 877 if (ehci->reclaim) {
872 struct ehci_qh *last; 878 struct ehci_qh *last;
873 879
874 for (last = ehci->reclaim; 880 for (last = ehci->reclaim;
@@ -1001,6 +1007,7 @@ rescan:
1001 qh->qh_state = QH_STATE_IDLE; 1007 qh->qh_state = QH_STATE_IDLE;
1002 switch (qh->qh_state) { 1008 switch (qh->qh_state) {
1003 case QH_STATE_LINKED: 1009 case QH_STATE_LINKED:
1010 case QH_STATE_COMPLETING:
1004 for (tmp = ehci->async->qh_next.qh; 1011 for (tmp = ehci->async->qh_next.qh;
1005 tmp && tmp != qh; 1012 tmp && tmp != qh;
1006 tmp = tmp->qh_next.qh) 1013 tmp = tmp->qh_next.qh)
@@ -1065,7 +1072,8 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1065 usb_settoggle(qh->dev, epnum, is_out, 0); 1072 usb_settoggle(qh->dev, epnum, is_out, 0);
1066 if (!list_empty(&qh->qtd_list)) { 1073 if (!list_empty(&qh->qtd_list)) {
1067 WARN_ONCE(1, "clear_halt for a busy endpoint\n"); 1074 WARN_ONCE(1, "clear_halt for a busy endpoint\n");
1068 } else if (qh->qh_state == QH_STATE_LINKED) { 1075 } else if (qh->qh_state == QH_STATE_LINKED ||
1076 qh->qh_state == QH_STATE_COMPLETING) {
1069 1077
1070 /* The toggle value in the QH can't be updated 1078 /* The toggle value in the QH can't be updated
1071 * while the QH is active. Unlink it now; 1079 * while the QH is active. Unlink it now;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 377ed530b920..57a84795c43f 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -310,13 +310,13 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
310static unsigned 310static unsigned
311qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) 311qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
312{ 312{
313 struct ehci_qtd *last = NULL, *end = qh->dummy; 313 struct ehci_qtd *last, *end = qh->dummy;
314 struct list_head *entry, *tmp; 314 struct list_head *entry, *tmp;
315 int last_status = -EINPROGRESS; 315 int last_status;
316 int stopped; 316 int stopped;
317 unsigned count = 0; 317 unsigned count = 0;
318 u8 state; 318 u8 state;
319 __le32 halt = HALT_BIT(ehci); 319 const __le32 halt = HALT_BIT(ehci);
320 struct ehci_qh_hw *hw = qh->hw; 320 struct ehci_qh_hw *hw = qh->hw;
321 321
322 if (unlikely (list_empty (&qh->qtd_list))) 322 if (unlikely (list_empty (&qh->qtd_list)))
@@ -327,11 +327,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
327 * they add urbs to this qh's queue or mark them for unlinking. 327 * they add urbs to this qh's queue or mark them for unlinking.
328 * 328 *
329 * NOTE: unlinking expects to be done in queue order. 329 * NOTE: unlinking expects to be done in queue order.
330 *
331 * It's a bug for qh->qh_state to be anything other than
332 * QH_STATE_IDLE, unless our caller is scan_async() or
333 * scan_periodic().
330 */ 334 */
331 state = qh->qh_state; 335 state = qh->qh_state;
332 qh->qh_state = QH_STATE_COMPLETING; 336 qh->qh_state = QH_STATE_COMPLETING;
333 stopped = (state == QH_STATE_IDLE); 337 stopped = (state == QH_STATE_IDLE);
334 338
339 rescan:
340 last = NULL;
341 last_status = -EINPROGRESS;
342 qh->needs_rescan = 0;
343
335 /* remove de-activated QTDs from front of queue. 344 /* remove de-activated QTDs from front of queue.
336 * after faults (including short reads), cleanup this urb 345 * after faults (including short reads), cleanup this urb
337 * then let the queue advance. 346 * then let the queue advance.
@@ -507,6 +516,21 @@ halt:
507 ehci_qtd_free (ehci, last); 516 ehci_qtd_free (ehci, last);
508 } 517 }
509 518
519 /* Do we need to rescan for URBs dequeued during a giveback? */
520 if (unlikely(qh->needs_rescan)) {
521 /* If the QH is already unlinked, do the rescan now. */
522 if (state == QH_STATE_IDLE)
523 goto rescan;
524
525 /* Otherwise we have to wait until the QH is fully unlinked.
526 * Our caller will start an unlink if qh->needs_rescan is
527 * set. But if an unlink has already started, nothing needs
528 * to be done.
529 */
530 if (state != QH_STATE_LINKED)
531 qh->needs_rescan = 0;
532 }
533
510 /* restore original state; caller must unlink or relink */ 534 /* restore original state; caller must unlink or relink */
511 qh->qh_state = state; 535 qh->qh_state = state;
512 536
@@ -535,8 +559,10 @@ halt:
535 & hw->hw_info2) != 0) { 559 & hw->hw_info2) != 0) {
536 intr_deschedule (ehci, qh); 560 intr_deschedule (ehci, qh);
537 (void) qh_schedule (ehci, qh); 561 (void) qh_schedule (ehci, qh);
538 } else 562 } else {
539 unlink_async (ehci, qh); 563 /* Tell the caller to start an unlink */
564 qh->needs_rescan = 1;
565 }
540 break; 566 break;
541 /* otherwise, unlink already started */ 567 /* otherwise, unlink already started */
542 } 568 }
@@ -916,6 +942,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
916 if (unlikely(qh->clearing_tt)) 942 if (unlikely(qh->clearing_tt))
917 return; 943 return;
918 944
945 WARN_ON(qh->qh_state != QH_STATE_IDLE);
946
919 /* (re)start the async schedule? */ 947 /* (re)start the async schedule? */
920 head = ehci->async; 948 head = ehci->async;
921 timer_action_done (ehci, TIMER_ASYNC_OFF); 949 timer_action_done (ehci, TIMER_ASYNC_OFF);
@@ -934,8 +962,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
934 } 962 }
935 963
936 /* clear halt and/or toggle; and maybe recover from silicon quirk */ 964 /* clear halt and/or toggle; and maybe recover from silicon quirk */
937 if (qh->qh_state == QH_STATE_IDLE) 965 qh_refresh(ehci, qh);
938 qh_refresh (ehci, qh);
939 966
940 /* splice right after start */ 967 /* splice right after start */
941 qh->qh_next = head->qh_next; 968 qh->qh_next = head->qh_next;
@@ -1220,6 +1247,8 @@ rescan:
1220 qh = qh_get (qh); 1247 qh = qh_get (qh);
1221 qh->stamp = ehci->stamp; 1248 qh->stamp = ehci->stamp;
1222 temp = qh_completions (ehci, qh); 1249 temp = qh_completions (ehci, qh);
1250 if (qh->needs_rescan)
1251 unlink_async(ehci, qh);
1223 qh_put (qh); 1252 qh_put (qh);
1224 if (temp != 0) { 1253 if (temp != 0) {
1225 goto rescan; 1254 goto rescan;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ec3dba6b8e48..064e76821ff5 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -341,6 +341,7 @@ struct ehci_qh {
341 u32 refcount; 341 u32 refcount;
342 unsigned stamp; 342 unsigned stamp;
343 343
344 u8 needs_rescan; /* Dequeue during giveback */
344 u8 qh_state; 345 u8 qh_state;
345#define QH_STATE_LINKED 1 /* HC sees this */ 346#define QH_STATE_LINKED 1 /* HC sees this */
346#define QH_STATE_UNLINK 2 /* HC may still see this */ 347#define QH_STATE_UNLINK 2 /* HC may still see this */