[PATCH 6/11] USB: EHCI: change return value of qh_completions()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch (as1658) cleans up the usage of qh_completions() in
ehci-hcd.  Currently the function's return value indicates whether any
URBs were given back; the idea was that the caller can scan the QH
over again to handle any URBs that were dequeued by a completion
handler.  This is not necessary; when qh_completions() is ready to
give back dequeued URBs, it does its own rescanning.

Therefore the new return value will be a flag indicating whether the
caller needs to unlink the QH.  This is more convenient than forcing
the caller to check qh->needs_rescan, and it makes a lot more sense --
why should "needs_rescan" imply that an unlink is needed?  The callers
are also changed to remove the unneeded rescans.

Lastly, the check for whether qh->qtd_list is non-empty is removed
from the start of qh_completions().  Two of the callers have to make
this test anyway, so the same test can simply be added to the other
two callers.

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

---

 drivers/usb/host/ehci-q.c     |   22 ++++++++--------------
 drivers/usb/host/ehci-sched.c |   12 +++++-------
 2 files changed, 13 insertions(+), 21 deletions(-)

Index: usb-3.9/drivers/usb/host/ehci-q.c
===================================================================
--- usb-3.9.orig/drivers/usb/host/ehci-q.c
+++ usb-3.9/drivers/usb/host/ehci-q.c
@@ -292,8 +292,8 @@ static int qh_schedule (struct ehci_hcd
 
 /*
  * Process and free completed qtds for a qh, returning URBs to drivers.
- * Chases up to qh->hw_current.  Returns number of completions called,
- * indicating how much "real" work we did.
+ * Chases up to qh->hw_current.  Returns nonzero if the caller should
+ * unlink qh.
  */
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -302,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, s
 	struct list_head	*entry, *tmp;
 	int			last_status;
 	int			stopped;
-	unsigned		count = 0;
 	u8			state;
 	struct ehci_qh_hw	*hw = qh->hw;
 
-	if (unlikely (list_empty (&qh->qtd_list)))
-		return count;
-
 	/* completions (or tasks on other cpus) must never clobber HALT
 	 * till we've gone through and cleaned everything up, even when
 	 * they add urbs to this qh's queue or mark them for unlinking.
@@ -345,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, s
 		if (last) {
 			if (likely (last->urb != urb)) {
 				ehci_urb_done(ehci, last->urb, last_status);
-				count++;
 				last_status = -EINPROGRESS;
 			}
 			ehci_qtd_free (ehci, last);
@@ -519,7 +514,6 @@ qh_completions (struct ehci_hcd *ehci, s
 	/* last urb's completion might still need calling */
 	if (likely (last != NULL)) {
 		ehci_urb_done(ehci, last->urb, last_status);
-		count++;
 		ehci_qtd_free (ehci, last);
 	}
 
@@ -566,7 +560,7 @@ qh_completions (struct ehci_hcd *ehci, s
 		/* otherwise, unlink already started */
 	}
 
-	return count;
+	return qh->needs_rescan;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1254,7 +1248,8 @@ static void end_unlink_async(struct ehci
 		qh->qh_state = QH_STATE_IDLE;
 		qh->qh_next.qh = NULL;
 
-		qh_completions(ehci, qh);
+		if (!list_empty(&qh->qtd_list))
+			qh_completions(ehci, qh);
 		if (!list_empty(&qh->qtd_list) &&
 				ehci->rh_state == EHCI_RH_RUNNING)
 			qh_link_async(ehci, qh);
@@ -1348,7 +1343,7 @@ static void scan_async (struct ehci_hcd
 	while (ehci->qh_scan_next) {
 		qh = ehci->qh_scan_next;
 		ehci->qh_scan_next = qh->qh_next.qh;
- rescan:
+
 		/* clean any finished work for this qh */
 		if (!list_empty(&qh->qtd_list)) {
 			int temp;
@@ -1361,14 +1356,13 @@ static void scan_async (struct ehci_hcd
 			 * in single_unlink_async().
 			 */
 			temp = qh_completions(ehci, qh);
-			if (qh->needs_rescan) {
+			if (unlikely(temp)) {
 				start_unlink_async(ehci, qh);
 			} else if (list_empty(&qh->qtd_list)
 					&& qh->qh_state == QH_STATE_LINKED) {
 				qh->unlink_cycle = ehci->async_unlink_cycle;
 				check_unlinks_later = true;
-			} else if (temp != 0)
-				goto rescan;
+			}
 		}
 	}
 
Index: usb-3.9/drivers/usb/host/ehci-sched.c
===================================================================
--- usb-3.9.orig/drivers/usb/host/ehci-sched.c
+++ usb-3.9/drivers/usb/host/ehci-sched.c
@@ -649,7 +649,8 @@ static void end_unlink_intr(struct ehci_
 	qh->qh_state = QH_STATE_IDLE;
 	hw->hw_next = EHCI_LIST_END(ehci);
 
-	qh_completions(ehci, qh);
+	if (!list_empty(&qh->qtd_list))
+		qh_completions(ehci, qh);
 
 	/* reschedule QH iff another request is queued */
 	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
@@ -914,7 +915,7 @@ static void scan_intr(struct ehci_hcd *e
 
 	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
 			intr_node) {
- rescan:
+
 		/* clean any finished work for this qh */
 		if (!list_empty(&qh->qtd_list)) {
 			int temp;
@@ -927,12 +928,9 @@ static void scan_intr(struct ehci_hcd *e
 			 * in qh_unlink_periodic().
 			 */
 			temp = qh_completions(ehci, qh);
-			if (unlikely(qh->needs_rescan ||
-					(list_empty(&qh->qtd_list) &&
-						qh->qh_state == QH_STATE_LINKED)))
+			if (unlikely(temp || (list_empty(&qh->qtd_list) &&
+					qh->qh_state == QH_STATE_LINKED)))
 				start_unlink_intr(ehci, qh);
-			else if (temp != 0)
-				goto rescan;
 		}
 	}
 }


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux