From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753571AbbHBALo (ORCPT ); Sat, 1 Aug 2015 20:11:44 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:36080 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751911AbbHBAJt (ORCPT ); Sat, 1 Aug 2015 20:09:49 -0400 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Markus Grabner" , "Greg Kroah-Hartman" , "Randy Dunlap" , "Arnd Bergmann" Date: Sun, 02 Aug 2015 01:02:38 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.2 159/164] staging: line6: avoid __sync_fetch_and_{and,or} In-Reply-To: X-SA-Exim-Connect-IP: 192.168.4.249 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.2.70-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Arnd Bergmann 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 Cc: Markus Grabner Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman [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 --- 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)) {