aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/amdtp.c33
-rw-r--r--sound/firewire/amdtp.h14
-rw-r--r--sound/firewire/speakers.c3
3 files changed, 37 insertions, 13 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 046007ddbca..b18140ff2b9 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,
47 s->flags = flags; 47 s->flags = flags;
48 s->context = ERR_PTR(-1); 48 s->context = ERR_PTR(-1);
49 mutex_init(&s->mutex); 49 mutex_init(&s->mutex);
50 s->packet_index = 0;
50 51
51 return 0; 52 return 0;
52} 53}
@@ -316,15 +317,19 @@ static void amdtp_fill_midi(struct amdtp_out_stream *s,
316static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) 317static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
317{ 318{
318 __be32 *buffer; 319 __be32 *buffer;
319 unsigned int data_blocks, syt, ptr; 320 unsigned int index, data_blocks, syt, ptr;
320 struct snd_pcm_substream *pcm; 321 struct snd_pcm_substream *pcm;
321 struct fw_iso_packet packet; 322 struct fw_iso_packet packet;
322 int err; 323 int err;
323 324
325 if (s->packet_index < 0)
326 return;
327 index = s->packet_index;
328
324 data_blocks = calculate_data_blocks(s); 329 data_blocks = calculate_data_blocks(s);
325 syt = calculate_syt(s, cycle); 330 syt = calculate_syt(s, cycle);
326 331
327 buffer = s->buffer.packets[s->packet_counter].buffer; 332 buffer = s->buffer.packets[index].buffer;
328 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | 333 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
329 (s->data_block_quadlets << 16) | 334 (s->data_block_quadlets << 16) |
330 s->data_block_counter); 335 s->data_block_counter);
@@ -343,20 +348,24 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
343 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; 348 s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
344 349
345 packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; 350 packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
346 packet.interrupt = IS_ALIGNED(s->packet_counter + 1, 351 packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL);
347 INTERRUPT_INTERVAL);
348 packet.skip = 0; 352 packet.skip = 0;
349 packet.tag = TAG_CIP; 353 packet.tag = TAG_CIP;
350 packet.sy = 0; 354 packet.sy = 0;
351 packet.header_length = 0; 355 packet.header_length = 0;
352 356
353 err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, 357 err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer,
354 s->buffer.packets[s->packet_counter].offset); 358 s->buffer.packets[index].offset);
355 if (err < 0) 359 if (err < 0) {
356 dev_err(&s->unit->device, "queueing error: %d\n", err); 360 dev_err(&s->unit->device, "queueing error: %d\n", err);
361 s->packet_index = -1;
362 amdtp_out_stream_pcm_abort(s);
363 return;
364 }
357 365
358 if (++s->packet_counter >= QUEUE_LENGTH) 366 if (++index >= QUEUE_LENGTH)
359 s->packet_counter = 0; 367 index = 0;
368 s->packet_index = index;
360 369
361 if (pcm) { 370 if (pcm) {
362 ptr = s->pcm_buffer_pointer + data_blocks; 371 ptr = s->pcm_buffer_pointer + data_blocks;
@@ -398,13 +407,13 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s)
398 int err; 407 int err;
399 408
400 for (i = 0; i < QUEUE_LENGTH; ++i) { 409 for (i = 0; i < QUEUE_LENGTH; ++i) {
401 skip_packet.interrupt = IS_ALIGNED(s->packet_counter + 1, 410 skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1,
402 INTERRUPT_INTERVAL); 411 INTERRUPT_INTERVAL);
403 err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); 412 err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0);
404 if (err < 0) 413 if (err < 0)
405 return err; 414 return err;
406 if (++s->packet_counter >= QUEUE_LENGTH) 415 if (++s->packet_index >= QUEUE_LENGTH)
407 s->packet_counter = 0; 416 s->packet_index = 0;
408 } 417 }
409 418
410 return 0; 419 return 0;
@@ -469,7 +478,7 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
469 478
470 amdtp_out_stream_update(s); 479 amdtp_out_stream_update(s);
471 480
472 s->packet_counter = 0; 481 s->packet_index = 0;
473 s->data_block_counter = 0; 482 s->data_block_counter = 0;
474 err = queue_initial_skip_packets(s); 483 err = queue_initial_skip_packets(s);
475 if (err < 0) 484 if (err < 0)
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index 02dc1a664b5..537a9cb8358 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -56,7 +56,7 @@ struct amdtp_out_stream {
56 56
57 struct snd_pcm_substream *pcm; 57 struct snd_pcm_substream *pcm;
58 58
59 unsigned int packet_counter; 59 int packet_index;
60 unsigned int data_block_counter; 60 unsigned int data_block_counter;
61 61
62 unsigned int data_block_state; 62 unsigned int data_block_state;
@@ -111,6 +111,18 @@ static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s,
111} 111}
112 112
113/** 113/**
114 * amdtp_out_streaming_error - check for streaming error
115 * @s: the AMDTP output stream
116 *
117 * If this function returns true, the stream's packet queue has stopped due to
118 * an asynchronous error.
119 */
120static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
121{
122 return s->packet_index < 0;
123}
124
125/**
114 * amdtp_out_stream_pcm_prepare - prepare PCM device for running 126 * amdtp_out_stream_pcm_prepare - prepare PCM device for running
115 * @s: the AMDTP output stream 127 * @s: the AMDTP output stream
116 * 128 *
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index f6b095ef075..0fce9218abb 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -283,6 +283,9 @@ static int fwspk_prepare(struct snd_pcm_substream *substream)
283 283
284 mutex_lock(&fwspk->mutex); 284 mutex_lock(&fwspk->mutex);
285 285
286 if (amdtp_out_streaming_error(&fwspk->stream))
287 fwspk_stop_stream(fwspk);
288
286 if (!fwspk->stream_running) { 289 if (!fwspk->stream_running) {
287 err = cmp_connection_establish(&fwspk->connection, 290 err = cmp_connection_establish(&fwspk->connection,
288 amdtp_out_stream_get_max_payload(&fwspk->stream)); 291 amdtp_out_stream_get_max_payload(&fwspk->stream));