diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 59c56c3d72d08a265d79090f87a4b1de87a997fd..e41f4008afc501927a5c3b08fda18891c1afc887 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -59,6 +59,29 @@ void _raw_spin_lock_wait(raw_spinlock_t *lp) } EXPORT_SYMBOL(_raw_spin_lock_wait); +void _raw_spin_lock_wait_flags(raw_spinlock_t *lp, unsigned long flags) +{ + int count = spin_retry; + unsigned int cpu = ~smp_processor_id(); + + local_irq_restore(flags); + while (1) { + if (count-- <= 0) { + unsigned int owner = lp->owner_cpu; + if (owner != 0) + _raw_yield_cpu(~owner); + count = spin_retry; + } + if (__raw_spin_is_locked(lp)) + continue; + local_irq_disable(); + if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) + return; + local_irq_restore(flags); + } +} +EXPORT_SYMBOL(_raw_spin_lock_wait_flags); + int _raw_spin_trylock_retry(raw_spinlock_t *lp) { unsigned int cpu = ~smp_processor_id(); diff --git a/include/asm-s390/spinlock.h b/include/asm-s390/spinlock.h index c1d6e7e304e20608c1ee8ae3c24d7f98299b7f73..df84ae96915f5342b4f86a76d0ac09651e12c4bd 100644 --- a/include/asm-s390/spinlock.h +++ b/include/asm-s390/spinlock.h @@ -53,12 +53,12 @@ _raw_compare_and_swap(volatile unsigned int *lock, */ #define __raw_spin_is_locked(x) ((x)->owner_cpu != 0) -#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) #define __raw_spin_unlock_wait(lock) \ do { while (__raw_spin_is_locked(lock)) \ _raw_spin_relax(lock); } while (0) extern void _raw_spin_lock_wait(raw_spinlock_t *); +extern void _raw_spin_lock_wait_flags(raw_spinlock_t *, unsigned long flags); extern int _raw_spin_trylock_retry(raw_spinlock_t *); extern void _raw_spin_relax(raw_spinlock_t *lock); @@ -72,6 +72,17 @@ static inline void __raw_spin_lock(raw_spinlock_t *lp) _raw_spin_lock_wait(lp); } +static inline void __raw_spin_lock_flags(raw_spinlock_t *lp, + unsigned long flags) +{ + int old; + + old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id()); + if (likely(old == 0)) + return; + _raw_spin_lock_wait_flags(lp, flags); +} + static inline int __raw_spin_trylock(raw_spinlock_t *lp) { int old;