From 88140456967a9db9449178640aa688d165e8c446 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 6 May 2014 19:41:36 +0200 Subject: [PATCH] s390/spinlock: fix system hang with spin_retry <= 0 On LPAR, when spin_retry is set to <= 0, arch_spin_lock_wait() and arch_spin_lock_wait_flags() may end up in a while(1) loop w/o doing any compare and swap operation. To fix this, use do/while instead of for loop. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/lib/spinlock.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 0946b99fe6c3..827f42aa2562 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -110,19 +110,20 @@ EXPORT_SYMBOL(arch_spin_relax); void arch_spin_lock_wait(arch_spinlock_t *lp) { - int count = spin_retry; unsigned int cpu = SPINLOCK_LOCKVAL; unsigned int owner; + int count; while (1) { owner = lp->lock; if (!owner || smp_vcpu_scheduled(~owner)) { - for (count = spin_retry; count > 0; count--) { + count = spin_retry; + do { if (arch_spin_is_locked(lp)) continue; if (_raw_compare_and_swap(&lp->lock, 0, cpu)) return; - } + } while (count-- > 0); if (MACHINE_IS_LPAR) continue; } @@ -137,22 +138,23 @@ EXPORT_SYMBOL(arch_spin_lock_wait); void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) { - int count = spin_retry; unsigned int cpu = SPINLOCK_LOCKVAL; unsigned int owner; + int count; local_irq_restore(flags); while (1) { owner = lp->lock; if (!owner || smp_vcpu_scheduled(~owner)) { - for (count = spin_retry; count > 0; count--) { + count = spin_retry; + do { if (arch_spin_is_locked(lp)) continue; local_irq_disable(); if (_raw_compare_and_swap(&lp->lock, 0, cpu)) return; local_irq_restore(flags); - } + } while (count-- > 0); if (MACHINE_IS_LPAR) continue; } -- 2.39.5