ALSA: fireworks: serialize transactions to update connections at bus reset
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sat, 20 Feb 2016 07:41:01 +0000 (16:41 +0900)
committerTakashi Iwai <tiwai@suse.de>
Sat, 20 Feb 2016 14:46:38 +0000 (15:46 +0100)
In IEC 61883-1, at bus-reset, applications can continue isochronous
streaming by updating connections. In ALSA fireworks driver, the
operation is executed in 'update' handler for bus driver.

The connection resources are also changed in process contexts of PCM/MIDI
applications. Therefore, bus-reset handling has race condition
against connection. Current ALSA fireworks driver has a bug for the
condition.

This commit fixes the bug, by expand critical section with mutex. As a
result, connection updating operation in bus-reset handler and connection
changing operation in process context are serialized.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/fireworks/fireworks.c
sound/firewire/fireworks/fireworks_stream.c

index d5b19bc11e5999480f030e682fa4087cc91067ac..8f27b67503c880bcf5d1c1e4a9e84ba2ad4bd006 100644 (file)
@@ -301,7 +301,10 @@ static void efw_update(struct fw_unit *unit)
        struct snd_efw *efw = dev_get_drvdata(&unit->device);
 
        snd_efw_transaction_bus_reset(efw->unit);
+
+       mutex_lock(&efw->mutex);
        snd_efw_stream_update_duplex(efw);
+       mutex_unlock(&efw->mutex);
 }
 
 static void efw_remove(struct fw_unit *unit)
index 968a40a1beb2cba3a48526cd776af08fa689e269..425db8d88235ad755b054f3701fc9b0c14072709 100644 (file)
@@ -313,12 +313,10 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw)
 
 void snd_efw_stream_update_duplex(struct snd_efw *efw)
 {
-       if ((cmp_connection_update(&efw->out_conn) < 0) ||
-           (cmp_connection_update(&efw->in_conn) < 0)) {
-               mutex_lock(&efw->mutex);
+       if (cmp_connection_update(&efw->out_conn) < 0 ||
+           cmp_connection_update(&efw->in_conn) < 0) {
                stop_stream(efw, &efw->rx_stream);
                stop_stream(efw, &efw->tx_stream);
-               mutex_unlock(&efw->mutex);
        } else {
                amdtp_stream_update(&efw->rx_stream);
                amdtp_stream_update(&efw->tx_stream);