s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
+ s->packet_index = 0;
return 0;
}
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);
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;
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;
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)
struct snd_pcm_substream *pcm;
- unsigned int packet_counter;
+ int packet_index;
unsigned int data_block_counter;
unsigned int data_block_state;
s->midi_ports = midi_ports;
}
+/**
+ * amdtp_out_streaming_error - check for streaming error
+ * @s: the AMDTP output stream
+ *
+ * If this function returns true, the stream's packet queue has stopped due to
+ * an asynchronous error.
+ */
+static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
+{
+ return s->packet_index < 0;
+}
+
/**
* amdtp_out_stream_pcm_prepare - prepare PCM device for running
* @s: the AMDTP output stream