#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
 
+static DEFINE_MUTEX(pseries_cpu_hotplug_mutex);
+
+void cpu_hotplug_driver_lock()
+{
+       mutex_lock(&pseries_cpu_hotplug_mutex);
+}
+
+void cpu_hotplug_driver_unlock()
+{
+       mutex_unlock(&pseries_cpu_hotplug_mutex);
+}
+
 static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
 {
        struct device_node *dn;
        char *cpu_name;
        int rc;
 
+       cpu_hotplug_driver_lock();
        rc = strict_strtoul(buf, 0, &drc_index);
-       if (rc)
-               return -EINVAL;
+       if (rc) {
+               rc = -EINVAL;
+               goto out;
+       }
 
        dn = dlpar_configure_connector(drc_index);
-       if (!dn)
-               return -EINVAL;
+       if (!dn) {
+               rc = -EINVAL;
+               goto out;
+       }
 
        /* configure-connector reports cpus as living in the base
         * directory of the device tree.  CPUs actually live in the
                           GFP_KERNEL);
        if (!cpu_name) {
                dlpar_free_cc_nodes(dn);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out;
        }
 
        sprintf(cpu_name, "/cpus%s", dn->full_name);
        rc = dlpar_acquire_drc(drc_index);
        if (rc) {
                dlpar_free_cc_nodes(dn);
-               return -EINVAL;
+               rc = -EINVAL;
+               goto out;
        }
 
        rc = dlpar_attach_node(dn);
        }
 
        rc = online_node_cpus(dn);
+out:
+       cpu_hotplug_driver_unlock();
 
        return rc ? rc : count;
 }
                return -EINVAL;
        }
 
+       cpu_hotplug_driver_lock();
        rc = offline_node_cpus(dn);
        if (rc) {
                of_node_put(dn);
-               return -EINVAL;
+               rc = -EINVAL;
+               goto out;
        }
 
        rc = dlpar_release_drc(*drc_index);
        if (rc) {
                of_node_put(dn);
-               return -EINVAL;
+               goto out;
        }
 
        rc = dlpar_detach_node(dn);
        if (rc) {
                dlpar_acquire_drc(*drc_index);
-               return rc;
+               goto out;
        }
 
        of_node_put(dn);
-       return count;
+out:
+       cpu_hotplug_driver_unlock();
+       return rc ? rc : count;
 }
 
 static int __init pseries_dlpar_init(void)
 
        struct cpu *cpu = container_of(dev, struct cpu, sysdev);
        ssize_t ret;
 
+       cpu_hotplug_driver_lock();
        switch (buf[0]) {
        case '0':
                ret = cpu_down(cpu->sysdev.id);
        default:
                ret = -EINVAL;
        }
+       cpu_hotplug_driver_unlock();
 
        if (ret >= 0)
                ret = count;
 
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
 int cpu_down(unsigned int cpu);
 
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+extern void cpu_hotplug_driver_lock(void);
+extern void cpu_hotplug_driver_unlock(void);
+#else
+static inline void cpu_hotplug_driver_lock(void)
+{
+}
+
+static inline void cpu_hotplug_driver_unlock(void)
+{
+}
+#endif
+
 #else          /* CONFIG_HOTPLUG_CPU */
 
 #define get_online_cpus()      do { } while (0)