arch/powerpc/kernel/rtas.c | 3 +++ include/linux/cpu.h | 4 ++++ kernel/cpu.c | 24 ++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) Index: linux-2.6.19-rc5/arch/powerpc/kernel/rtas.c =================================================================== --- linux-2.6.19-rc5.orig/arch/powerpc/kernel/rtas.c +++ linux-2.6.19-rc5/arch/powerpc/kernel/rtas.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -881,6 +882,8 @@ void __init rtas_initialize(void) #ifdef CONFIG_HOTPLUG_CPU rtas_stop_self_args.token = rtas_token("stop-self"); + if(rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE) + disable_cpu_hotplug_perm(); #endif /* CONFIG_HOTPLUG_CPU */ #ifdef CONFIG_RTAS_ERROR_LOGGING rtas_last_error_token = rtas_token("rtas-last-error"); Index: linux-2.6.19-rc5/kernel/cpu.c =================================================================== --- linux-2.6.19-rc5.orig/kernel/cpu.c +++ linux-2.6.19-rc5/kernel/cpu.c @@ -63,8 +63,20 @@ void unlock_cpu_hotplug(void) } EXPORT_SYMBOL_GPL(unlock_cpu_hotplug); +void disable_cpu_hotplug_perm(void) +{ + mutex_lock(&cpu_add_remove_lock); + cpu_hotplug_disabled = PERM_DISABLED_CPU_HOTPLUG; + mutex_unlock(&cpu_add_remove_lock); +} + #endif /* CONFIG_HOTPLUG_CPU */ +static int is_cpu_hotplug_perm_disabled() +{ + return cpu_hotplug_disabled == PERM_DISABLED_CPU_HOTPLUG; +} + /* Need to know about CPUs going up/down? */ int __cpuinit register_cpu_notifier(struct notifier_block *nb) { @@ -193,7 +205,7 @@ int cpu_down(unsigned int cpu) int err = 0; mutex_lock(&cpu_add_remove_lock); - if (cpu_hotplug_disabled) + if (cpu_hotplug_disabled || is_cpu_hotplug_perm_disabled()) err = -EBUSY; else err = _cpu_down(cpu); @@ -244,7 +256,7 @@ int __devinit cpu_up(unsigned int cpu) int err = 0; mutex_lock(&cpu_add_remove_lock); - if (cpu_hotplug_disabled) + if (cpu_hotplug_disabled || is_cpu_hotplug_perm_disabled()) err = -EBUSY; else err = _cpu_up(cpu); @@ -261,6 +273,10 @@ int disable_nonboot_cpus(void) int cpu, first_cpu, error; mutex_lock(&cpu_add_remove_lock); + if(is_cpu_hotplug_perm_disabled()) { + error = -EBUSY; + goto out; + } first_cpu = first_cpu(cpu_present_map); if (!cpu_online(first_cpu)) { error = _cpu_up(first_cpu); @@ -311,6 +327,10 @@ void enable_nonboot_cpus(void) /* Allow everyone to use the CPU hotplug again */ mutex_lock(&cpu_add_remove_lock); + if(is_cpu_hotplug_perm_disabled()) { + mutex_unlock(&cpu_add_remove_lock); + return; + } cpu_hotplug_disabled = 0; mutex_unlock(&cpu_add_remove_lock); Index: linux-2.6.19-rc5/include/linux/cpu.h =================================================================== --- linux-2.6.19-rc5.orig/include/linux/cpu.h +++ linux-2.6.19-rc5/include/linux/cpu.h @@ -31,6 +31,8 @@ struct cpu { struct sys_device sysdev; }; +#define PERM_DISABLED_CPU_HOTPLUG -1 + extern int register_cpu(struct cpu *cpu, int num); extern struct sys_device *get_cpu_sysdev(unsigned cpu); #ifdef CONFIG_HOTPLUG_CPU @@ -68,6 +70,7 @@ extern struct sysdev_class cpu_sysdev_cl /* Stop CPUs going up and down. */ extern void lock_cpu_hotplug(void); extern void unlock_cpu_hotplug(void); +extern void disable_cpu_hotplug_perm(void); #define hotcpu_notifier(fn, pri) { \ static struct notifier_block fn##_nb = \ { .notifier_call = fn, .priority = pri }; \ @@ -80,6 +83,7 @@ int cpu_down(unsigned int cpu); #else #define lock_cpu_hotplug() do { } while (0) #define unlock_cpu_hotplug() do { } while (0) +#define disable_cpu_hotplug_perm() do { } while (0) #define lock_cpu_hotplug_interruptible() 0 #define hotcpu_notifier(fn, pri) do { } while (0) #define register_hotcpu_notifier(nb) do { } while (0)