[07/25] ALSA: firewire-lib: avoid endless loop to transfer MIDI messages at fatal error
diff mbox

Message ID 1439425221-30826-8-git-send-email-o-takashi@sakamocchi.jp
State New
Headers show

Commit Message

Takashi Sakamoto Aug. 13, 2015, 12:20 a.m. UTC
Currently, when asynchronous transactions finish in error state and
retries, tasklet scheduling and tasklet running also continues. This
should be canceled at fatal error because it can cause endless loop.

This commit cancels transferring MIDI messages when transactions encounter
fatal error, by setting error state.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/lib.c | 11 +++++++++--
 sound/firewire/lib.h |  8 ++++++--
 2 files changed, 15 insertions(+), 4 deletions(-)

Patch
diff mbox

diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
index 452728c..387505f 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_tick = 0;
+	else
+		/* Don't continue processing. */
+		port->error = true;
 
 	port->idling = true;
 
@@ -94,8 +97,8 @@  static void midi_port_tasklet(unsigned long data)
 	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_tasklet(unsigned long data)
 		if (port->consume_bytes == 0) {
 			port->next_tick = 0;
 			tasklet_schedule(&port->tasklet);
+		} else {
+			/* Fatal error. */
+			port->error = true;
 		}
 		return;
 	}
@@ -169,6 +175,7 @@  int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
 	port->packetize = packetize;
 	port->idling = true;
 	port->next_tick = 0;
+	port->error = false;
 
 	tasklet_init(&port->tasklet, midi_port_tasklet, (unsigned long)port);
 
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index e4b00e2..ebac516 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -27,6 +27,7 @@  struct snd_fw_async_midi_port {
 	struct tasklet_struct tasklet;
 	bool idling;
 	unsigned long next_tick;
+	bool error;
 
 	__u64 addr;
 	struct fw_transaction transaction;
@@ -54,8 +55,10 @@  static inline void
 snd_fw_async_midi_port_run(struct snd_fw_async_midi_port *port,
 			   struct snd_rawmidi_substream *substream)
 {
-	port->substream = substream;
-	tasklet_schedule(&port->tasklet);
+	if (!port->error) {
+		port->substream = substream;
+		tasklet_schedule(&port->tasklet);
+	}
 }
 
 /**
@@ -66,6 +69,7 @@  static inline void
 snd_fw_async_midi_port_finish(struct snd_fw_async_midi_port *port)
 {
 	port->substream = NULL;
+	port->error = false;
 }
 
 #endif