diff options
-rw-r--r-- | drivers/staging/line6/pcm.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index 02f77d74809f..4795f1284906 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c | |||
@@ -107,11 +107,15 @@ static bool test_flags(unsigned long flags0, unsigned long flags1, | |||
107 | 107 | ||
108 | int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) | 108 | int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) |
109 | { | 109 | { |
110 | unsigned long flags_old = | 110 | unsigned long flags_old, flags_new, flags_final; |
111 | __sync_fetch_and_or(&line6pcm->flags, channels); | 111 | int err; |
112 | unsigned long flags_new = flags_old | channels; | 112 | |
113 | unsigned long flags_final = flags_old; | 113 | do { |
114 | int err = 0; | 114 | flags_old = ACCESS_ONCE(line6pcm->flags); |
115 | flags_new = flags_old | channels; | ||
116 | } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); | ||
117 | |||
118 | flags_final = flags_old; | ||
115 | 119 | ||
116 | line6pcm->prev_fbuf = NULL; | 120 | line6pcm->prev_fbuf = NULL; |
117 | 121 | ||
@@ -197,9 +201,12 @@ pcm_acquire_error: | |||
197 | 201 | ||
198 | int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) | 202 | int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) |
199 | { | 203 | { |
200 | unsigned long flags_old = | 204 | unsigned long flags_old, flags_new; |
201 | __sync_fetch_and_and(&line6pcm->flags, ~channels); | 205 | |
202 | unsigned long flags_new = flags_old & ~channels; | 206 | do { |
207 | flags_old = ACCESS_ONCE(line6pcm->flags); | ||
208 | flags_new = flags_old & ~channels; | ||
209 | } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); | ||
203 | 210 | ||
204 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) | 211 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) |
205 | line6_unlink_audio_in_urbs(line6pcm); | 212 | line6_unlink_audio_in_urbs(line6pcm); |