diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index bd4e5dca3ff7e81f4ce754cbaad3856bb4948a6a..a4352b88a331d2a2b0459feff927320389d8a1c0 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -852,8 +852,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr) if (cpu_online(pr->id)) cpu_down(pr->id); + get_online_cpus(); + /* + * The cpu might become online again at this point. So we check whether + * the cpu has been onlined or not. If the cpu became online, it means + * that someone wants to use the cpu. So acpi_processor_handle_eject() + * returns -EAGAIN. + */ + if (unlikely(cpu_online(pr->id))) { + put_online_cpus(); + pr_warn("Failed to remove CPU %d, because other task " + "brought the CPU back online\n", pr->id); + return -EAGAIN; + } arch_unregister_cpu(pr->id); acpi_unmap_lsapic(pr->id); + put_online_cpus(); return (0); } #else diff --git a/kernel/cpu.c b/kernel/cpu.c index 42bd331ee0abff1d542583e14beb20d91f6fae62..f45657f1eb8ee3bb2ae084f5ebc4f22d80675eba 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -348,11 +348,13 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; struct task_struct *idle; - if (cpu_online(cpu) || !cpu_present(cpu)) - return -EINVAL; - cpu_hotplug_begin(); + if (cpu_online(cpu) || !cpu_present(cpu)) { + ret = -EINVAL; + goto out; + } + idle = idle_thread_get(cpu); if (IS_ERR(idle)) { ret = PTR_ERR(idle);