diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2013-08-07 10:58:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-12 16:45:26 -0400 |
commit | 24f531371de17010f2b1b57d90e42240032e7733 (patch) | |
tree | cf8720d58ff2897754e6212db7c2eb898db6ee7f /drivers/usb | |
parent | d4e4ab86bcba5a72779c43dc1459f71fea3d89c8 (diff) |
USB: EHCI: accept very late isochronous URBs
Since commits 4005ad4390bf (EHCI: implement new semantics for
URB_ISO_ASAP) and c75c5ab575af (ALSA: USB: adjust for changed 3.8 USB
API) became widely distributed, people have been experiencing problems
with audio transfers. The slightest underrun causes complete failure,
requiring the audio stream to be restarted.
It turns out that the current isochronous API doesn't handle underruns
in the best way. The ALSA developers would much rather have transfers
that are submitted too late be accepted and complete in the normal
fashion, rather than being refused outright.
This patch implements the requested approach. When an isochronous URB
submission is so late that all its scheduled slots have already
expired, a debugging message will be printed in the log and the URB
will be accepted as usual. Assuming it was submitted by a completion
handler (which is normally the case), it will complete shortly
thereafter with all the usb_iso_packet_descriptor status fields marked
-EXDEV.
This fixes (for ehci-hcd)
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1191603
It should be applied to all kernels that include commit 4005ad4390bf.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Maksim Boyko <maksboyko@yandex.ru>
CC: Clemens Ladisch <clemens@ladisch.de>
CC: <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f80d0330d548..8e3c878f38cf 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1391,21 +1391,20 @@ iso_stream_schedule ( | |||
1391 | 1391 | ||
1392 | /* Behind the scheduling threshold? */ | 1392 | /* Behind the scheduling threshold? */ |
1393 | if (unlikely(start < next)) { | 1393 | if (unlikely(start < next)) { |
1394 | unsigned now2 = (now - base) & (mod - 1); | ||
1394 | 1395 | ||
1395 | /* USB_ISO_ASAP: Round up to the first available slot */ | 1396 | /* USB_ISO_ASAP: Round up to the first available slot */ |
1396 | if (urb->transfer_flags & URB_ISO_ASAP) | 1397 | if (urb->transfer_flags & URB_ISO_ASAP) |
1397 | start += (next - start + period - 1) & -period; | 1398 | start += (next - start + period - 1) & -period; |
1398 | 1399 | ||
1399 | /* | 1400 | /* |
1400 | * Not ASAP: Use the next slot in the stream. If | 1401 | * Not ASAP: Use the next slot in the stream, |
1401 | * the entire URB falls before the threshold, fail. | 1402 | * no matter what. |
1402 | */ | 1403 | */ |
1403 | else if (start + span - period < next) { | 1404 | else if (start + span - period < now2) { |
1404 | ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", | 1405 | ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", |
1405 | urb, start + base, | 1406 | urb, start + base, |
1406 | span - period, next + base); | 1407 | span - period, now2 + base); |
1407 | status = -EXDEV; | ||
1408 | goto fail; | ||
1409 | } | 1408 | } |
1410 | } | 1409 | } |
1411 | 1410 | ||