aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-03-22 13:30:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 16:35:05 -0400
commit79bcf7b02ba3d45bafe81a2753cedb8ef49548e3 (patch)
treeda06b30b0fdd12dfb3286bed6a940bd2e4e0dfe0
parentc1fdb68e3d73741630ca16695cf9176c233be7ed (diff)
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.c22
-rw-r--r--drivers/usb/host/ehci-sched.c12
2 files changed, 13 insertions, 21 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b824cb674898..c95f60d43b1a 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);
292 292
293/* 293/*
294 * Process and free completed qtds for a qh, returning URBs to drivers. 294 * Process and free completed qtds for a qh, returning URBs to drivers.
295 * Chases up to qh->hw_current. Returns number of completions called, 295 * Chases up to qh->hw_current. Returns nonzero if the caller should
296 * indicating how much "real" work we did. 296 * unlink qh.
297 */ 297 */
298static unsigned 298static unsigned
299qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) 299qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -302,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
302 struct list_head *entry, *tmp; 302 struct list_head *entry, *tmp;
303 int last_status; 303 int last_status;
304 int stopped; 304 int stopped;
305 unsigned count = 0;
306 u8 state; 305 u8 state;
307 struct ehci_qh_hw *hw = qh->hw; 306 struct ehci_qh_hw *hw = qh->hw;
308 307
309 if (unlikely (list_empty (&qh->qtd_list)))
310 return count;
311
312 /* completions (or tasks on other cpus) must never clobber HALT 308 /* completions (or tasks on other cpus) must never clobber HALT
313 * till we've gone through and cleaned everything up, even when 309 * till we've gone through and cleaned everything up, even when
314 * they add urbs to this qh's queue or mark them for unlinking. 310 * 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)
345 if (last) { 341 if (last) {
346 if (likely (last->urb != urb)) { 342 if (likely (last->urb != urb)) {
347 ehci_urb_done(ehci, last->urb, last_status); 343 ehci_urb_done(ehci, last->urb, last_status);
348 count++;
349 last_status = -EINPROGRESS; 344 last_status = -EINPROGRESS;
350 } 345 }
351 ehci_qtd_free (ehci, last); 346 ehci_qtd_free (ehci, last);
@@ -519,7 +514,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
519 /* last urb's completion might still need calling */ 514 /* last urb's completion might still need calling */
520 if (likely (last != NULL)) { 515 if (likely (last != NULL)) {
521 ehci_urb_done(ehci, last->urb, last_status); 516 ehci_urb_done(ehci, last->urb, last_status);
522 count++;
523 ehci_qtd_free (ehci, last); 517 ehci_qtd_free (ehci, last);
524 } 518 }
525 519
@@ -566,7 +560,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
566 /* otherwise, unlink already started */ 560 /* otherwise, unlink already started */
567 } 561 }
568 562
569 return count; 563 return qh->needs_rescan;
570} 564}
571 565
572/*-------------------------------------------------------------------------*/ 566/*-------------------------------------------------------------------------*/
@@ -1254,7 +1248,8 @@ static void end_unlink_async(struct ehci_hcd *ehci)
1254 qh->qh_state = QH_STATE_IDLE; 1248 qh->qh_state = QH_STATE_IDLE;
1255 qh->qh_next.qh = NULL; 1249 qh->qh_next.qh = NULL;
1256 1250
1257 qh_completions(ehci, qh); 1251 if (!list_empty(&qh->qtd_list))
1252 qh_completions(ehci, qh);
1258 if (!list_empty(&qh->qtd_list) && 1253 if (!list_empty(&qh->qtd_list) &&
1259 ehci->rh_state == EHCI_RH_RUNNING) 1254 ehci->rh_state == EHCI_RH_RUNNING)
1260 qh_link_async(ehci, qh); 1255 qh_link_async(ehci, qh);
@@ -1348,7 +1343,7 @@ static void scan_async (struct ehci_hcd *ehci)
1348 while (ehci->qh_scan_next) { 1343 while (ehci->qh_scan_next) {
1349 qh = ehci->qh_scan_next; 1344 qh = ehci->qh_scan_next;
1350 ehci->qh_scan_next = qh->qh_next.qh; 1345 ehci->qh_scan_next = qh->qh_next.qh;
1351 rescan: 1346
1352 /* clean any finished work for this qh */ 1347 /* clean any finished work for this qh */
1353 if (!list_empty(&qh->qtd_list)) { 1348 if (!list_empty(&qh->qtd_list)) {
1354 int temp; 1349 int temp;
@@ -1361,14 +1356,13 @@ static void scan_async (struct ehci_hcd *ehci)
1361 * in single_unlink_async(). 1356 * in single_unlink_async().
1362 */ 1357 */
1363 temp = qh_completions(ehci, qh); 1358 temp = qh_completions(ehci, qh);
1364 if (qh->needs_rescan) { 1359 if (unlikely(temp)) {
1365 start_unlink_async(ehci, qh); 1360 start_unlink_async(ehci, qh);
1366 } else if (list_empty(&qh->qtd_list) 1361 } else if (list_empty(&qh->qtd_list)
1367 && qh->qh_state == QH_STATE_LINKED) { 1362 && qh->qh_state == QH_STATE_LINKED) {
1368 qh->unlink_cycle = ehci->async_unlink_cycle; 1363 qh->unlink_cycle = ehci->async_unlink_cycle;
1369 check_unlinks_later = true; 1364 check_unlinks_later = true;
1370 } else if (temp != 0) 1365 }
1371 goto rescan;
1372 } 1366 }
1373 } 1367 }
1374 1368
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 66259dc7822e..5c82bbab9a48 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)
649 qh->qh_state = QH_STATE_IDLE; 649 qh->qh_state = QH_STATE_IDLE;
650 hw->hw_next = EHCI_LIST_END(ehci); 650 hw->hw_next = EHCI_LIST_END(ehci);
651 651
652 qh_completions(ehci, qh); 652 if (!list_empty(&qh->qtd_list))
653 qh_completions(ehci, qh);
653 654
654 /* reschedule QH iff another request is queued */ 655 /* reschedule QH iff another request is queued */
655 if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { 656 if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
@@ -914,7 +915,7 @@ static void scan_intr(struct ehci_hcd *ehci)
914 915
915 list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list, 916 list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
916 intr_node) { 917 intr_node) {
917 rescan: 918
918 /* clean any finished work for this qh */ 919 /* clean any finished work for this qh */
919 if (!list_empty(&qh->qtd_list)) { 920 if (!list_empty(&qh->qtd_list)) {
920 int temp; 921 int temp;
@@ -927,12 +928,9 @@ static void scan_intr(struct ehci_hcd *ehci)
927 * in qh_unlink_periodic(). 928 * in qh_unlink_periodic().
928 */ 929 */
929 temp = qh_completions(ehci, qh); 930 temp = qh_completions(ehci, qh);
930 if (unlikely(qh->needs_rescan || 931 if (unlikely(temp || (list_empty(&qh->qtd_list) &&
931 (list_empty(&qh->qtd_list) && 932 qh->qh_state == QH_STATE_LINKED)))
932 qh->qh_state == QH_STATE_LINKED)))
933 start_unlink_intr(ehci, qh); 933 start_unlink_intr(ehci, qh);
934 else if (temp != 0)
935 goto rescan;
936 } 934 }
937 } 935 }
938} 936}