ALSA: fireworks/bebob/dice/oxfw: fix substreams counting at vmalloc failure
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sat, 29 Aug 2015 01:38:46 +0000 (10:38 +0900)
committerTakashi Iwai <tiwai@suse.de>
Sat, 29 Aug 2015 07:14:41 +0000 (09:14 +0200)
In PCM core, when hw_params() in each driver returns error, the state of
PCM substream is kept as 'open'. In this case, current drivers for sound
units on IEEE 1394 bus doesn't decrement substream counter in hw_free()
correctly. This causes these drivers to keep streams even if not
required.

This commit fixes this bug. When snd_pcm_lib_alloc_vmalloc_buffer()
fails, hw_params function in each driver returns without incrementing the
counter.

Reported-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Acked-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/firewire/bebob/bebob_pcm.c
sound/firewire/dice/dice-pcm.c
sound/firewire/fireworks/fireworks_pcm.c
sound/firewire/oxfw/oxfw-pcm.c

index 7a2c1f53bc4436e018b3081507f8577420bc869a..c0f018a61fdc039b0e331a40d9bed4e305645320 100644 (file)
@@ -211,26 +211,38 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream,
                      struct snd_pcm_hw_params *hw_params)
 {
        struct snd_bebob *bebob = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
                atomic_inc(&bebob->substreams_counter);
        amdtp_stream_set_pcm_format(&bebob->tx_stream,
                                    params_format(hw_params));
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+
+       return 0;
 }
 static int
 pcm_playback_hw_params(struct snd_pcm_substream *substream,
                       struct snd_pcm_hw_params *hw_params)
 {
        struct snd_bebob *bebob = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
                atomic_inc(&bebob->substreams_counter);
        amdtp_stream_set_pcm_format(&bebob->rx_stream,
                                    params_format(hw_params));
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+
+       return 0;
 }
 
 static int
index f77714511f8b5c2e309ca91af4bddab506283883..4e67b1da0fe6ffbe9350b0e17a71a87f2b03e73b 100644 (file)
@@ -230,6 +230,12 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *hw_params)
 {
        struct snd_dice *dice = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                mutex_lock(&dice->mutex);
@@ -240,13 +246,18 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
        amdtp_stream_set_pcm_format(&dice->tx_stream,
                                    params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 static int playback_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *hw_params)
 {
        struct snd_dice *dice = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                mutex_lock(&dice->mutex);
@@ -257,8 +268,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream,
        amdtp_stream_set_pcm_format(&dice->rx_stream,
                                    params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int capture_hw_free(struct snd_pcm_substream *substream)
index 8a34753de210831070643abd8e24b5ae10f89781..c30b2ffa8dfb1db8354c25b4681938ac82627194 100644 (file)
@@ -244,25 +244,35 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
        struct snd_efw *efw = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
                atomic_inc(&efw->capture_substreams);
        amdtp_stream_set_pcm_format(&efw->tx_stream, params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *hw_params)
 {
        struct snd_efw *efw = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
                atomic_inc(&efw->playback_substreams);
        amdtp_stream_set_pcm_format(&efw->rx_stream, params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
index 67ade0775a5b21b45329ef54db02a5a812b966ae..9c73930d0278820a11fd46a2db2fb877b6a61a88 100644 (file)
@@ -231,7 +231,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
        struct snd_oxfw *oxfw = substream->private_data;
+       int err;
 
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                mutex_lock(&oxfw->mutex);
@@ -241,13 +246,18 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
 
        amdtp_stream_set_pcm_format(&oxfw->tx_stream, params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *hw_params)
 {
        struct snd_oxfw *oxfw = substream->private_data;
+       int err;
+
+       err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                              params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                mutex_lock(&oxfw->mutex);
@@ -257,8 +267,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
 
        amdtp_stream_set_pcm_format(&oxfw->rx_stream, params_format(hw_params));
 
-       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-                                               params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)