diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 22:27:53 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 22:27:53 +0100 |
commit | dd1c3ed76f26504621b5ce08b894666aafa38e47 (patch) | |
tree | f879aefbbd7871733bc616cb7f73dd5ffca53f44 /arch/xtensa/include | |
parent | Merge tag 'powerpc-5.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/po... (diff) | |
parent | xtensa: simplify trap_init (diff) | |
download | linux-dd1c3ed76f26504621b5ce08b894666aafa38e47.tar.xz linux-dd1c3ed76f26504621b5ce08b894666aafa38e47.zip |
Merge tag 'xtensa-20190307' of git://github.com/jcmvbkbc/linux-xtensa
Pull xtensa updates from Max Filippov:
- use generic spinlock/rwlock implementations
- clean up IPI processing
- document boot parameters passing to the kernel
- fix get_wchan
- various cleanups in time.c, process.c, traps.c and thread_info.h
* tag 'xtensa-20190307' of git://github.com/jcmvbkbc/linux-xtensa:
xtensa: simplify trap_init
xtensa: drop unused definitions
xtensa: fix get_wchan
xtensa: use generic spinlock/rwlock implementation
xtensa: provide xchg for sizes 1 and 2
xtensa: clean up arch/xtensa/kernel/time.c
xtensa: SMP: rework IPI processing
xtensa: document boot parameter passing
Diffstat (limited to 'arch/xtensa/include')
-rw-r--r-- | arch/xtensa/include/asm/Kbuild | 2 | ||||
-rw-r--r-- | arch/xtensa/include/asm/cmpxchg.h | 36 | ||||
-rw-r--r-- | arch/xtensa/include/asm/spinlock.h | 185 | ||||
-rw-r--r-- | arch/xtensa/include/asm/spinlock_types.h | 15 | ||||
-rw-r--r-- | arch/xtensa/include/asm/thread_info.h | 9 |
5 files changed, 40 insertions, 207 deletions
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 809f39ce08c0..d939e13e8d84 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -23,6 +23,8 @@ generic-y += mm-arch-hooks.h generic-y += param.h generic-y += percpu.h generic-y += preempt.h +generic-y += qrwlock.h +generic-y += qspinlock.h generic-y += rwsem.h generic-y += sections.h generic-y += socket.h diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index 201e9009efd8..22a10c715c1f 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h @@ -13,6 +13,7 @@ #ifndef __ASSEMBLY__ +#include <linux/bits.h> #include <linux/stringify.h> /* @@ -138,6 +139,28 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val) #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) +static inline u32 xchg_small(volatile void *ptr, u32 x, int size) +{ + int off = (unsigned long)ptr % sizeof(u32); + volatile u32 *p = ptr - off; +#ifdef __BIG_ENDIAN + int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE; +#else + int bitoff = off * BITS_PER_BYTE; +#endif + u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff; + u32 oldv, newv; + u32 ret; + + do { + oldv = READ_ONCE(*p); + ret = (oldv & bitmask) >> bitoff; + newv = (oldv & ~bitmask) | (x << bitoff); + } while (__cmpxchg_u32(p, oldv, newv) != oldv); + + return ret; +} + /* * This only works if the compiler isn't horribly bad at optimizing. * gcc-2.5.8 reportedly can't handle this, but I define that one to @@ -150,11 +173,16 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { - case 4: - return xchg_u32(ptr, x); + case 1: + return xchg_small(ptr, x, 1); + case 2: + return xchg_small(ptr, x, 2); + case 4: + return xchg_u32(ptr, x); + default: + __xchg_called_with_bad_pointer(); + return x; } - __xchg_called_with_bad_pointer(); - return x; } #endif /* __ASSEMBLY__ */ diff --git a/arch/xtensa/include/asm/spinlock.h b/arch/xtensa/include/asm/spinlock.h index c6e1290dcbb7..584b0de6f2ca 100644 --- a/arch/xtensa/include/asm/spinlock.h +++ b/arch/xtensa/include/asm/spinlock.h @@ -12,188 +12,9 @@ #define _XTENSA_SPINLOCK_H #include <asm/barrier.h> -#include <asm/processor.h> +#include <asm/qrwlock.h> +#include <asm/qspinlock.h> -/* - * spinlock - * - * There is at most one owner of a spinlock. There are not different - * types of spinlock owners like there are for rwlocks (see below). - * - * When trying to obtain a spinlock, the function "spins" forever, or busy- - * waits, until the lock is obtained. When spinning, presumably some other - * owner will soon give up the spinlock making it available to others. Use - * the trylock functions to avoid spinning forever. - * - * possible values: - * - * 0 nobody owns the spinlock - * 1 somebody owns the spinlock - */ - -#define arch_spin_is_locked(x) ((x)->slock != 0) - -static inline void arch_spin_lock(arch_spinlock_t *lock) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - "1: movi %0, 1\n" - " s32c1i %0, %1, 0\n" - " bnez %0, 1b\n" - : "=&a" (tmp) - : "a" (&lock->slock) - : "memory"); -} - -/* Returns 1 if the lock is obtained, 0 otherwise. */ - -static inline int arch_spin_trylock(arch_spinlock_t *lock) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - " movi %0, 1\n" - " s32c1i %0, %1, 0\n" - : "=&a" (tmp) - : "a" (&lock->slock) - : "memory"); - - return tmp == 0 ? 1 : 0; -} - -static inline void arch_spin_unlock(arch_spinlock_t *lock) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " s32ri %0, %1, 0\n" - : "=&a" (tmp) - : "a" (&lock->slock) - : "memory"); -} - -/* - * rwlock - * - * Read-write locks are really a more flexible spinlock. They allow - * multiple readers but only one writer. Write ownership is exclusive - * (i.e., all other readers and writers are blocked from ownership while - * there is a write owner). These rwlocks are unfair to writers. Writers - * can be starved for an indefinite time by readers. - * - * possible values: - * - * 0 nobody owns the rwlock - * >0 one or more readers own the rwlock - * (the positive value is the actual number of readers) - * 0x80000000 one writer owns the rwlock, no other writers, no readers - */ - -static inline void arch_write_lock(arch_rwlock_t *rw) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - "1: movi %0, 1\n" - " slli %0, %0, 31\n" - " s32c1i %0, %1, 0\n" - " bnez %0, 1b\n" - : "=&a" (tmp) - : "a" (&rw->lock) - : "memory"); -} - -/* Returns 1 if the lock is obtained, 0 otherwise. */ - -static inline int arch_write_trylock(arch_rwlock_t *rw) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - " movi %0, 1\n" - " slli %0, %0, 31\n" - " s32c1i %0, %1, 0\n" - : "=&a" (tmp) - : "a" (&rw->lock) - : "memory"); - - return tmp == 0 ? 1 : 0; -} - -static inline void arch_write_unlock(arch_rwlock_t *rw) -{ - unsigned long tmp; - - __asm__ __volatile__( - " movi %0, 0\n" - " s32ri %0, %1, 0\n" - : "=&a" (tmp) - : "a" (&rw->lock) - : "memory"); -} - -static inline void arch_read_lock(arch_rwlock_t *rw) -{ - unsigned long tmp; - unsigned long result; - - __asm__ __volatile__( - "1: l32i %1, %2, 0\n" - " bltz %1, 1b\n" - " wsr %1, scompare1\n" - " addi %0, %1, 1\n" - " s32c1i %0, %2, 0\n" - " bne %0, %1, 1b\n" - : "=&a" (result), "=&a" (tmp) - : "a" (&rw->lock) - : "memory"); -} - -/* Returns 1 if the lock is obtained, 0 otherwise. */ - -static inline int arch_read_trylock(arch_rwlock_t *rw) -{ - unsigned long result; - unsigned long tmp; - - __asm__ __volatile__( - " l32i %1, %2, 0\n" - " addi %0, %1, 1\n" - " bltz %0, 1f\n" - " wsr %1, scompare1\n" - " s32c1i %0, %2, 0\n" - " sub %0, %0, %1\n" - "1:\n" - : "=&a" (result), "=&a" (tmp) - : "a" (&rw->lock) - : "memory"); - - return result == 0; -} - -static inline void arch_read_unlock(arch_rwlock_t *rw) -{ - unsigned long tmp1, tmp2; - - __asm__ __volatile__( - "1: l32i %1, %2, 0\n" - " addi %0, %1, -1\n" - " wsr %1, scompare1\n" - " s32c1i %0, %2, 0\n" - " bne %0, %1, 1b\n" - : "=&a" (tmp1), "=&a" (tmp2) - : "a" (&rw->lock) - : "memory"); -} +#define smp_mb__after_spinlock() smp_mb() #endif /* _XTENSA_SPINLOCK_H */ diff --git a/arch/xtensa/include/asm/spinlock_types.h b/arch/xtensa/include/asm/spinlock_types.h index bb1fe6c1816e..64c9389254f1 100644 --- a/arch/xtensa/include/asm/spinlock_types.h +++ b/arch/xtensa/include/asm/spinlock_types.h @@ -2,20 +2,11 @@ #ifndef __ASM_SPINLOCK_TYPES_H #define __ASM_SPINLOCK_TYPES_H -#ifndef __LINUX_SPINLOCK_TYPES_H +#if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H) # error "please don't include this file directly" #endif -typedef struct { - volatile unsigned int slock; -} arch_spinlock_t; - -#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } - -typedef struct { - volatile unsigned int lock; -} arch_rwlock_t; - -#define __ARCH_RW_LOCK_UNLOCKED { 0 } +#include <asm-generic/qspinlock_types.h> +#include <asm-generic/qrwlock_types.h> #endif diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index f333f10a7650..f092cc3f4e66 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h @@ -121,15 +121,6 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_WORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ _TIF_SYSCALL_TRACEPOINT) -/* - * Thread-synchronous status. - * - * This is different from the flags in that nobody else - * ever touches our thread-synchronous status, so we don't - * have to worry about atomic accesses. - */ -#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */ - #define THREAD_SIZE KERNEL_STACK_SIZE #define THREAD_SIZE_ORDER (KERNEL_STACK_SHIFT - PAGE_SHIFT) |