int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) { unsigned long flags_old, flags_new; do { flags_old = ACCESS_ONCE(line6pcm->flags); flags_new = flags_old & ~channels; } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) line6_unlink_audio_in_urbs(line6pcm); if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { line6_wait_clear_audio_in_urbs(line6pcm); line6_free_capture_buffer(line6pcm); } if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) line6_unlink_audio_out_urbs(line6pcm); if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { line6_wait_clear_audio_out_urbs(line6pcm); line6_free_playback_buffer(line6pcm); } return 0; }
int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) { unsigned long flags_old = __sync_fetch_and_and(&line6pcm->flags, ~channels); unsigned long flags_new = flags_old & ~channels; if (test_flags(flags_new, flags_old, MASK_CAPTURE)) { line6_unlink_audio_in_urbs(line6pcm); if (!(flags_old & MASK_PCM_ALSA_CAPTURE)) line6_free_capture_buffer(line6pcm); } if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) { line6_unlink_audio_out_urbs(line6pcm); if (!(flags_old & MASK_PCM_ALSA_PLAYBACK)) line6_free_playback_buffer(line6pcm); } return 0; }