[PATCH 5/6] sh: Emulate two-byte cmpxchg

Paul E. McKenney paulmck at kernel.org
Tue Sep 22 16:06:05 PDT 2026


On Wed, Sep 16, 2026 at 09:16:16PM +0200, John Paul Adrian Glaubitz wrote:
> Hi Bradley,
> 
> On Fri, 2026-09-11 at 19:25 +0000, Bradley Morgan wrote:
> > SH has no byte or halfword atomic memory operations, so the
> > __cmpxchg() switch routes case 1 through cmpxchg_emu_u8() and
> > lets case 2 fall through to __cmpxchg_called_with_bad_pointer(),
> > which is declared but never defined, so a two-byte cmpxchg()
> > fails at link time. Route case 2 through the new cmpxchg_emu_u16().
> > 
> > Signed-off-by: Bradley Morgan <brads at mainlining.org>
> > ---
> >  arch/sh/include/asm/cmpxchg.h | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
> > index 1e5dc5ccf7bf..477d3025a441 100644
> > --- a/arch/sh/include/asm/cmpxchg.h
> > +++ b/arch/sh/include/asm/cmpxchg.h
> > @@ -59,6 +59,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
> >  	switch (size) {
> >  	case 1:
> >  		return cmpxchg_emu_u8(ptr, old, new);
> > +	case 2:
> > +		return cmpxchg_emu_u16(ptr, old, new);
> >  	case 4:
> >  		return __cmpxchg_u32(ptr, old, new);
> >  	}
> 
> Odd, I thought this series was merged long time ago. Was there anything holding it back?
> 
> Either way:
> 
> Acked-by: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>

Thank you, John!

In my reshuffling, I associated the arch/sh/Kconfig change with the
cmpxchg.h changes, as shown below.  The idea is to show all the changes
for a given architecture in one place.  I kept your Acked-by, but please
let me know if this is in any way problematic.

						Thanx, Paul

------------------------------------------------------------------------

commit 662151462e30187c342cffcd250834a32a9eb67a
Author: Bradley Morgan <brads at mainlining.org>
Date:   Tue Sep 22 17:33:52 2026 +0000

    sh: Emulate two-byte cmpxchg
    
    SH has no byte or halfword atomic memory operations, so the __cmpxchg()
    switch routes case 1 through cmpxchg_emu_u8() and lets case 2 fall
    through to __cmpxchg_called_with_bad_pointer(), which is declared but
    never defined, so a two-byte cmpxchg() fails at link time. Route case
    2 through the new cmpxchg_emu_u16(), which takes the old and new
    values as unsigned long, so the (unsigned long) casts move off the
    call and into _old_ and _new_ declarations that type check the old
    and new arguments against *ptr through (unsigned long)(0 ? *ptr : _o_),
    the idiom David Laight suggested, so cmpxchg(&p, 4, 5) no longer
    compiles silently.
    
    Acked-by: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
    Signed-off-by: Bradley Morgan <brads at mainlining.org>
    Signed-off-by: Paul E. McKenney <paulmck at kernel.org>
    Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
    Cc: Rich Felker <dalias at libc.org>
    Cc: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
    Cc: <linux-sh at vger.kernel.org>

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d60f1d5a94c0..09e556fced01 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,7 +14,7 @@ config SUPERH
 	select ARCH_HIBERNATION_POSSIBLE if MMU
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_WANT_IPC_PARSE_VERSION
-	select ARCH_NEED_CMPXCHG_1_EMU
+	select ARCH_NEED_CMPXCHG_1_2_EMU
 	select CPU_NO_EFFICIENT_FFS
 	select DMA_DECLARE_COHERENT
 	select GENERIC_ATOMIC64
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
index 1e5dc5ccf7bf..b87f59107b4e 100644
--- a/arch/sh/include/asm/cmpxchg.h
+++ b/arch/sh/include/asm/cmpxchg.h
@@ -59,6 +59,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
 	switch (size) {
 	case 1:
 		return cmpxchg_emu_u8(ptr, old, new);
+	case 2:
+		return cmpxchg_emu_u16(ptr, old, new);
 	case 4:
 		return __cmpxchg_u32(ptr, old, new);
 	}
@@ -70,8 +72,10 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
   ({									 \
      __typeof__(*(ptr)) _o_ = (o);					 \
      __typeof__(*(ptr)) _n_ = (n);					 \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
-				    (unsigned long)_n_, sizeof(*(ptr))); \
+     unsigned long _old_ = (unsigned long)(0 ? *ptr : _o_);	 \
+     unsigned long _new_ = (unsigned long)(0 ? *ptr : _n_);	 \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), _old_,				 \
+				    _new_, sizeof(*(ptr)));	 \
   })
 
 #include <asm-generic/cmpxchg-local.h>



More information about the linux-arm-kernel mailing list