From: Arnd Bergmann Date: Fri, 21 Jun 2013 19:55:35 +0000 (+0200) Subject: staging: line6: avoid __sync_fetch_and_{and,or} X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=9f613601482c56e05884f21565e3d218fac427ae;p=linux-beck.git staging: line6: avoid __sync_fetch_and_{and,or} __sync_fetch_and_and and __sync_fetch_and_or are functions that are provided by gcc and depending on the target architecture may be implemented in libgcc, which is not always available in the kernel. This leads to a build failure on ARMv5: drivers/built-in.o: In function `line6_pcm_release': :(.text+0x3bfe80): undefined reference to `__sync_fetch_and_and_4' drivers/built-in.o: In function `line6_pcm_acquire': :(.text+0x3bff30): undefined reference to `__sync_fetch_and_or_4' To work around this, we can use the kernel-provided cmpxchg macro. Build-tested only. Signed-off-by: Arnd Bergmann Cc: Markus Grabner Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- 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, int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) { - unsigned long flags_old = - __sync_fetch_and_or(&line6pcm->flags, channels); - unsigned long flags_new = flags_old | channels; - unsigned long flags_final = flags_old; - int err = 0; + unsigned long flags_old, flags_new, flags_final; + int err; + + do { + flags_old = ACCESS_ONCE(line6pcm->flags); + flags_new = flags_old | channels; + } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); + + flags_final = flags_old; line6pcm->prev_fbuf = NULL; @@ -197,9 +201,12 @@ pcm_acquire_error: int line6_pcm_release(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; + 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);