Commit bde3e288 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

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: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent ea848b7b
...@@ -79,6 +79,9 @@ static void async_midi_port_callback(struct fw_card *card, int rcode, ...@@ -79,6 +79,9 @@ static void async_midi_port_callback(struct fw_card *card, int rcode,
else if (!rcode_is_permanent_error(rcode)) else if (!rcode_is_permanent_error(rcode))
/* To start next transaction immediately for recovery. */ /* To start next transaction immediately for recovery. */
port->next_ktime = ktime_set(0, 0); port->next_ktime = ktime_set(0, 0);
else
/* Don't continue processing. */
port->error = true;
port->idling = true; port->idling = true;
...@@ -94,8 +97,8 @@ static void midi_port_work(struct work_struct *work) ...@@ -94,8 +97,8 @@ static void midi_port_work(struct work_struct *work)
int generation; int generation;
int type; int type;
/* Under transacting. */ /* Under transacting or error state. */
if (!port->idling) if (!port->idling || port->error)
return; return;
/* Nothing to do. */ /* Nothing to do. */
...@@ -119,6 +122,9 @@ static void midi_port_work(struct work_struct *work) ...@@ -119,6 +122,9 @@ static void midi_port_work(struct work_struct *work)
if (port->consume_bytes == 0) { if (port->consume_bytes == 0) {
port->next_ktime = ktime_set(0, 0); port->next_ktime = ktime_set(0, 0);
schedule_work(&port->work); schedule_work(&port->work);
} else {
/* Fatal error. */
port->error = true;
} }
return; return;
} }
...@@ -178,6 +184,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port, ...@@ -178,6 +184,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
port->fill = fill; port->fill = fill;
port->idling = true; port->idling = true;
port->next_ktime = ktime_set(0, 0); port->next_ktime = ktime_set(0, 0);
port->error = false;
INIT_WORK(&port->work, midi_port_work); INIT_WORK(&port->work, midi_port_work);
......
...@@ -32,6 +32,7 @@ struct snd_fw_async_midi_port { ...@@ -32,6 +32,7 @@ struct snd_fw_async_midi_port {
struct work_struct work; struct work_struct work;
bool idling; bool idling;
ktime_t next_ktime; ktime_t next_ktime;
bool error;
u64 addr; u64 addr;
struct fw_transaction transaction; struct fw_transaction transaction;
...@@ -58,8 +59,10 @@ static inline void ...@@ -58,8 +59,10 @@ static inline void
snd_fw_async_midi_port_run(struct snd_fw_async_midi_port *port, snd_fw_async_midi_port_run(struct snd_fw_async_midi_port *port,
struct snd_rawmidi_substream *substream) struct snd_rawmidi_substream *substream)
{ {
port->substream = substream; if (!port->error) {
schedule_work(&port->work); port->substream = substream;
schedule_work(&port->work);
}
} }
/** /**
...@@ -70,6 +73,7 @@ static inline void ...@@ -70,6 +73,7 @@ static inline void
snd_fw_async_midi_port_finish(struct snd_fw_async_midi_port *port) snd_fw_async_midi_port_finish(struct snd_fw_async_midi_port *port)
{ {
port->substream = NULL; port->substream = NULL;
port->error = false;
} }
#endif #endif
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