Commit 956dea9e authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: oxfw: discontinue MIDI substream for scs1x at transaction failure

With a previous commit, ALSA oxfw driver retries transferring MIDI
messages at transaction failure for scs1x. On the other hand, there're
fatal transaction error. Then, no MIDI messages reach to the unit anymore.
In this case, MIDI substream should be terminated.

This commit stops MIDI transmission after the fatal error occurs.
Unfortunately, unlike ALSA PCM functionality, ALSA rawmidi core has no
feature to discontinue MIDI substream runtime in kernel side, thus this
commit just stops MIDI transmission without notifying it to userspace.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b4c23ab1
...@@ -32,6 +32,7 @@ struct fw_scs1x { ...@@ -32,6 +32,7 @@ struct fw_scs1x {
bool transaction_running; bool transaction_running;
struct fw_transaction transaction; struct fw_transaction transaction;
unsigned int transaction_bytes; unsigned int transaction_bytes;
bool error;
struct fw_device *fw_dev; struct fw_device *fw_dev;
}; };
...@@ -126,8 +127,13 @@ static void scs_write_callback(struct fw_card *card, int rcode, ...@@ -126,8 +127,13 @@ static void scs_write_callback(struct fw_card *card, int rcode,
{ {
struct fw_scs1x *scs = callback_data; struct fw_scs1x *scs = callback_data;
if (rcode != RCODE_GENERATION) if (!rcode_is_permanent_error(rcode)) {
scs->transaction_bytes = 0; /* Don't retry for this data. */
if (rcode == RCODE_COMPLETE)
scs->transaction_bytes = 0;
} else {
scs->error = true;
}
scs->transaction_running = false; scs->transaction_running = false;
schedule_work(&scs->work); schedule_work(&scs->work);
...@@ -178,7 +184,7 @@ static void scs_output_work(struct work_struct *work) ...@@ -178,7 +184,7 @@ static void scs_output_work(struct work_struct *work)
return; return;
stream = ACCESS_ONCE(scs->output); stream = ACCESS_ONCE(scs->output);
if (!stream) { if (!stream || scs->error) {
scs->output_idle = true; scs->output_idle = true;
wake_up(&scs->idle_wait); wake_up(&scs->idle_wait);
return; return;
...@@ -317,6 +323,7 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up) ...@@ -317,6 +323,7 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
scs->output_escaped = false; scs->output_escaped = false;
scs->output_idle = false; scs->output_idle = false;
scs->transaction_bytes = 0; scs->transaction_bytes = 0;
scs->error = false;
ACCESS_ONCE(scs->output) = stream; ACCESS_ONCE(scs->output) = stream;
schedule_work(&scs->work); schedule_work(&scs->work);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment