summaryrefslogtreecommitdiffstats
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
authorJay Fenlason <fenlason@redhat.com>2009-11-21 00:05:56 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-11-21 00:56:47 +0100
commit31769cef2e973544164aa7d0db2e2024660d5e21 (patch)
tree6f3c2ce2e742fa197ac1460012a14eaf09bf3afa /drivers/firewire/ohci.c
parent5ed1f321a71b8549cc2eea26c94fe7943ed01d31 (diff)
downloadlinux-31769cef2e973544164aa7d0db2e2024660d5e21.tar.gz
linux-31769cef2e973544164aa7d0db2e2024660d5e21.tar.bz2
linux-31769cef2e973544164aa7d0db2e2024660d5e21.zip
firewire: ohci: pass correct iso xmit timestamps to core
Here is the final set of patches I used to get ffado to work with the new firewire stack. With these patches, I was able to start ardour and record from and playback to my PreSonus Inspire1394 from a (mostly) Fedora 12 system. Signed-off-by: Jay Fenlason <fenlason@redhat.com> Until now, firewire-ohci exposed only the transmit cycle of the last transmitted packet at each isochronous transmit complete event. This made it impossible for FFADO (FireWire audio drivers in userspace) to synchronize audio-out streams. The fix is to store the timestamp of each packet in the iso xmit event. As a bonus, the transfer status is stored too. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c07cfada190a..94260aa76aa3 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1904,15 +1904,30 @@ static int handle_it_packet(struct context *context,
{
struct iso_context *ctx =
container_of(context, struct iso_context, context);
+ int i;
+ struct descriptor *pd;
- if (last->transfer_status == 0)
- /* This descriptor isn't done yet, stop iteration. */
+ for (pd = d; pd <= last; pd++)
+ if (pd->transfer_status)
+ break;
+ if (pd > last)
+ /* Descriptor(s) not done yet, stop iteration */
return 0;
- if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
+ i = ctx->header_length;
+ if (i + 4 < PAGE_SIZE) {
+ /* Present this value as big-endian to match the receive code */
+ *(__be32 *)(ctx->header + i) = cpu_to_be32(
+ ((u32)le16_to_cpu(pd->transfer_status) << 16) |
+ le16_to_cpu(pd->res_count));
+ ctx->header_length += 4;
+ }
+ if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count),
- 0, NULL, ctx->base.callback_data);
-
+ ctx->header_length, ctx->header,
+ ctx->base.callback_data);
+ ctx->header_length = 0;
+ }
return 1;
}