Skip to content

Commit

Permalink
ALSA: fireworks/bebob/dice/oxfw: fix substreams counting at vmalloc f…
Browse files Browse the repository at this point in the history
…ailure

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>
  • Loading branch information
takaswie authored and tiwai committed Aug 29, 2015
1 parent 6aa6925 commit 22c103c
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
20 changes: 16 additions & 4 deletions sound/firewire/bebob/bebob_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 14 additions & 4 deletions sound/firewire/dice/dice-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down
18 changes: 14 additions & 4 deletions sound/firewire/fireworks/fireworks_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 13 additions & 4 deletions sound/firewire/oxfw/oxfw-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down

0 comments on commit 22c103c

Please sign in to comment.