diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-10-01 10:32:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-22 14:10:24 -0400 |
commit | 4005ad4390bf698e3bdae9567e79242ec0584097 (patch) | |
tree | 6dd474eb74153ff382184c9f6656ea2e1441ad28 /drivers | |
parent | a03bede5c73a6876fa891cfe82a65460dc9f4698 (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.c | 33 |
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); |