#include <linux/vermagic.h>
 #include <linux/notifier.h>
 #include <linux/sched.h>
-#include <linux/stop_machine.h>
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/mutex.h>
  * 1) List of modules (also safely readable with preempt_disable),
  * 2) module_use links,
  * 3) module_addr_min/module_addr_max.
- * (delete uses stop_machine/add uses RCU list operations). */
+ * (delete and add uses RCU list operations). */
 DEFINE_MUTEX(module_mutex);
 EXPORT_SYMBOL_GPL(module_mutex);
 static LIST_HEAD(modules);
 
 EXPORT_TRACEPOINT_SYMBOL(module_get);
 
+/* MODULE_REF_BASE is the base reference count by kmodule loader. */
+#define MODULE_REF_BASE        1
+
 /* Init the unload section of the module. */
 static int module_unload_init(struct module *mod)
 {
+       /*
+        * Initialize reference counter to MODULE_REF_BASE.
+        * refcnt == 0 means module is going.
+        */
+       atomic_set(&mod->refcnt, MODULE_REF_BASE);
+
        INIT_LIST_HEAD(&mod->source_list);
        INIT_LIST_HEAD(&mod->target_list);
 
        /* Hold reference count during initialization. */
-       atomic_set(&mod->refcnt, 1);
+       atomic_inc(&mod->refcnt);
 
        return 0;
 }
 }
 #endif /* CONFIG_MODULE_FORCE_UNLOAD */
 
-struct stopref
+/* Try to release refcount of module, 0 means success. */
+static int try_release_module_ref(struct module *mod)
 {
-       struct module *mod;
-       int flags;
-       int *forced;
-};
+       int ret;
 
-/* Whole machine is stopped with interrupts off when this runs. */
-static int __try_stop_module(void *_sref)
-{
-       struct stopref *sref = _sref;
+       /* Try to decrement refcnt which we set at loading */
+       ret = atomic_sub_return(MODULE_REF_BASE, &mod->refcnt);
+       BUG_ON(ret < 0);
+       if (ret)
+               /* Someone can put this right now, recover with checking */
+               ret = atomic_add_unless(&mod->refcnt, MODULE_REF_BASE, 0);
+
+       return ret;
+}
 
+static int try_stop_module(struct module *mod, int flags, int *forced)
+{
        /* If it's not unused, quit unless we're forcing. */
-       if (module_refcount(sref->mod) != 0) {
-               if (!(*sref->forced = try_force_unload(sref->flags)))
+       if (try_release_module_ref(mod) != 0) {
+               *forced = try_force_unload(flags);
+               if (!(*forced))
                        return -EWOULDBLOCK;
        }
 
        /* Mark it as dying. */
-       sref->mod->state = MODULE_STATE_GOING;
-       return 0;
-}
-
-static int try_stop_module(struct module *mod, int flags, int *forced)
-{
-       struct stopref sref = { mod, flags, forced };
+       mod->state = MODULE_STATE_GOING;
 
-       return stop_machine(__try_stop_module, &sref, NULL);
+       return 0;
 }
 
 unsigned long module_refcount(struct module *mod)
 {
-       return (unsigned long)atomic_read(&mod->refcnt);
+       return (unsigned long)atomic_read(&mod->refcnt) - MODULE_REF_BASE;
 }
 EXPORT_SYMBOL(module_refcount);
 
 
        if (module) {
                preempt_disable();
-
-               if (likely(module_is_live(module))) {
-                       atomic_inc(&module->refcnt);
+               /* Note: here, we can fail to get a reference */
+               if (likely(module_is_live(module) &&
+                          atomic_inc_not_zero(&module->refcnt) != 0))
                        trace_module_get(module, _RET_IP_);
-               } else
+               else
                        ret = false;
 
                preempt_enable();
 
 void module_put(struct module *module)
 {
+       int ret;
+
        if (module) {
                preempt_disable();
-               atomic_dec(&module->refcnt);
+               ret = atomic_dec_if_positive(&module->refcnt);
+               WARN_ON(ret < 0);       /* Failed to put refcount */
                trace_module_put(module, _RET_IP_);
                preempt_enable();
        }