--- /dev/null
+/*
+ * MCS lock defines
+ *
+ * This file contains the main data structure and API definitions of MCS lock.
+ *
+ * The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spin-lock
+ * with the desirable properties of being fair, and with each cpu trying
+ * to acquire the lock spinning on a local variable.
+ * It avoids expensive cache bouncings that common test-and-set spin-lock
+ * implementations incur.
+ */
+#ifndef __LINUX_MCS_SPINLOCK_H
+#define __LINUX_MCS_SPINLOCK_H
+
+struct mcs_spinlock {
+       struct mcs_spinlock *next;
+       int locked; /* 1 if lock acquired */
+};
+
+/*
+ * Note: the smp_load_acquire/smp_store_release pair is not
+ * sufficient to form a full memory barrier across
+ * cpus for many architectures (except x86) for mcs_unlock and mcs_lock.
+ * For applications that need a full barrier across multiple cpus
+ * with mcs_unlock and mcs_lock pair, smp_mb__after_unlock_lock() should be
+ * used after mcs_lock.
+ */
+static inline
+void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+       struct mcs_spinlock *prev;
+
+       /* Init node */
+       node->locked = 0;
+       node->next   = NULL;
+
+       prev = xchg(lock, node);
+       if (likely(prev == NULL)) {
+               /* Lock acquired */
+               node->locked = 1;
+               return;
+       }
+       ACCESS_ONCE(prev->next) = node;
+       /*
+        * Wait until the lock holder passes the lock down.
+        * Using smp_load_acquire() provides a memory barrier that
+        * ensures subsequent operations happen after the lock is acquired.
+        */
+       while (!(smp_load_acquire(&node->locked)))
+               arch_mutex_cpu_relax();
+}
+
+static inline
+void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+       struct mcs_spinlock *next = ACCESS_ONCE(node->next);
+
+       if (likely(!next)) {
+               /*
+                * Release the lock by setting it to NULL
+                */
+               if (cmpxchg(lock, node, NULL) == node)
+                       return;
+               /* Wait until the next pointer is set */
+               while (!(next = ACCESS_ONCE(node->next)))
+                       arch_mutex_cpu_relax();
+       }
+       /*
+        * Pass lock to next waiter.
+        * smp_store_release() provides a memory barrier to ensure
+        * all operations in the critical section has been completed
+        * before unlocking.
+        */
+       smp_store_release(&next->locked, 1);
+}
+
+#endif /* __LINUX_MCS_SPINLOCK_H */
 
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
+#include <linux/mcs_spinlock.h>
 
 /*
  * In the DEBUG case we are using the "NULL fastpath" for mutexes,
        INIT_LIST_HEAD(&lock->wait_list);
        mutex_clear_owner(lock);
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-       lock->spin_mlock = NULL;
+       lock->mcs_lock = NULL;
 #endif
 
        debug_mutex_init(lock, name, key);
  * more or less simultaneously, the spinners need to acquire a MCS lock
  * first before spinning on the owner field.
  *
- * We don't inline mspin_lock() so that perf can correctly account for the
- * time spent in this lock function.
  */
-struct mspin_node {
-       struct mspin_node *next ;
-       int               locked;       /* 1 if lock acquired */
-};
-#define        MLOCK(mutex)    ((struct mspin_node **)&((mutex)->spin_mlock))
-
-static noinline
-void mspin_lock(struct mspin_node **lock, struct mspin_node *node)
-{
-       struct mspin_node *prev;
-
-       /* Init node */
-       node->locked = 0;
-       node->next   = NULL;
-
-       prev = xchg(lock, node);
-       if (likely(prev == NULL)) {
-               /* Lock acquired */
-               node->locked = 1;
-               return;
-       }
-       ACCESS_ONCE(prev->next) = node;
-       /*
-        * Wait until the lock holder passes the lock down.
-        * Using smp_load_acquire() provides a memory barrier that
-        * ensures subsequent operations happen after the lock is acquired.
-        */
-       while (!(smp_load_acquire(&node->locked)))
-               arch_mutex_cpu_relax();
-}
-
-static void mspin_unlock(struct mspin_node **lock, struct mspin_node *node)
-{
-       struct mspin_node *next = ACCESS_ONCE(node->next);
-
-       if (likely(!next)) {
-               /*
-                * Release the lock by setting it to NULL
-                */
-               if (cmpxchg(lock, node, NULL) == node)
-                       return;
-               /* Wait until the next pointer is set */
-               while (!(next = ACCESS_ONCE(node->next)))
-                       arch_mutex_cpu_relax();
-       }
-       /*
-        * Pass lock to next waiter.
-        * smp_store_release() provides a memory barrier to ensure
-        * all operations in the critical section has been completed
-        * before unlocking.
-        */
-       smp_store_release(&next->locked, 1);
-}
 
 /*
  * Mutex spinning code migrated from kernel/sched/core.c
 
        for (;;) {
                struct task_struct *owner;
-               struct mspin_node  node;
+               struct mcs_spinlock  node;
 
                if (use_ww_ctx && ww_ctx->acquired > 0) {
                        struct ww_mutex *ww;
                 * If there's an owner, wait for it to either
                 * release the lock or go to sleep.
                 */
-               mspin_lock(MLOCK(lock), &node);
+               mcs_spin_lock(&lock->mcs_lock, &node);
                owner = ACCESS_ONCE(lock->owner);
                if (owner && !mutex_spin_on_owner(lock, owner)) {
-                       mspin_unlock(MLOCK(lock), &node);
+                       mcs_spin_unlock(&lock->mcs_lock, &node);
                        goto slowpath;
                }
 
                        }
 
                        mutex_set_owner(lock);
-                       mspin_unlock(MLOCK(lock), &node);
+                       mcs_spin_unlock(&lock->mcs_lock, &node);
                        preempt_enable();
                        return 0;
                }
-               mspin_unlock(MLOCK(lock), &node);
+               mcs_spin_unlock(&lock->mcs_lock, &node);
 
                /*
                 * When there's no owner, we might have preempted between the