summaryrefslogtreecommitdiff
path: root/sound/firewire/lib.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-10-09 02:10:29 +0300
committerTakashi Iwai <tiwai@suse.de>2015-10-09 10:57:06 +0300
commitbde3e2880ff92f9956914afdd19648ccb20f487a (patch)
tree979aaf8249fd2c7b6037b48c2e45220993d57da1 /sound/firewire/lib.c
parentea848b7b62ab6d3078955b87833c3b336b71bc9f (diff)
downloadlinux-bde3e2880ff92f9956914afdd19648ccb20f487a.tar.xz
ALSA: firewire-lib: avoid endless loop to transfer MIDI messages at fatal error
Currently, when asynchronous transactions finish in error state and retries, work scheduling and work running also continues. This should be canceled at fatal error because it can cause endless loop. This commit enables to cancel transferring MIDI messages when transactions encounter fatal errors. This is achieved by setting error state. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/lib.c')
-rw-r--r--sound/firewire/lib.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
index 9a98c7cd8744..edf1c8bd25a6 100644
--- a/sound/firewire/lib.c
+++ b/sound/firewire/lib.c
@@ -79,6 +79,9 @@ static void async_midi_port_callback(struct fw_card *card, int rcode,
else if (!rcode_is_permanent_error(rcode))
/* To start next transaction immediately for recovery. */
port->next_ktime = ktime_set(0, 0);
+ else
+ /* Don't continue processing. */
+ port->error = true;
port->idling = true;
@@ -94,8 +97,8 @@ static void midi_port_work(struct work_struct *work)
int generation;
int type;
- /* Under transacting. */
- if (!port->idling)
+ /* Under transacting or error state. */
+ if (!port->idling || port->error)
return;
/* Nothing to do. */
@@ -119,6 +122,9 @@ static void midi_port_work(struct work_struct *work)
if (port->consume_bytes == 0) {
port->next_ktime = ktime_set(0, 0);
schedule_work(&port->work);
+ } else {
+ /* Fatal error. */
+ port->error = true;
}
return;
}
@@ -178,6 +184,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
port->fill = fill;
port->idling = true;
port->next_ktime = ktime_set(0, 0);
+ port->error = false;
INIT_WORK(&port->work, midi_port_work);