aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-03-22 13:31:11 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 16:35:05 -0400
commit7bc782d73c7db042ecc965866b8c1c2b7d6e93d6 (patch)
treefa5fcfb05da245b4b611585b36a9271c8144fd6b
parent79bcf7b02ba3d45bafe81a2753cedb8ef49548e3 (diff)
USB: EHCI: split needs_rescan into two flags
This patch (as1662) does some more QH-related cleanup in ehci-hcd. The qh->needs_rescan flag is currently used for two different purposes; the patch replaces it with two separate flags for greater clarity: qh->dequeue_during_giveback indicates that a completion handler dequeued an URB (implying that a rescan is needed), and qh->exception indicates that the QH is in an exceptional state requiring an unlink (either it encountered an I/O error or an unlink was requested). The new flags get set where the dequeue, exception, or unlink request occurred, rather than where the unlink is started. This is so that in the future, if we need to, we will be able to tell apart unlinks that truly were required from those that were carried out merely because the QH wasn't being used. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ehci-hcd.c16
-rw-r--r--drivers/usb/host/ehci-q.c62
-rw-r--r--drivers/usb/host/ehci-sched.c11
-rw-r--r--drivers/usb/host/ehci.h4
4 files changed, 39 insertions, 54 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0c3314c41363..93f4cd75845e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -903,11 +903,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
903 qh = (struct ehci_qh *) urb->hcpriv; 903 qh = (struct ehci_qh *) urb->hcpriv;
904 if (!qh) 904 if (!qh)
905 break; 905 break;
906 qh->exception = 1;
906 switch (qh->qh_state) { 907 switch (qh->qh_state) {
907 case QH_STATE_LINKED: 908 case QH_STATE_LINKED:
908 case QH_STATE_COMPLETING:
909 start_unlink_async(ehci, qh); 909 start_unlink_async(ehci, qh);
910 break; 910 break;
911 case QH_STATE_COMPLETING:
912 qh->dequeue_during_giveback = 1;
913 break;
911 case QH_STATE_UNLINK: 914 case QH_STATE_UNLINK:
912 case QH_STATE_UNLINK_WAIT: 915 case QH_STATE_UNLINK_WAIT:
913 /* already started */ 916 /* already started */
@@ -923,11 +926,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
923 qh = (struct ehci_qh *) urb->hcpriv; 926 qh = (struct ehci_qh *) urb->hcpriv;
924 if (!qh) 927 if (!qh)
925 break; 928 break;
929 qh->exception = 1;
926 switch (qh->qh_state) { 930 switch (qh->qh_state) {
927 case QH_STATE_LINKED: 931 case QH_STATE_LINKED:
928 case QH_STATE_COMPLETING:
929 start_unlink_intr(ehci, qh); 932 start_unlink_intr(ehci, qh);
930 break; 933 break;
934 case QH_STATE_COMPLETING:
935 qh->dequeue_during_giveback = 1;
936 break;
931 case QH_STATE_IDLE: 937 case QH_STATE_IDLE:
932 qh_completions (ehci, qh); 938 qh_completions (ehci, qh);
933 break; 939 break;
@@ -984,6 +990,7 @@ rescan:
984 goto done; 990 goto done;
985 } 991 }
986 992
993 qh->exception = 1;
987 if (ehci->rh_state < EHCI_RH_RUNNING) 994 if (ehci->rh_state < EHCI_RH_RUNNING)
988 qh->qh_state = QH_STATE_IDLE; 995 qh->qh_state = QH_STATE_IDLE;
989 switch (qh->qh_state) { 996 switch (qh->qh_state) {
@@ -1052,13 +1059,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1052 usb_settoggle(qh->dev, epnum, is_out, 0); 1059 usb_settoggle(qh->dev, epnum, is_out, 0);
1053 if (!list_empty(&qh->qtd_list)) { 1060 if (!list_empty(&qh->qtd_list)) {
1054 WARN_ONCE(1, "clear_halt for a busy endpoint\n"); 1061 WARN_ONCE(1, "clear_halt for a busy endpoint\n");
1055 } else if (qh->qh_state == QH_STATE_LINKED || 1062 } else {
1056 qh->qh_state == QH_STATE_COMPLETING) {
1057
1058 /* The toggle value in the QH can't be updated 1063 /* The toggle value in the QH can't be updated
1059 * while the QH is active. Unlink it now; 1064 * while the QH is active. Unlink it now;
1060 * re-linking will call qh_refresh(). 1065 * re-linking will call qh_refresh().
1061 */ 1066 */
1067 qh->exception = 1;
1062 if (eptype == USB_ENDPOINT_XFER_BULK) 1068 if (eptype == USB_ENDPOINT_XFER_BULK)
1063 start_unlink_async(ehci, qh); 1069 start_unlink_async(ehci, qh);
1064 else 1070 else
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index c95f60d43b1a..fca741dbf9df 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -322,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
322 rescan: 322 rescan:
323 last = NULL; 323 last = NULL;
324 last_status = -EINPROGRESS; 324 last_status = -EINPROGRESS;
325 qh->needs_rescan = 0; 325 qh->dequeue_during_giveback = 0;
326 326
327 /* remove de-activated QTDs from front of queue. 327 /* remove de-activated QTDs from front of queue.
328 * after faults (including short reads), cleanup this urb 328 * after faults (including short reads), cleanup this urb
@@ -518,18 +518,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
518 } 518 }
519 519
520 /* Do we need to rescan for URBs dequeued during a giveback? */ 520 /* Do we need to rescan for URBs dequeued during a giveback? */
521 if (unlikely(qh->needs_rescan)) { 521 if (unlikely(qh->dequeue_during_giveback)) {
522 /* If the QH is already unlinked, do the rescan now. */ 522 /* If the QH is already unlinked, do the rescan now. */
523 if (state == QH_STATE_IDLE) 523 if (state == QH_STATE_IDLE)
524 goto rescan; 524 goto rescan;
525 525
526 /* Otherwise we have to wait until the QH is fully unlinked. 526 /* Otherwise the caller must unlink the QH. */
527 * Our caller will start an unlink if qh->needs_rescan is
528 * set. But if an unlink has already started, nothing needs
529 * to be done.
530 */
531 if (state != QH_STATE_LINKED)
532 qh->needs_rescan = 0;
533 } 527 }
534 528
535 /* restore original state; caller must unlink or relink */ 529 /* restore original state; caller must unlink or relink */
@@ -538,29 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
538 /* be sure the hardware's done with the qh before refreshing 532 /* be sure the hardware's done with the qh before refreshing
539 * it after fault cleanup, or recovering from silicon wrongly 533 * it after fault cleanup, or recovering from silicon wrongly
540 * overlaying the dummy qtd (which reduces DMA chatter). 534 * overlaying the dummy qtd (which reduces DMA chatter).
535 *
536 * We won't refresh a QH that's linked (after the HC
537 * stopped the queue). That avoids a race:
538 * - HC reads first part of QH;
539 * - CPU updates that first part and the token;
540 * - HC reads rest of that QH, including token
541 * Result: HC gets an inconsistent image, and then
542 * DMAs to/from the wrong memory (corrupting it).
543 *
544 * That should be rare for interrupt transfers,
545 * except maybe high bandwidth ...
541 */ 546 */
542 if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) { 547 if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
543 if (state == QH_STATE_LINKED) { 548 qh->exception = 1;
544 /*
545 * We won't refresh a QH that's linked (after the HC
546 * stopped the queue). That avoids a race:
547 * - HC reads first part of QH;
548 * - CPU updates that first part and the token;
549 * - HC reads rest of that QH, including token
550 * Result: HC gets an inconsistent image, and then
551 * DMAs to/from the wrong memory (corrupting it).
552 *
553 * That should be rare for interrupt transfers,
554 * except maybe high bandwidth ...
555 *
556 * Therefore tell the caller to start an unlink.
557 */
558 qh->needs_rescan = 1;
559 }
560 /* otherwise, unlink already started */
561 }
562 549
563 return qh->needs_rescan; 550 /* Let the caller know if the QH needs to be unlinked. */
551 return qh->exception;
564} 552}
565 553
566/*-------------------------------------------------------------------------*/ 554/*-------------------------------------------------------------------------*/
@@ -1002,8 +990,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
1002 head->qh_next.qh = qh; 990 head->qh_next.qh = qh;
1003 head->hw->hw_next = dma; 991 head->hw->hw_next = dma;
1004 992
1005 qh->xacterrs = 0;
1006 qh->qh_state = QH_STATE_LINKED; 993 qh->qh_state = QH_STATE_LINKED;
994 qh->xacterrs = 0;
995 qh->exception = 0;
1007 /* qtd completions reported later by interrupt */ 996 /* qtd completions reported later by interrupt */
1008 997
1009 enable_async(ehci); 998 enable_async(ehci);
@@ -1317,16 +1306,9 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
1317 1306
1318static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) 1307static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
1319{ 1308{
1320 /* 1309 /* If the QH isn't linked then there's nothing we can do. */
1321 * If the QH isn't linked then there's nothing we can do 1310 if (qh->qh_state != QH_STATE_LINKED)
1322 * unless we were called during a giveback, in which case
1323 * qh_completions() has to deal with it.
1324 */
1325 if (qh->qh_state != QH_STATE_LINKED) {
1326 if (qh->qh_state == QH_STATE_COMPLETING)
1327 qh->needs_rescan = 1;
1328 return; 1311 return;
1329 }
1330 1312
1331 single_unlink_async(ehci, qh); 1313 single_unlink_async(ehci, qh);
1332 start_iaa_cycle(ehci, false); 1314 start_iaa_cycle(ehci, false);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 5c82bbab9a48..e7a2dbd27b1e 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
539 } 539 }
540 qh->qh_state = QH_STATE_LINKED; 540 qh->qh_state = QH_STATE_LINKED;
541 qh->xacterrs = 0; 541 qh->xacterrs = 0;
542 qh->exception = 0;
542 543
543 /* update per-qh bandwidth for usbfs */ 544 /* update per-qh bandwidth for usbfs */
544 ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period 545 ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
@@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
602 603
603static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) 604static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
604{ 605{
605 /* If the QH isn't linked then there's nothing we can do 606 /* If the QH isn't linked then there's nothing we can do. */
606 * unless we were called during a giveback, in which case 607 if (qh->qh_state != QH_STATE_LINKED)
607 * qh_completions() has to deal with it.
608 */
609 if (qh->qh_state != QH_STATE_LINKED) {
610 if (qh->qh_state == QH_STATE_COMPLETING)
611 qh->needs_rescan = 1;
612 return; 608 return;
613 }
614 609
615 qh_unlink_periodic (ehci, qh); 610 qh_unlink_periodic (ehci, qh);
616 611
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 36c3a8210595..6815209511aa 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -384,7 +384,6 @@ struct ehci_qh {
384 384
385 unsigned unlink_cycle; 385 unsigned unlink_cycle;
386 386
387 u8 needs_rescan; /* Dequeue during giveback */
388 u8 qh_state; 387 u8 qh_state;
389#define QH_STATE_LINKED 1 /* HC sees this */ 388#define QH_STATE_LINKED 1 /* HC sees this */
390#define QH_STATE_UNLINK 2 /* HC may still see this */ 389#define QH_STATE_UNLINK 2 /* HC may still see this */
@@ -407,6 +406,9 @@ struct ehci_qh {
407 struct usb_device *dev; /* access to TT */ 406 struct usb_device *dev; /* access to TT */
408 unsigned is_out:1; /* bulk or intr OUT */ 407 unsigned is_out:1; /* bulk or intr OUT */
409 unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ 408 unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
409 unsigned dequeue_during_giveback:1;
410 unsigned exception:1; /* got a fault, or an unlink
411 was requested */
410}; 412};
411 413
412/*-------------------------------------------------------------------------*/ 414/*-------------------------------------------------------------------------*/