3.2.70-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Arnd Bergmann <arnd@xxxxxxxx> commit 9f613601482c56e05884f21565e3d218fac427ae upstream. __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 <arnd@xxxxxxxx> Cc: Markus Grabner <grabner@xxxxxxxxxxxxx> Acked-by: Randy Dunlap <rdunlap@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> [bwh: Backported to 3.2: - Adjust context - Fix up two more instances of __sync_fetch_and_and() that were removed separately upstream] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/staging/line6/pcm.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -88,10 +88,13 @@ static DEVICE_ATTR(impulse_period, S_IWU int line6_pcm_start(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; - int err = 0; + unsigned long flags_old, flags_new; + int err; + + do { + flags_old = ACCESS_ONCE(line6pcm->flags); + flags_new = flags_old | channels; + } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); #if LINE6_BACKUP_MONITOR_SIGNAL if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) { @@ -133,10 +136,8 @@ int line6_pcm_start(struct snd_line6_pcm line6pcm->prev_fsize = 0; err = line6_submit_audio_in_all_urbs(line6pcm); - if (err < 0) { - __sync_fetch_and_and(&line6pcm->flags, ~channels); - return err; - } + if (err < 0) + goto fail; } if (((flags_old & MASK_PLAYBACK) == 0) && @@ -160,20 +161,29 @@ int line6_pcm_start(struct snd_line6_pcm line6pcm->count_out = 0; err = line6_submit_audio_out_all_urbs(line6pcm); - if (err < 0) { - __sync_fetch_and_and(&line6pcm->flags, ~channels); - return err; - } + if (err < 0) + goto fail; } return 0; + +fail: + do { + flags_old = ACCESS_ONCE(line6pcm->flags); + flags_new = flags_old & ~channels; + } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); + + return err; } 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; + 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 (((flags_old & MASK_CAPTURE) != 0) && ((flags_new & MASK_CAPTURE) == 0)) { -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html