|
@@ -19,6 +19,7 @@
|
|
#include <linux/mutex.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/suspend.h>
|
|
|
|
+#include <linux/lockdep.h>
|
|
|
|
|
|
#include "smpboot.h"
|
|
#include "smpboot.h"
|
|
|
|
|
|
@@ -57,17 +58,30 @@ static struct {
|
|
* an ongoing cpu hotplug operation.
|
|
* an ongoing cpu hotplug operation.
|
|
*/
|
|
*/
|
|
int refcount;
|
|
int refcount;
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
|
+ struct lockdep_map dep_map;
|
|
|
|
+#endif
|
|
} cpu_hotplug = {
|
|
} cpu_hotplug = {
|
|
.active_writer = NULL,
|
|
.active_writer = NULL,
|
|
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
|
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
|
.refcount = 0,
|
|
.refcount = 0,
|
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
|
+ .dep_map = {.name = "cpu_hotplug.lock" },
|
|
|
|
+#endif
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* Lockdep annotations for get/put_online_cpus() and cpu_hotplug_begin/end() */
|
|
|
|
+#define cpuhp_lock_acquire_read() lock_map_acquire_read(&cpu_hotplug.dep_map)
|
|
|
|
+#define cpuhp_lock_acquire() lock_map_acquire(&cpu_hotplug.dep_map)
|
|
|
|
+#define cpuhp_lock_release() lock_map_release(&cpu_hotplug.dep_map)
|
|
|
|
+
|
|
void get_online_cpus(void)
|
|
void get_online_cpus(void)
|
|
{
|
|
{
|
|
might_sleep();
|
|
might_sleep();
|
|
if (cpu_hotplug.active_writer == current)
|
|
if (cpu_hotplug.active_writer == current)
|
|
return;
|
|
return;
|
|
|
|
+ cpuhp_lock_acquire_read();
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
cpu_hotplug.refcount++;
|
|
cpu_hotplug.refcount++;
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
@@ -87,6 +101,7 @@ void put_online_cpus(void)
|
|
if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
|
|
if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
|
|
wake_up_process(cpu_hotplug.active_writer);
|
|
wake_up_process(cpu_hotplug.active_writer);
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
|
|
+ cpuhp_lock_release();
|
|
|
|
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(put_online_cpus);
|
|
EXPORT_SYMBOL_GPL(put_online_cpus);
|
|
@@ -117,6 +132,7 @@ void cpu_hotplug_begin(void)
|
|
{
|
|
{
|
|
cpu_hotplug.active_writer = current;
|
|
cpu_hotplug.active_writer = current;
|
|
|
|
|
|
|
|
+ cpuhp_lock_acquire();
|
|
for (;;) {
|
|
for (;;) {
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
if (likely(!cpu_hotplug.refcount))
|
|
if (likely(!cpu_hotplug.refcount))
|
|
@@ -131,6 +147,7 @@ void cpu_hotplug_done(void)
|
|
{
|
|
{
|
|
cpu_hotplug.active_writer = NULL;
|
|
cpu_hotplug.active_writer = NULL;
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
|
|
+ cpuhp_lock_release();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|