|
@@ -417,6 +417,45 @@ int generic_check_cpu_restart(unsigned int cpu)
|
|
|
{
|
|
|
return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
|
|
|
}
|
|
|
+
|
|
|
+static atomic_t secondary_inhibit_count;
|
|
|
+
|
|
|
+/*
|
|
|
+ * Don't allow secondary CPU threads to come online
|
|
|
+ */
|
|
|
+void inhibit_secondary_onlining(void)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * This makes secondary_inhibit_count stable during cpu
|
|
|
+ * online/offline operations.
|
|
|
+ */
|
|
|
+ get_online_cpus();
|
|
|
+
|
|
|
+ atomic_inc(&secondary_inhibit_count);
|
|
|
+ put_online_cpus();
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(inhibit_secondary_onlining);
|
|
|
+
|
|
|
+/*
|
|
|
+ * Allow secondary CPU threads to come online again
|
|
|
+ */
|
|
|
+void uninhibit_secondary_onlining(void)
|
|
|
+{
|
|
|
+ get_online_cpus();
|
|
|
+ atomic_dec(&secondary_inhibit_count);
|
|
|
+ put_online_cpus();
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining);
|
|
|
+
|
|
|
+static int secondaries_inhibited(void)
|
|
|
+{
|
|
|
+ return atomic_read(&secondary_inhibit_count);
|
|
|
+}
|
|
|
+
|
|
|
+#else /* HOTPLUG_CPU */
|
|
|
+
|
|
|
+#define secondaries_inhibited() 0
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)
|
|
@@ -435,6 +474,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
|
|
{
|
|
|
int rc, c;
|
|
|
|
|
|
+ /*
|
|
|
+ * Don't allow secondary threads to come online if inhibited
|
|
|
+ */
|
|
|
+ if (threads_per_core > 1 && secondaries_inhibited() &&
|
|
|
+ cpu % threads_per_core != 0)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
if (smp_ops == NULL ||
|
|
|
(smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
|
|
|
return -EINVAL;
|