Re: [PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
On Tue, Dec 22, 2020 at 01:52:50PM +1000, Nicholas Piggin wrote: > Excerpts from Boqun Feng's message of November 14, 2020 1:30 am: > > Hi Nicholas, > > > > On Wed, Nov 11, 2020 at 09:07:23PM +1000, Nicholas Piggin wrote: > >> All the cool kids are doing it. > >> > >> Signed-off-by: Nicholas Piggin > >> --- > >> arch/powerpc/include/asm/atomic.h | 681 ++--- > >> arch/powerpc/include/asm/cmpxchg.h | 62 +-- > >> 2 files changed, 248 insertions(+), 495 deletions(-) > >> > >> diff --git a/arch/powerpc/include/asm/atomic.h > >> b/arch/powerpc/include/asm/atomic.h > >> index 8a55eb8cc97b..899aa2403ba7 100644 > >> --- a/arch/powerpc/include/asm/atomic.h > >> +++ b/arch/powerpc/include/asm/atomic.h > >> @@ -11,185 +11,285 @@ > >> #include > >> #include > >> > >> +#define ARCH_ATOMIC > >> + > >> +#ifndef CONFIG_64BIT > >> +#include > >> +#endif > >> + > >> /* > >> * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with > >> * a "bne-" instruction at the end, so an isync is enough as a acquire > >> barrier > >> * on the platform without lwsync. > >> */ > >> #define __atomic_acquire_fence() \ > >> - __asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory") > >> + asm volatile(PPC_ACQUIRE_BARRIER "" : : : "memory") > >> > >> #define __atomic_release_fence() \ > >> - __asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory") > >> + asm volatile(PPC_RELEASE_BARRIER "" : : : "memory") > >> > >> -static __inline__ int atomic_read(const atomic_t *v) > >> -{ > >> - int t; > >> +#define __atomic_pre_full_fence smp_mb > >> > >> - __asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter)); > >> +#define __atomic_post_full_fence smp_mb > >> > > Thanks for the review. > > > Do you need to define __atomic_{pre,post}_full_fence for PPC? IIRC, they > > are default smp_mb__{before,atomic}_atomic(), so are smp_mb() defautly > > on PPC. > > Okay I didn't realise that's not required. > > >> - return t; > >> +#define arch_atomic_read(v) > >> __READ_ONCE((v)->counter) > >> +#define arch_atomic_set(v, i) > >> __WRITE_ONCE(((v)->counter), (i)) > >> +#ifdef CONFIG_64BIT > >> +#define ATOMIC64_INIT(i) { (i) } > >> +#define arch_atomic64_read(v) > >> __READ_ONCE((v)->counter) > >> +#define arch_atomic64_set(v, i) > >> __WRITE_ONCE(((v)->counter), (i)) > >> +#endif > >> + > > [...] > >> > >> +#define ATOMIC_FETCH_OP_UNLESS_RELAXED(name, type, dtype, width, asm_op) \ > >> +static inline int arch_##name##_relaxed(type *v, dtype a, dtype u) > >> \ > > > > I don't think we have atomic_fetch_*_unless_relaxed() at atomic APIs, > > ditto for: > > > > atomic_fetch_add_unless_relaxed() > > atomic_inc_not_zero_relaxed() > > atomic_dec_if_positive_relaxed() > > > > , and we don't have the _acquire() and _release() variants for them > > either, and if you don't define their fully-ordered version (e.g. > > atomic_inc_not_zero()), atomic-arch-fallback.h will use read and cmpxchg > > to implement them, and I think not what we want. > > Okay. How can those be added? The atoimc generation is pretty > complicated. > Yeah, I know ;-) I think you can just implement and define fully-ordered verions: arch_atomic_fetch_*_unless() arch_atomic_inc_not_zero() arch_atomic_dec_if_postive() , that should work. Rules of atomic generation, IIRC: 1. If you define _relaxed, _acquire, _release or fully-ordered version, atomic generation will use that version 2. If you define _relaxed, atomic generation will use that and barriers to generate _acquire, _release and fully-ordered versions, unless they are already defined (as Rule #1 says) 3. If you don't define _relaxed, but define the fully-ordered version, atomic generation will use the fully-ordered version and use it as _relaxed variants and generate the rest using Rule #2. > > [...] > >> > >> #endif /* __KERNEL__ */ > >> #endif /* _ASM_POWERPC_ATOMIC_H_ */ > >> diff --git a/arch/powerpc/include/asm/cmpxchg.h > >> b/arch/powerpc/include/asm/cmpxchg.h > >> index cf091c4c22e5..181f7e8b3281 100644 > >> --- a/arch/powerpc/include/asm/cmpxchg.h > >> +++ b/arch/powerpc/include/asm/cmpxchg.h > >> @@ -192,7 +192,7 @@ __xchg_relaxed(void *ptr, unsigned long x, unsigned > >> int size) > >>(unsigned long)_x_, sizeof(*(ptr))); > >> \ > >>}) > >> > >> -#define xchg_relaxed(ptr, x) > >> \ > >> +#define arch_xchg_relaxed(ptr, x) \ > >> ({ > >> \ > >>__typeof__(*(ptr)) _x_ = (x); \ > >>(__typeof__(*(ptr)))
Re: [PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
Excerpts from Boqun Feng's message of November 14, 2020 1:30 am: > Hi Nicholas, > > On Wed, Nov 11, 2020 at 09:07:23PM +1000, Nicholas Piggin wrote: >> All the cool kids are doing it. >> >> Signed-off-by: Nicholas Piggin >> --- >> arch/powerpc/include/asm/atomic.h | 681 ++--- >> arch/powerpc/include/asm/cmpxchg.h | 62 +-- >> 2 files changed, 248 insertions(+), 495 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/atomic.h >> b/arch/powerpc/include/asm/atomic.h >> index 8a55eb8cc97b..899aa2403ba7 100644 >> --- a/arch/powerpc/include/asm/atomic.h >> +++ b/arch/powerpc/include/asm/atomic.h >> @@ -11,185 +11,285 @@ >> #include >> #include >> >> +#define ARCH_ATOMIC >> + >> +#ifndef CONFIG_64BIT >> +#include >> +#endif >> + >> /* >> * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with >> * a "bne-" instruction at the end, so an isync is enough as a acquire >> barrier >> * on the platform without lwsync. >> */ >> #define __atomic_acquire_fence()\ >> -__asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory") >> +asm volatile(PPC_ACQUIRE_BARRIER "" : : : "memory") >> >> #define __atomic_release_fence()\ >> -__asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory") >> +asm volatile(PPC_RELEASE_BARRIER "" : : : "memory") >> >> -static __inline__ int atomic_read(const atomic_t *v) >> -{ >> -int t; >> +#define __atomic_pre_full_fence smp_mb >> >> -__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter)); >> +#define __atomic_post_full_fencesmp_mb >> Thanks for the review. > Do you need to define __atomic_{pre,post}_full_fence for PPC? IIRC, they > are default smp_mb__{before,atomic}_atomic(), so are smp_mb() defautly > on PPC. Okay I didn't realise that's not required. >> -return t; >> +#define arch_atomic_read(v) __READ_ONCE((v)->counter) >> +#define arch_atomic_set(v, i) >> __WRITE_ONCE(((v)->counter), (i)) >> +#ifdef CONFIG_64BIT >> +#define ATOMIC64_INIT(i){ (i) } >> +#define arch_atomic64_read(v) >> __READ_ONCE((v)->counter) >> +#define arch_atomic64_set(v, i) >> __WRITE_ONCE(((v)->counter), (i)) >> +#endif >> + > [...] >> >> +#define ATOMIC_FETCH_OP_UNLESS_RELAXED(name, type, dtype, width, asm_op) \ >> +static inline int arch_##name##_relaxed(type *v, dtype a, dtype u) \ > > I don't think we have atomic_fetch_*_unless_relaxed() at atomic APIs, > ditto for: > > atomic_fetch_add_unless_relaxed() > atomic_inc_not_zero_relaxed() > atomic_dec_if_positive_relaxed() > > , and we don't have the _acquire() and _release() variants for them > either, and if you don't define their fully-ordered version (e.g. > atomic_inc_not_zero()), atomic-arch-fallback.h will use read and cmpxchg > to implement them, and I think not what we want. Okay. How can those be added? The atoimc generation is pretty complicated. > [...] >> >> #endif /* __KERNEL__ */ >> #endif /* _ASM_POWERPC_ATOMIC_H_ */ >> diff --git a/arch/powerpc/include/asm/cmpxchg.h >> b/arch/powerpc/include/asm/cmpxchg.h >> index cf091c4c22e5..181f7e8b3281 100644 >> --- a/arch/powerpc/include/asm/cmpxchg.h >> +++ b/arch/powerpc/include/asm/cmpxchg.h >> @@ -192,7 +192,7 @@ __xchg_relaxed(void *ptr, unsigned long x, unsigned int >> size) >> (unsigned long)_x_, sizeof(*(ptr))); >> \ >>}) >> >> -#define xchg_relaxed(ptr, x) >> \ >> +#define arch_xchg_relaxed(ptr, x) \ >> ({ \ >> __typeof__(*(ptr)) _x_ = (x); \ >> (__typeof__(*(ptr))) __xchg_relaxed((ptr), \ >> @@ -448,35 +448,7 @@ __cmpxchg_relaxed(void *ptr, unsigned long old, >> unsigned long new, >> return old; >> } >> >> -static __always_inline unsigned long >> -__cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new, >> - unsigned int size) >> -{ >> -switch (size) { >> -case 1: >> -return __cmpxchg_u8_acquire(ptr, old, new); >> -case 2: >> -return __cmpxchg_u16_acquire(ptr, old, new); >> -case 4: >> -return __cmpxchg_u32_acquire(ptr, old, new); >> -#ifdef CONFIG_PPC64 >> -case 8: >> -return __cmpxchg_u64_acquire(ptr, old, new); >> -#endif >> -} >> -BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_acquire"); >> -return old; >> -} >> -#define cmpxchg(ptr, o, n) \ >> - ({ >> \ >> - __typeof__(*(ptr)) _o_ = (o); \ >> - __typeof__(*(ptr)) _n_ = (n);
Re: [PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
Hi Nicholas, On Wed, Nov 11, 2020 at 09:07:23PM +1000, Nicholas Piggin wrote: > All the cool kids are doing it. > > Signed-off-by: Nicholas Piggin > --- > arch/powerpc/include/asm/atomic.h | 681 ++--- > arch/powerpc/include/asm/cmpxchg.h | 62 +-- > 2 files changed, 248 insertions(+), 495 deletions(-) > > diff --git a/arch/powerpc/include/asm/atomic.h > b/arch/powerpc/include/asm/atomic.h > index 8a55eb8cc97b..899aa2403ba7 100644 > --- a/arch/powerpc/include/asm/atomic.h > +++ b/arch/powerpc/include/asm/atomic.h > @@ -11,185 +11,285 @@ > #include > #include > > +#define ARCH_ATOMIC > + > +#ifndef CONFIG_64BIT > +#include > +#endif > + > /* > * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with > * a "bne-" instruction at the end, so an isync is enough as a acquire > barrier > * on the platform without lwsync. > */ > #define __atomic_acquire_fence() \ > - __asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory") > + asm volatile(PPC_ACQUIRE_BARRIER "" : : : "memory") > > #define __atomic_release_fence() \ > - __asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory") > + asm volatile(PPC_RELEASE_BARRIER "" : : : "memory") > > -static __inline__ int atomic_read(const atomic_t *v) > -{ > - int t; > +#define __atomic_pre_full_fence smp_mb > > - __asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter)); > +#define __atomic_post_full_fence smp_mb > Do you need to define __atomic_{pre,post}_full_fence for PPC? IIRC, they are default smp_mb__{before,atomic}_atomic(), so are smp_mb() defautly on PPC. > - return t; > +#define arch_atomic_read(v) __READ_ONCE((v)->counter) > +#define arch_atomic_set(v, i) > __WRITE_ONCE(((v)->counter), (i)) > +#ifdef CONFIG_64BIT > +#define ATOMIC64_INIT(i) { (i) } > +#define arch_atomic64_read(v) > __READ_ONCE((v)->counter) > +#define arch_atomic64_set(v, i) > __WRITE_ONCE(((v)->counter), (i)) > +#endif > + [...] > > +#define ATOMIC_FETCH_OP_UNLESS_RELAXED(name, type, dtype, width, asm_op) \ > +static inline int arch_##name##_relaxed(type *v, dtype a, dtype u) \ I don't think we have atomic_fetch_*_unless_relaxed() at atomic APIs, ditto for: atomic_fetch_add_unless_relaxed() atomic_inc_not_zero_relaxed() atomic_dec_if_positive_relaxed() , and we don't have the _acquire() and _release() variants for them either, and if you don't define their fully-ordered version (e.g. atomic_inc_not_zero()), atomic-arch-fallback.h will use read and cmpxchg to implement them, and I think not what we want. [...] > > #endif /* __KERNEL__ */ > #endif /* _ASM_POWERPC_ATOMIC_H_ */ > diff --git a/arch/powerpc/include/asm/cmpxchg.h > b/arch/powerpc/include/asm/cmpxchg.h > index cf091c4c22e5..181f7e8b3281 100644 > --- a/arch/powerpc/include/asm/cmpxchg.h > +++ b/arch/powerpc/include/asm/cmpxchg.h > @@ -192,7 +192,7 @@ __xchg_relaxed(void *ptr, unsigned long x, unsigned int > size) > (unsigned long)_x_, sizeof(*(ptr))); > \ >}) > > -#define xchg_relaxed(ptr, x) \ > +#define arch_xchg_relaxed(ptr, x)\ > ({ \ > __typeof__(*(ptr)) _x_ = (x); \ > (__typeof__(*(ptr))) __xchg_relaxed((ptr), \ > @@ -448,35 +448,7 @@ __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned > long new, > return old; > } > > -static __always_inline unsigned long > -__cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new, > - unsigned int size) > -{ > - switch (size) { > - case 1: > - return __cmpxchg_u8_acquire(ptr, old, new); > - case 2: > - return __cmpxchg_u16_acquire(ptr, old, new); > - case 4: > - return __cmpxchg_u32_acquire(ptr, old, new); > -#ifdef CONFIG_PPC64 > - case 8: > - return __cmpxchg_u64_acquire(ptr, old, new); > -#endif > - } > - BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_acquire"); > - return old; > -} > -#define cmpxchg(ptr, o, n)\ > - ({ \ > - __typeof__(*(ptr)) _o_ = (o);\ > - __typeof__(*(ptr)) _n_ = (n);\ > - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, > \ > - (unsigned long)_n_, sizeof(*(ptr))); \ > - }) > - > - If you remove {atomic_}_cmpxchg_{,_acquire}() and use the version provided by atomic-arch-fallback.h, then a fail cmpxchg
Re: [PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
Hi Nicholas, I love your patch! Perhaps something to improve: [auto build test WARNING on powerpc/next] [also build test WARNING on asm-generic/master linus/master v5.10-rc3 next-20201112] [cannot apply to scottwood/next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/powerpc-convert-to-use-ARCH_ATOMIC/2020-190941 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc64-randconfig-s031-2020 (attached as .config) compiler: powerpc-linux-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.3-107-gaf3512a6-dirty # https://github.com/0day-ci/linux/commit/9e1bec8fe216b0745c647e52c40d1f0033fb4efd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Nicholas-Piggin/powerpc-convert-to-use-ARCH_ATOMIC/2020-190941 git checkout 9e1bec8fe216b0745c647e52c40d1f0033fb4efd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=powerpc64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot "sparse warnings: (new ones prefixed by >>)" >> drivers/gpu/drm/drm_lock.c:75:24: sparse: sparse: incorrect type in argument >> 1 (different modifiers) @@ expected void *ptr @@ got unsigned int >> volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:75:24: sparse: expected void *ptr >> drivers/gpu/drm/drm_lock.c:75:24: sparse: got unsigned int volatile >> *__ai_ptr >> drivers/gpu/drm/drm_lock.c:75:24: sparse: sparse: incorrect type in argument >> 1 (different modifiers) @@ expected void *ptr @@ got unsigned int >> volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:75:24: sparse: expected void *ptr >> drivers/gpu/drm/drm_lock.c:75:24: sparse: got unsigned int volatile >> *__ai_ptr drivers/gpu/drm/drm_lock.c:118:24: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:118:24: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:118:24: sparse: got unsigned int volatile *__ai_ptr drivers/gpu/drm/drm_lock.c:118:24: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:118:24: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:118:24: sparse: got unsigned int volatile *__ai_ptr drivers/gpu/drm/drm_lock.c:141:24: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:141:24: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:141:24: sparse: got unsigned int volatile *__ai_ptr drivers/gpu/drm/drm_lock.c:141:24: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:141:24: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:141:24: sparse: got unsigned int volatile *__ai_ptr drivers/gpu/drm/drm_lock.c:319:40: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:319:40: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:319:40: sparse: got unsigned int volatile *__ai_ptr drivers/gpu/drm/drm_lock.c:319:40: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void *ptr @@ got unsigned int volatile *__ai_ptr @@ drivers/gpu/drm/drm_lock.c:319:40: sparse: expected void *ptr drivers/gpu/drm/drm_lock.c:319:40: sparse: got unsigned int volatile *__ai_ptr vim +75 drivers/gpu/drm/drm_lock.c 4ac5ec40ec70022 Daniel Vetter 2010-08-23 48 bd50d4a2168370b Benjamin Gaignard 2020-03-06 49 /* 1a75a222f5ca106 Daniel Vetter 2016-06-14 50 * Take the heavyweight lock. 1a75a222f5ca106 Daniel Vetter 2016-06-14 51 * 1a75a222f5ca106 Daniel Vetter 2016-06-14 52 * \param lock lock pointer. 1a75a222f5ca106 Daniel Vetter 2016-06-14 53 * \param context locking context. 1a75a222f5ca106 Daniel Vetter 2016-06-14 54 * \return one if the lock is held, or zero otherwise. 1a75a222f5ca106 Daniel Vetter 2016-06-14 55 * 1a75a222f5ca106 Daniel Vetter 2016-06-14 56 * Attempt to mark the lock as held by
Re: [PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
Hi Nicholas, I love your patch! Perhaps something to improve: [auto build test WARNING on powerpc/next] [also build test WARNING on asm-generic/master linus/master v5.10-rc3 next-2020] [cannot apply to scottwood/next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/powerpc-convert-to-use-ARCH_ATOMIC/2020-190941 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-allyesconfig (attached as .config) compiler: powerpc64-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/9e1bec8fe216b0745c647e52c40d1f0033fb4efd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Nicholas-Piggin/powerpc-convert-to-use-ARCH_ATOMIC/2020-190941 git checkout 9e1bec8fe216b0745c647e52c40d1f0033fb4efd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=powerpc If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): In file included from arch/powerpc/include/asm/atomic.h:11, from include/linux/atomic.h:7, from include/linux/rcupdate.h:25, from include/linux/rculist.h:11, from include/linux/sched/signal.h:5, from drivers/gpu/drm/drm_lock.c:37: drivers/gpu/drm/drm_lock.c: In function 'drm_lock_take': >> arch/powerpc/include/asm/cmpxchg.h:463:41: warning: passing argument 1 of >> '__cmpxchg_relaxed' discards 'volatile' qualifier from pointer target type >> [-Wdiscarded-qualifiers] 463 | (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr), \ | ^ include/linux/atomic.h:73:9: note: in expansion of macro 'arch_cmpxchg_relaxed' 73 | typeof(op##_relaxed(args)) __ret;\ | ^~ include/linux/atomic-arch-fallback.h:52:2: note: in expansion of macro '__atomic_op_fence' 52 | __atomic_op_fence(arch_cmpxchg, __VA_ARGS__) | ^ include/asm-generic/atomic-instrumented.h:1685:2: note: in expansion of macro 'arch_cmpxchg' 1685 | arch_cmpxchg(__ai_ptr, __VA_ARGS__);\ | ^~~~ drivers/gpu/drm/drm_lock.c:75:10: note: in expansion of macro 'cmpxchg' 75 | prev = cmpxchg(lock, old, new); | ^~~ arch/powerpc/include/asm/cmpxchg.h:432:25: note: expected 'void *' but argument is of type 'volatile unsigned int *' 432 | __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new, | ~~^~~ >> arch/powerpc/include/asm/cmpxchg.h:463:41: warning: passing argument 1 of >> '__cmpxchg_relaxed' discards 'volatile' qualifier from pointer target type >> [-Wdiscarded-qualifiers] 463 | (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr), \ | ^ include/linux/atomic.h:75:10: note: in expansion of macro 'arch_cmpxchg_relaxed' 75 | __ret = op##_relaxed(args); \ | ^~ include/linux/atomic-arch-fallback.h:52:2: note: in expansion of macro '__atomic_op_fence' 52 | __atomic_op_fence(arch_cmpxchg, __VA_ARGS__) | ^ include/asm-generic/atomic-instrumented.h:1685:2: note: in expansion of macro 'arch_cmpxchg' 1685 | arch_cmpxchg(__ai_ptr, __VA_ARGS__);\ | ^~~~ drivers/gpu/drm/drm_lock.c:75:10: note: in expansion of macro 'cmpxchg' 75 | prev = cmpxchg(lock, old, new); | ^~~ arch/powerpc/include/asm/cmpxchg.h:432:25: note: expected 'void *' but argument is of type 'volatile unsigned int *' 432 | __cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new, | ~~^~~ drivers/gpu/drm/drm_lock.c: In function 'drm_lock_transfer': >> arch/powerpc/include/asm/cmpxchg.h:463:41: warning: passing argument 1 of >> '__cmpxchg_relaxed' discards 'volatile' qualifier from pointer target type >> [-Wdiscarded-qualifiers] 463 | (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr), \ | ^ include/linux/atomic.h:73:9: note: in expansion of macro 'arch_cmpxchg_relaxed' 73 | typeof(op##_relaxed(args)) __ret;\ | ^~ include/linux/atomic-arch-fallback.h:52:2: note: in expansion of macro '__atomic_op_fence' 52 | __atomic_op_fence(arch_cmpxchg, __VA_ARGS__) | ^
[PATCH 3/3] powerpc: rewrite atomics to use ARCH_ATOMIC
All the cool kids are doing it. Signed-off-by: Nicholas Piggin --- arch/powerpc/include/asm/atomic.h | 681 ++--- arch/powerpc/include/asm/cmpxchg.h | 62 +-- 2 files changed, 248 insertions(+), 495 deletions(-) diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index 8a55eb8cc97b..899aa2403ba7 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -11,185 +11,285 @@ #include #include +#define ARCH_ATOMIC + +#ifndef CONFIG_64BIT +#include +#endif + /* * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with * a "bne-" instruction at the end, so an isync is enough as a acquire barrier * on the platform without lwsync. */ #define __atomic_acquire_fence() \ - __asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory") + asm volatile(PPC_ACQUIRE_BARRIER "" : : : "memory") #define __atomic_release_fence() \ - __asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory") + asm volatile(PPC_RELEASE_BARRIER "" : : : "memory") -static __inline__ int atomic_read(const atomic_t *v) -{ - int t; +#define __atomic_pre_full_fencesmp_mb - __asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter)); +#define __atomic_post_full_fence smp_mb - return t; +#define arch_atomic_read(v)__READ_ONCE((v)->counter) +#define arch_atomic_set(v, i) __WRITE_ONCE(((v)->counter), (i)) +#ifdef CONFIG_64BIT +#define ATOMIC64_INIT(i) { (i) } +#define arch_atomic64_read(v) __READ_ONCE((v)->counter) +#define arch_atomic64_set(v, i) __WRITE_ONCE(((v)->counter), (i)) +#endif + +#define ATOMIC_OP(name, type, dtype, width, asm_op)\ +static inline void arch_##name(dtype a, type *v) \ +{ \ + dtype t;\ + \ + asm volatile( \ +"1:l" #width "arx %0,0,%3 # " #name "\n"\ +"\t" #asm_op " %0,%2,%0 \n" \ +" st" #width "cx. %0,0,%3 \n" \ +" bne-1b \n" \ + : "=" (t), "+m" (v->counter) \ + : "r" (a), "r" (>counter)\ + : "cr0", "xer");\ } -static __inline__ void atomic_set(atomic_t *v, int i) -{ - __asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i)); +#define ATOMIC_OP_IMM(name, type, dtype, width, asm_op, imm) \ +static inline void arch_##name(type *v) \ +{ \ + dtype t;\ + \ + asm volatile( \ +"1:l" #width "arx %0,0,%3 # " #name "\n"\ +"\t" #asm_op " %0,%0,%2 \n" \ +" st" #width "cx. %0,0,%3 \n" \ +" bne-1b \n" \ + : "=" (t), "+m" (v->counter) \ + : "i" (imm), "r" (>counter) \ + : "cr0", "xer");\ } -#define ATOMIC_OP(op, asm_op) \ -static __inline__ void atomic_##op(int a, atomic_t *v) \ +#define ATOMIC_OP_RETURN_RELAXED(name, type, dtype, width, asm_op) \ +static inline dtype arch_##name##_relaxed(dtype a, type *v)\ { \ - int t; \ + dtype t;\ \ - __asm__ __volatile__( \ -"1:lwarx %0,0,%3 # atomic_" #op "\n" \ - #asm_op " %0,%2,%0\n" \ -" stwcx. %0,0,%3 \n" \ -" bne-1b\n" \ + asm volatile( \ +"1:l" #width "arx %0,0,%3 # " #name