Fix reporting of isochronous transmit cycles on firewire-core

While firewire-core's iso reception ABI was fixed in its version 2 to
report the cycle of each received packet to userspace like rawiso does,
this same enhancement was forgotten to add to the iso transmission ABI,
causing FFADO to fail to set up and maintain streaming.

Since kernel commit 31769cef2e973544164aa7d0db2e2024660d5e21, we also
get iso xmit cycles in fw_cdev_event_iso_interrupt.header.  Pass these
to the iso receive handler.  In case of older kernels, calculate cycles
based on the cycle of the iso interrupt event.  These are inaccurate but
better than nothing.

Signed-off-by: Jay Fenlason <fenlason@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (changelog, whitespace)
This commit is contained in:
Jay Fenlason 2009-11-19 15:00:02 -05:00 committed by Stefan Richter
parent 1fb09ead37
commit ce82d255ef
1 changed files with 46 additions and 10 deletions

View File

@ -70,13 +70,12 @@ queue_packet(fw_handle_t handle,
}
static int
queue_xmit_packets(raw1394handle_t handle, int limit)
queue_xmit_packets(raw1394handle_t handle, int limit, int cycle)
{
fw_handle_t fwhandle = handle->mode.fw;
enum raw1394_iso_disposition d;
unsigned char tag, sy;
unsigned int len;
int cycle = -1;
unsigned int dropped = 0;
if (fwhandle->iso.xmit_handler == NULL)
@ -90,6 +89,11 @@ queue_xmit_packets(raw1394handle_t handle, int limit)
switch (d) {
case RAW1394_ISO_OK:
queue_packet(fwhandle, len, 0, tag, sy);
if (cycle >= 0) {
cycle++;
if (cycle >= 8000)
cycle %= 8000;
}
break;
case RAW1394_ISO_DEFER:
case RAW1394_ISO_AGAIN:
@ -119,7 +123,21 @@ int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
fwhandle->iso.prebuffer = prebuffer_packets;
fwhandle->iso.start_on_cycle = start_on_cycle;
queue_xmit_packets(handle, prebuffer_packets);
retval = queue_xmit_packets(handle, prebuffer_packets, start_on_cycle);
if (retval)
return -1;
if (start_on_cycle >= 0) {
int tmp;
tmp = start_on_cycle + prebuffer_packets;
tmp %= 8000;
retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets, tmp);
} else {
retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets, -1);
}
if (retval)
return -1;
if (fwhandle->iso.prebuffer <= fwhandle->iso.packet_count) {
start_iso.cycle = start_on_cycle;
@ -131,12 +149,7 @@ int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
return retval;
}
retval = queue_xmit_packets(handle, fwhandle->iso.buf_packets);
if (retval)
return -1;
else
fwhandle->iso.state = ISO_ACTIVE;
fwhandle->iso.state = ISO_ACTIVE;
return 0;
}
@ -256,8 +269,31 @@ static int handle_iso_event(raw1394handle_t handle,
switch (fwhandle->iso.type) {
case FW_CDEV_ISO_CONTEXT_TRANSMIT:
{
int cycle;
fwhandle->iso.packet_count -= fwhandle->iso.irq_interval;
return queue_xmit_packets(handle, fwhandle->iso.buf_packets);
if (interrupt->header_length) {
/*
* Take the cycle of the last packet transmitted, add
* the number of packets currently queued, plus one, and
* that's the cycle number of the next packet to ask
* for.
*/
cycle = be32_to_cpu(interrupt->header[interrupt->header_length/4 - 1]);
cycle &= 0x1fff;
} else {
/*
* Bogusly faking it again. Assume that the last packet
* transmitted was transmitted on interrupt->cycle.
*/
cycle = interrupt->cycle;
}
cycle += fwhandle->iso.packet_count;
cycle++;
cycle %= 8000;
return queue_xmit_packets(handle, fwhandle->iso.buf_packets, cycle);
}
case FW_CDEV_ISO_CONTEXT_RECEIVE:
return flush_recv_packets(handle, interrupt);
default: