summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2016-02-24 09:26:33 +0900
committerTakashi Iwai <tiwai@suse.de>2016-02-24 16:32:08 +0100
commit956dea9e911253e34fa1773da07a6c4044e20817 (patch)
tree925226fb8a2ecaccc34f8b1125e76281cbff3ce2
parentb4c23ab1cbfedbebf9f7eecd1bd8a7989f388649 (diff)
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: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/firewire/oxfw/oxfw-scs1x.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
index 72446ac33ea7..f897c9831077 100644
--- a/sound/firewire/oxfw/oxfw-scs1x.c
+++ b/sound/firewire/oxfw/oxfw-scs1x.c
@@ -32,6 +32,7 @@ struct fw_scs1x {
bool transaction_running;
struct fw_transaction transaction;
unsigned int transaction_bytes;
+ bool error;
struct fw_device *fw_dev;
};
@@ -126,8 +127,13 @@ static void scs_write_callback(struct fw_card *card, int rcode,
{
struct fw_scs1x *scs = callback_data;
- if (rcode != RCODE_GENERATION)
- scs->transaction_bytes = 0;
+ if (!rcode_is_permanent_error(rcode)) {
+ /* Don't retry for this data. */
+ if (rcode == RCODE_COMPLETE)
+ scs->transaction_bytes = 0;
+ } else {
+ scs->error = true;
+ }
scs->transaction_running = false;
schedule_work(&scs->work);
@@ -178,7 +184,7 @@ static void scs_output_work(struct work_struct *work)
return;
stream = ACCESS_ONCE(scs->output);
- if (!stream) {
+ if (!stream || scs->error) {
scs->output_idle = true;
wake_up(&scs->idle_wait);
return;
@@ -317,6 +323,7 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
scs->output_escaped = false;
scs->output_idle = false;
scs->transaction_bytes = 0;
+ scs->error = false;
ACCESS_ONCE(scs->output) = stream;
schedule_work(&scs->work);