Merge remote-tracking branches 'regulator/fix/88pm800', 'regulator/fix/max8973',...
[linux-drm-fsl-dcu.git] / arch / arc / include / asm / spinlock.h
index b6a8c2dfbe6e42cd51def893784f0780bc67264e..e1651df6a93d5bc8ab0af3a833c7c6ffd23acacc 100644 (file)
@@ -22,24 +22,46 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
 
+       /*
+        * This smp_mb() is technically superfluous, we only need the one
+        * after the lock for providing the ACQUIRE semantics.
+        * However doing the "right" thing was regressing hackbench
+        * so keeping this, pending further investigation
+        */
+       smp_mb();
+
        __asm__ __volatile__(
        "1:     ex  %0, [%1]            \n"
        "       breq  %0, %2, 1b        \n"
        : "+&r" (tmp)
        : "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__)
        : "memory");
+
+       /*
+        * ACQUIRE barrier to ensure load/store after taking the lock
+        * don't "bleed-up" out of the critical section (leak-in is allowed)
+        * http://www.spinics.net/lists/kernel/msg2010409.html
+        *
+        * ARCv2 only has load-load, store-store and all-all barrier
+        * thus need the full all-all barrier
+        */
+       smp_mb();
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
 
+       smp_mb();
+
        __asm__ __volatile__(
        "1:     ex  %0, [%1]            \n"
        : "+r" (tmp)
        : "r"(&(lock->slock))
        : "memory");
 
+       smp_mb();
+
        return (tmp == __ARCH_SPIN_LOCK_UNLOCKED__);
 }
 
@@ -47,12 +69,22 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
        unsigned int tmp = __ARCH_SPIN_LOCK_UNLOCKED__;
 
+       /*
+        * RELEASE barrier: given the instructions avail on ARCv2, full barrier
+        * is the only option
+        */
+       smp_mb();
+
        __asm__ __volatile__(
        "       ex  %0, [%1]            \n"
        : "+r" (tmp)
        : "r"(&(lock->slock))
        : "memory");
 
+       /*
+        * superfluous, but keeping for now - see pairing version in
+        * arch_spin_lock above
+        */
        smp_mb();
 }