diff options
| author | Alan Stern <stern@rowland.harvard.edu> | 2013-03-22 13:30:56 -0400 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-25 13:35:05 -0700 | 
| commit | 79bcf7b02ba3d45bafe81a2753cedb8ef49548e3 (patch) | |
| tree | da06b30b0fdd12dfb3286bed6a940bd2e4e0dfe0 | |
| parent | c1fdb68e3d73741630ca16695cf9176c233be7ed (diff) | |
| download | olio-linux-3.10-79bcf7b02ba3d45bafe81a2753cedb8ef49548e3.tar.xz olio-linux-3.10-79bcf7b02ba3d45bafe81a2753cedb8ef49548e3.zip  | |
USB: EHCI: change return value of qh_completions()
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@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 22 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 12 | 
2 files changed, 13 insertions, 21 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index b824cb67489..c95f60d43b1 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -292,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);  /*   * 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, struct ehci_qh *qh)  	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, struct ehci_qh *qh)  		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, struct ehci_qh *qh)  	/* 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, struct ehci_qh *qh)  		/* otherwise, unlink already started */  	} -	return count; +	return qh->needs_rescan;  }  /*-------------------------------------------------------------------------*/ @@ -1254,7 +1248,8 @@ static void end_unlink_async(struct ehci_hcd *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 *ehci)  	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 *ehci)  			 * 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; +			}  		}  	} diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 66259dc7822..5c82bbab9a4 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -649,7 +649,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  	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 *ehci)  	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 *ehci)  			 * 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;  		}  	}  }  |