From: Takashi Iwai Date: Fri, 23 Jan 2015 13:34:42 +0000 (+0100) Subject: ALSA: line6: Fix the error recovery in line6_pcm_acquire() X-Git-Tag: v4.0-rc1~129^2~35^2~17 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=5343ecf4e5c94aecdd6a859b76c125c3544865d1;p=linux.git ALSA: line6: Fix the error recovery in line6_pcm_acquire() line6_pcm_acquire() tries to restore the newly obtained resources at the error path. But some flags aren't recorded and released properly when the corresponding buffer is already present. These bits have to be cleared in the error recovery, too. Also, "flags_final" can be initialized to zero since we pass only the subset of "channels" bits. Tested-by: Chris Rorvick Signed-off-by: Takashi Iwai --- diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index f740b4490d75..9a2a15f4c4e4 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -106,7 +106,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) flags_new = flags_old | channels; } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); - flags_final = flags_old; + flags_final = 0; line6pcm->prev_fbuf = NULL; @@ -120,9 +120,9 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) err = -ENOMEM; goto pcm_acquire_error; } - - flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER; } + + flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER; } if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) { @@ -157,9 +157,9 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) err = -ENOMEM; goto pcm_acquire_error; } - - flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER; } + + flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER; } if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) { @@ -187,7 +187,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) If not all requested resources/streams could be obtained, release those which were successfully obtained (if any). */ - line6_pcm_release(line6pcm, flags_final & channels); + line6_pcm_release(line6pcm, flags_final); return err; } EXPORT_SYMBOL_GPL(line6_pcm_acquire);