summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-10-08 19:10:26 -0400
committerTakashi Iwai <tiwai@suse.de>2015-10-09 03:57:05 -0400
commitd3ef9cb93aec59eb1d90d01ae0642fd517c25381 (patch)
treeab00c5e5d1c4ce2b0b12a2614e229d78b806aff6
parent585d7cba5e1fcd8703a120042f35695165986b9b (diff)
ALSA: firewire-lib: add a restriction for a transaction at once
Currently, when waiting for a response, callers can start another transaction by scheduling another work. This is not good for error processing of transaction, especially the first response is too late. This commit serialize request/response transactions, by adding one boolean member to represent idling state. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/firewire/lib.c9
-rw-r--r--sound/firewire/lib.h1
2 files changed, 10 insertions, 0 deletions
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
index 03ada3f1047a..ddc3e88ee0d1 100644
--- a/sound/firewire/lib.c
+++ b/sound/firewire/lib.c
@@ -76,6 +76,8 @@ static void async_midi_port_callback(struct fw_card *card, int rcode,
76 76
77 if (rcode == RCODE_COMPLETE && substream != NULL) 77 if (rcode == RCODE_COMPLETE && substream != NULL)
78 snd_rawmidi_transmit_ack(substream, port->consume_bytes); 78 snd_rawmidi_transmit_ack(substream, port->consume_bytes);
79
80 port->idling = true;
79} 81}
80 82
81static void midi_port_work(struct work_struct *work) 83static void midi_port_work(struct work_struct *work)
@@ -86,6 +88,10 @@ static void midi_port_work(struct work_struct *work)
86 int generation; 88 int generation;
87 int type; 89 int type;
88 90
91 /* Under transacting. */
92 if (!port->idling)
93 return;
94
89 /* Nothing to do. */ 95 /* Nothing to do. */
90 if (substream == NULL || snd_rawmidi_transmit_empty(substream)) 96 if (substream == NULL || snd_rawmidi_transmit_empty(substream))
91 return; 97 return;
@@ -110,6 +116,8 @@ static void midi_port_work(struct work_struct *work)
110 type = TCODE_WRITE_BLOCK_REQUEST; 116 type = TCODE_WRITE_BLOCK_REQUEST;
111 117
112 /* Start this transaction. */ 118 /* Start this transaction. */
119 port->idling = false;
120
113 /* 121 /*
114 * In Linux FireWire core, when generation is updated with memory 122 * In Linux FireWire core, when generation is updated with memory
115 * barrier, node id has already been updated. In this module, After 123 * barrier, node id has already been updated. In this module, After
@@ -150,6 +158,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
150 port->parent = fw_parent_device(unit); 158 port->parent = fw_parent_device(unit);
151 port->addr = addr; 159 port->addr = addr;
152 port->fill = fill; 160 port->fill = fill;
161 port->idling = true;
153 162
154 INIT_WORK(&port->work, midi_port_work); 163 INIT_WORK(&port->work, midi_port_work);
155 164
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index 37a7fe4235f2..0af06f44e8c2 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -30,6 +30,7 @@ typedef int (*snd_fw_async_midi_port_fill)(
30struct snd_fw_async_midi_port { 30struct snd_fw_async_midi_port {
31 struct fw_device *parent; 31 struct fw_device *parent;
32 struct work_struct work; 32 struct work_struct work;
33 bool idling;
33 34
34 u64 addr; 35 u64 addr;
35 struct fw_transaction transaction; 36 struct fw_transaction transaction;