diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2016-02-24 03:26:32 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-24 18:31:54 +0300 |
commit | b4c23ab1cbfedbebf9f7eecd1bd8a7989f388649 (patch) | |
tree | 09b0188e820d211a61482afec313e4ffb69d9f85 /sound/firewire | |
parent | fb087eaaef72061b2bb4e35b70ab43865f541cad (diff) | |
download | linux-b4c23ab1cbfedbebf9f7eecd1bd8a7989f388649.tar.xz |
ALSA: oxfw: retry MIDI transferring for scs1x at transaction failure
Currently, ALSA oxfw driver has a TODO to retry MIDI transferring
at transaction failure.
This commit achieves it. Current implementation uses snd_rawmidi_transmit()
to transfer messages, thus the target MIDI messages are not in buffer when
transaction failure is detected. Although we cannot use a pair of
snd_rawmidi_transmit_peek() and snd_ramwidi_transmit_ack(), the
messages are still in scs1x specific structure and the data is available
for retries.
This commit adds a member to the structure for the length of buffered
messages, and uses the value again at retries.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/oxfw/oxfw-scs1x.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c index f7ac1243ec94..72446ac33ea7 100644 --- a/sound/firewire/oxfw/oxfw-scs1x.c +++ b/sound/firewire/oxfw/oxfw-scs1x.c @@ -31,6 +31,7 @@ struct fw_scs1x { u8 buffer[HSS1394_MAX_PACKET_SIZE]; bool transaction_running; struct fw_transaction transaction; + unsigned int transaction_bytes; struct fw_device *fw_dev; }; @@ -125,8 +126,8 @@ static void scs_write_callback(struct fw_card *card, int rcode, { struct fw_scs1x *scs = callback_data; - if (rcode == RCODE_GENERATION) - ; /* TODO: retry this packet */ + if (rcode != RCODE_GENERATION) + scs->transaction_bytes = 0; scs->transaction_running = false; schedule_work(&scs->work); @@ -183,6 +184,9 @@ static void scs_output_work(struct work_struct *work) return; } + if (scs->transaction_bytes > 0) + goto retry; + i = scs->output_bytes; for (;;) { if (snd_rawmidi_transmit(stream, &byte, 1) != 1) { @@ -253,13 +257,16 @@ static void scs_output_work(struct work_struct *work) scs->output_bytes = 1; scs->output_escaped = false; + scs->transaction_bytes = i; +retry: scs->transaction_running = true; generation = scs->fw_dev->generation; smp_rmb(); /* node_id vs. generation */ fw_send_request(scs->fw_dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST, scs->fw_dev->node_id, generation, scs->fw_dev->max_speed, HSS1394_ADDRESS, - scs->buffer, i, scs_write_callback, scs); + scs->buffer, scs->transaction_bytes, + scs_write_callback, scs); } static int midi_capture_open(struct snd_rawmidi_substream *stream) @@ -309,6 +316,7 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up) scs->output_bytes = 1; scs->output_escaped = false; scs->output_idle = false; + scs->transaction_bytes = 0; ACCESS_ONCE(scs->output) = stream; schedule_work(&scs->work); |