aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-10-01 10:32:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-22 14:10:24 -0400
commit4005ad4390bf698e3bdae9567e79242ec0584097 (patch)
tree6dd474eb74153ff382184c9f6656ea2e1441ad28 /drivers
parenta03bede5c73a6876fa891cfe82a65460dc9f4698 (diff)
EHCI: implement new semantics for URB_ISO_ASAP
This patch (as1612) updates the isochronous scheduling and processing in ehci-hcd to match the new semantics for URB_ISO_ASAP. It also adds a missing "unlikely" in sitd_complete() to match the corresponding statement in itd_complete(), and it increments urb->error_count in a couple of places that had been overlooked. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ehci-sched.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e08e65d8e004..b538a4d62d5e 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1386,8 +1386,8 @@ iso_stream_schedule (
1386 1386
1387 /* Typical case: reuse current schedule, stream is still active. 1387 /* Typical case: reuse current schedule, stream is still active.
1388 * Hopefully there are no gaps from the host falling behind 1388 * Hopefully there are no gaps from the host falling behind
1389 * (irq delays etc), but if there are we'll take the next 1389 * (irq delays etc). If there are, the behavior depends on
1390 * slot in the schedule, implicitly assuming URB_ISO_ASAP. 1390 * whether URB_ISO_ASAP is set.
1391 */ 1391 */
1392 if (likely (!list_empty (&stream->td_list))) { 1392 if (likely (!list_empty (&stream->td_list))) {
1393 1393
@@ -1414,9 +1414,25 @@ iso_stream_schedule (
1414 goto fail; 1414 goto fail;
1415 } 1415 }
1416 1416
1417 /* Behind the scheduling threshold? Assume URB_ISO_ASAP. */ 1417 /* Behind the scheduling threshold? */
1418 if (unlikely(start < next)) 1418 if (unlikely(start < next)) {
1419 start += (next - start + period - 1) & (- period); 1419
1420 /* USB_ISO_ASAP: Round up to the first available slot */
1421 if (urb->transfer_flags & URB_ISO_ASAP)
1422 start += (next - start + period - 1) & -period;
1423
1424 /*
1425 * Not ASAP: Use the next slot in the stream. If
1426 * the entire URB falls before the threshold, fail.
1427 */
1428 else if (start + span - period < next) {
1429 ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
1430 urb, start + base,
1431 span - period, next + base);
1432 status = -EXDEV;
1433 goto fail;
1434 }
1435 }
1420 1436
1421 start += base; 1437 start += base;
1422 } 1438 }
@@ -1699,7 +1715,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
1699 urb->actual_length += desc->actual_length; 1715 urb->actual_length += desc->actual_length;
1700 } else { 1716 } else {
1701 /* URB was too late */ 1717 /* URB was too late */
1702 desc->status = -EXDEV; 1718 urb->error_count++;
1703 } 1719 }
1704 } 1720 }
1705 1721
@@ -2072,7 +2088,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
2072 t = hc32_to_cpup(ehci, &sitd->hw_results); 2088 t = hc32_to_cpup(ehci, &sitd->hw_results);
2073 2089
2074 /* report transfer status */ 2090 /* report transfer status */
2075 if (t & SITD_ERRS) { 2091 if (unlikely(t & SITD_ERRS)) {
2076 urb->error_count++; 2092 urb->error_count++;
2077 if (t & SITD_STS_DBE) 2093 if (t & SITD_STS_DBE)
2078 desc->status = usb_pipein (urb->pipe) 2094 desc->status = usb_pipein (urb->pipe)
@@ -2082,6 +2098,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
2082 desc->status = -EOVERFLOW; 2098 desc->status = -EOVERFLOW;
2083 else /* XACT, MMF, etc */ 2099 else /* XACT, MMF, etc */
2084 desc->status = -EPROTO; 2100 desc->status = -EPROTO;
2101 } else if (unlikely(t & SITD_STS_ACTIVE)) {
2102 /* URB was too late */
2103 urb->error_count++;
2085 } else { 2104 } else {
2086 desc->status = 0; 2105 desc->status = 0;
2087 desc->actual_length = desc->length - SITD_LENGTH(t); 2106 desc->actual_length = desc->length - SITD_LENGTH(t);