summaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2016-02-24 01:26:32 +0100
committerTakashi Iwai <tiwai@suse.de>2016-02-24 16:31:54 +0100
commitb4c23ab1cbfedbebf9f7eecd1bd8a7989f388649 (patch)
tree09b0188e820d211a61482afec313e4ffb69d9f85 /sound/firewire
parentALSA: hda - hdmi eld control created based on pcm (diff)
downloadlinux-b4c23ab1cbfedbebf9f7eecd1bd8a7989f388649.tar.xz
linux-b4c23ab1cbfedbebf9f7eecd1bd8a7989f388649.zip
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.c14
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);