summaryrefslogtreecommitdiffstats
path: root/sound/firewire/amdtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/amdtp.c')
-rw-r--r--sound/firewire/amdtp.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 046007d..b18140f 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -47,6 +47,7 @@ int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
+ s->packet_index = 0;
return 0;
}
@@ -316,15 +317,19 @@ static void amdtp_fill_midi(struct amdtp_out_stream *s,
static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
{
__be32 *buffer;
- unsigned int data_blocks, syt, ptr;
+ unsigned int index, data_blocks, syt, ptr;
struct snd_pcm_substream *pcm;
struct fw_iso_packet packet;
int err;
+ if (s->packet_index < 0)
+ return;
+ index = s->packet_index;
+
data_blocks = calculate_data_blocks(s);
syt = calculate_syt(s, cycle);
- buffer = s->buffer.packets[s->packet_counter].buffer;
+ buffer = s->buffer.packets[index].buffer;
buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
(s->data_block_quadlets << 16) |
s->data_block_counter);
@@ -343,20 +348,24 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
- packet.interrupt = IS_ALIGNED(s->packet_counter + 1,
- INTERRUPT_INTERVAL);
+ packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL);
packet.skip = 0;
packet.tag = TAG_CIP;
packet.sy = 0;
packet.header_length = 0;
err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer,
- s->buffer.packets[s->packet_counter].offset);
- if (err < 0)
+ s->buffer.packets[index].offset);
+ if (err < 0) {
dev_err(&s->unit->device, "queueing error: %d\n", err);
+ s->packet_index = -1;
+ amdtp_out_stream_pcm_abort(s);
+ return;
+ }
- if (++s->packet_counter >= QUEUE_LENGTH)
- s->packet_counter = 0;
+ if (++index >= QUEUE_LENGTH)
+ index = 0;
+ s->packet_index = index;
if (pcm) {
ptr = s->pcm_buffer_pointer + data_blocks;
@@ -398,13 +407,13 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s)
int err;
for (i = 0; i < QUEUE_LENGTH; ++i) {
- skip_packet.interrupt = IS_ALIGNED(s->packet_counter + 1,
+ skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1,
INTERRUPT_INTERVAL);
err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0);
if (err < 0)
return err;
- if (++s->packet_counter >= QUEUE_LENGTH)
- s->packet_counter = 0;
+ if (++s->packet_index >= QUEUE_LENGTH)
+ s->packet_index = 0;
}
return 0;
@@ -469,7 +478,7 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
amdtp_out_stream_update(s);
- s->packet_counter = 0;
+ s->packet_index = 0;
s->data_block_counter = 0;
err = queue_initial_skip_packets(s);
if (err < 0)
OpenPOWER on IntegriCloud