staging: line6: avoid __sync_fetch_and_{and,or}
PATCH 1/1 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.
drivers/staging/line6/pcm.c +15 -8
@@ -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);
Quoted 4 lines · Arnd Bergmann
__sync_fetch_and_andand__sync_fetch_and_orare 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:
and on x86_64.
Thanks.
Quoted 56 lines
drivers/built-in.o: In function `line6_pcm_release':
:(.text+0x3bfe80): undefined reference to__sync_fetch_and_and_4' drivers/built-in.o: In functionline6_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 <[email protected]>Cc Greg Kroah-Hartman <[email protected]>Cc Markus Grabner <[email protected]>drivers/staging/line6/pcm.c +15
-9@@ -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); --
Signature · 1 line
~Randy