11da177e4SLinus Torvalds /* CPU control. 21da177e4SLinus Torvalds * (C) 2001, 2002, 2003, 2004 Rusty Russell 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This code is licenced under the GPL. 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds #include <linux/proc_fs.h> 71da177e4SLinus Torvalds #include <linux/smp.h> 81da177e4SLinus Torvalds #include <linux/init.h> 91da177e4SLinus Torvalds #include <linux/notifier.h> 101da177e4SLinus Torvalds #include <linux/sched.h> 111da177e4SLinus Torvalds #include <linux/unistd.h> 121da177e4SLinus Torvalds #include <linux/cpu.h> 131da177e4SLinus Torvalds #include <linux/module.h> 141da177e4SLinus Torvalds #include <linux/kthread.h> 151da177e4SLinus Torvalds #include <linux/stop_machine.h> 1681615b62SIngo Molnar #include <linux/mutex.h> 171da177e4SLinus Torvalds 1868f4f1ecSMax Krasnyansky /* 1968f4f1ecSMax Krasnyansky * Represents all cpu's present in the system 2068f4f1ecSMax Krasnyansky * In systems capable of hotplug, this map could dynamically grow 2168f4f1ecSMax Krasnyansky * as new cpu's are detected in the system via any platform specific 2268f4f1ecSMax Krasnyansky * method, such as ACPI for e.g. 2368f4f1ecSMax Krasnyansky */ 2468f4f1ecSMax Krasnyansky cpumask_t cpu_present_map __read_mostly; 2568f4f1ecSMax Krasnyansky EXPORT_SYMBOL(cpu_present_map); 2668f4f1ecSMax Krasnyansky 2768f4f1ecSMax Krasnyansky #ifndef CONFIG_SMP 2868f4f1ecSMax Krasnyansky 2968f4f1ecSMax Krasnyansky /* 3068f4f1ecSMax Krasnyansky * Represents all cpu's that are currently online. 3168f4f1ecSMax Krasnyansky */ 3268f4f1ecSMax Krasnyansky cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL; 3368f4f1ecSMax Krasnyansky EXPORT_SYMBOL(cpu_online_map); 3468f4f1ecSMax Krasnyansky 3568f4f1ecSMax Krasnyansky cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; 3668f4f1ecSMax Krasnyansky EXPORT_SYMBOL(cpu_possible_map); 3768f4f1ecSMax Krasnyansky 3868f4f1ecSMax Krasnyansky #else /* CONFIG_SMP */ 3968f4f1ecSMax Krasnyansky 40d221938cSGautham R Shenoy /* Serializes the updates to cpu_online_map, cpu_present_map */ 41aa953877SLinus Torvalds static DEFINE_MUTEX(cpu_add_remove_lock); 421da177e4SLinus Torvalds 43bd5349cfSNeil Brown static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain); 441da177e4SLinus Torvalds 45e3920fb4SRafael J. Wysocki /* If set, cpu_up and cpu_down will return -EBUSY and do nothing. 46e3920fb4SRafael J. Wysocki * Should always be manipulated under cpu_add_remove_lock 47e3920fb4SRafael J. Wysocki */ 48e3920fb4SRafael J. Wysocki static int cpu_hotplug_disabled; 49e3920fb4SRafael J. Wysocki 50d221938cSGautham R Shenoy static struct { 51d221938cSGautham R Shenoy struct task_struct *active_writer; 52d221938cSGautham R Shenoy struct mutex lock; /* Synchronizes accesses to refcount, */ 53d221938cSGautham R Shenoy /* 54d221938cSGautham R Shenoy * Also blocks the new readers during 55d221938cSGautham R Shenoy * an ongoing cpu hotplug operation. 56d221938cSGautham R Shenoy */ 57d221938cSGautham R Shenoy int refcount; 58d221938cSGautham R Shenoy } cpu_hotplug; 5990d45d17SAshok Raj 60d221938cSGautham R Shenoy void __init cpu_hotplug_init(void) 61d221938cSGautham R Shenoy { 62d221938cSGautham R Shenoy cpu_hotplug.active_writer = NULL; 63d221938cSGautham R Shenoy mutex_init(&cpu_hotplug.lock); 64d221938cSGautham R Shenoy cpu_hotplug.refcount = 0; 65d221938cSGautham R Shenoy } 66d221938cSGautham R Shenoy 67e761b772SMax Krasnyansky cpumask_t cpu_active_map; 68e761b772SMax Krasnyansky 69d221938cSGautham R Shenoy #ifdef CONFIG_HOTPLUG_CPU 70a9d9baa1SAshok Raj 7186ef5c9aSGautham R Shenoy void get_online_cpus(void) 72a9d9baa1SAshok Raj { 73d221938cSGautham R Shenoy might_sleep(); 74d221938cSGautham R Shenoy if (cpu_hotplug.active_writer == current) 75aa953877SLinus Torvalds return; 76d221938cSGautham R Shenoy mutex_lock(&cpu_hotplug.lock); 77d221938cSGautham R Shenoy cpu_hotplug.refcount++; 78d221938cSGautham R Shenoy mutex_unlock(&cpu_hotplug.lock); 79d221938cSGautham R Shenoy 80a9d9baa1SAshok Raj } 8186ef5c9aSGautham R Shenoy EXPORT_SYMBOL_GPL(get_online_cpus); 82a9d9baa1SAshok Raj 8386ef5c9aSGautham R Shenoy void put_online_cpus(void) 84a9d9baa1SAshok Raj { 85d221938cSGautham R Shenoy if (cpu_hotplug.active_writer == current) 86aa953877SLinus Torvalds return; 87d221938cSGautham R Shenoy mutex_lock(&cpu_hotplug.lock); 88d2ba7e2aSOleg Nesterov if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer)) 89d2ba7e2aSOleg Nesterov wake_up_process(cpu_hotplug.active_writer); 90d221938cSGautham R Shenoy mutex_unlock(&cpu_hotplug.lock); 91d221938cSGautham R Shenoy 92a9d9baa1SAshok Raj } 9386ef5c9aSGautham R Shenoy EXPORT_SYMBOL_GPL(put_online_cpus); 94a9d9baa1SAshok Raj 95a9d9baa1SAshok Raj #endif /* CONFIG_HOTPLUG_CPU */ 9690d45d17SAshok Raj 97d221938cSGautham R Shenoy /* 98d221938cSGautham R Shenoy * The following two API's must be used when attempting 99d221938cSGautham R Shenoy * to serialize the updates to cpu_online_map, cpu_present_map. 100d221938cSGautham R Shenoy */ 101d221938cSGautham R Shenoy void cpu_maps_update_begin(void) 102d221938cSGautham R Shenoy { 103d221938cSGautham R Shenoy mutex_lock(&cpu_add_remove_lock); 104d221938cSGautham R Shenoy } 105d221938cSGautham R Shenoy 106d221938cSGautham R Shenoy void cpu_maps_update_done(void) 107d221938cSGautham R Shenoy { 108d221938cSGautham R Shenoy mutex_unlock(&cpu_add_remove_lock); 109d221938cSGautham R Shenoy } 110d221938cSGautham R Shenoy 111d221938cSGautham R Shenoy /* 112d221938cSGautham R Shenoy * This ensures that the hotplug operation can begin only when the 113d221938cSGautham R Shenoy * refcount goes to zero. 114d221938cSGautham R Shenoy * 115d221938cSGautham R Shenoy * Note that during a cpu-hotplug operation, the new readers, if any, 116d221938cSGautham R Shenoy * will be blocked by the cpu_hotplug.lock 117d221938cSGautham R Shenoy * 118d2ba7e2aSOleg Nesterov * Since cpu_hotplug_begin() is always called after invoking 119d2ba7e2aSOleg Nesterov * cpu_maps_update_begin(), we can be sure that only one writer is active. 120d221938cSGautham R Shenoy * 121d221938cSGautham R Shenoy * Note that theoretically, there is a possibility of a livelock: 122d221938cSGautham R Shenoy * - Refcount goes to zero, last reader wakes up the sleeping 123d221938cSGautham R Shenoy * writer. 124d221938cSGautham R Shenoy * - Last reader unlocks the cpu_hotplug.lock. 125d221938cSGautham R Shenoy * - A new reader arrives at this moment, bumps up the refcount. 126d221938cSGautham R Shenoy * - The writer acquires the cpu_hotplug.lock finds the refcount 127d221938cSGautham R Shenoy * non zero and goes to sleep again. 128d221938cSGautham R Shenoy * 129d221938cSGautham R Shenoy * However, this is very difficult to achieve in practice since 13086ef5c9aSGautham R Shenoy * get_online_cpus() not an api which is called all that often. 131d221938cSGautham R Shenoy * 132d221938cSGautham R Shenoy */ 133d221938cSGautham R Shenoy static void cpu_hotplug_begin(void) 134d221938cSGautham R Shenoy { 135d221938cSGautham R Shenoy cpu_hotplug.active_writer = current; 136d2ba7e2aSOleg Nesterov 137d2ba7e2aSOleg Nesterov for (;;) { 138d2ba7e2aSOleg Nesterov mutex_lock(&cpu_hotplug.lock); 139d2ba7e2aSOleg Nesterov if (likely(!cpu_hotplug.refcount)) 140d2ba7e2aSOleg Nesterov break; 141d2ba7e2aSOleg Nesterov __set_current_state(TASK_UNINTERRUPTIBLE); 142d221938cSGautham R Shenoy mutex_unlock(&cpu_hotplug.lock); 143d221938cSGautham R Shenoy schedule(); 144d221938cSGautham R Shenoy } 145d221938cSGautham R Shenoy } 146d221938cSGautham R Shenoy 147d221938cSGautham R Shenoy static void cpu_hotplug_done(void) 148d221938cSGautham R Shenoy { 149d221938cSGautham R Shenoy cpu_hotplug.active_writer = NULL; 150d221938cSGautham R Shenoy mutex_unlock(&cpu_hotplug.lock); 151d221938cSGautham R Shenoy } 1521da177e4SLinus Torvalds /* Need to know about CPUs going up/down? */ 153f7b16c10SSam Ravnborg int __ref register_cpu_notifier(struct notifier_block *nb) 1541da177e4SLinus Torvalds { 155bd5349cfSNeil Brown int ret; 156d221938cSGautham R Shenoy cpu_maps_update_begin(); 157bd5349cfSNeil Brown ret = raw_notifier_chain_register(&cpu_chain, nb); 158d221938cSGautham R Shenoy cpu_maps_update_done(); 159bd5349cfSNeil Brown return ret; 1601da177e4SLinus Torvalds } 16165edc68cSChandra Seetharaman 16265edc68cSChandra Seetharaman #ifdef CONFIG_HOTPLUG_CPU 16365edc68cSChandra Seetharaman 1641da177e4SLinus Torvalds EXPORT_SYMBOL(register_cpu_notifier); 1651da177e4SLinus Torvalds 1669647155fSSam Ravnborg void __ref unregister_cpu_notifier(struct notifier_block *nb) 1671da177e4SLinus Torvalds { 168d221938cSGautham R Shenoy cpu_maps_update_begin(); 169bd5349cfSNeil Brown raw_notifier_chain_unregister(&cpu_chain, nb); 170d221938cSGautham R Shenoy cpu_maps_update_done(); 1711da177e4SLinus Torvalds } 1721da177e4SLinus Torvalds EXPORT_SYMBOL(unregister_cpu_notifier); 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds static inline void check_for_tasks(int cpu) 1751da177e4SLinus Torvalds { 1761da177e4SLinus Torvalds struct task_struct *p; 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds write_lock_irq(&tasklist_lock); 1791da177e4SLinus Torvalds for_each_process(p) { 1801da177e4SLinus Torvalds if (task_cpu(p) == cpu && 1811da177e4SLinus Torvalds (!cputime_eq(p->utime, cputime_zero) || 1821da177e4SLinus Torvalds !cputime_eq(p->stime, cputime_zero))) 1831da177e4SLinus Torvalds printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\ 184e7407dccSHeiko Carstens (state = %ld, flags = %x) \n", 185ba25f9dcSPavel Emelyanov p->comm, task_pid_nr(p), cpu, 186ba25f9dcSPavel Emelyanov p->state, p->flags); 1871da177e4SLinus Torvalds } 1881da177e4SLinus Torvalds write_unlock_irq(&tasklist_lock); 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds 191db912f96SAvi Kivity struct take_cpu_down_param { 192db912f96SAvi Kivity unsigned long mod; 193db912f96SAvi Kivity void *hcpu; 194db912f96SAvi Kivity }; 195db912f96SAvi Kivity 1961da177e4SLinus Torvalds /* Take this CPU down. */ 197514a20a5SSam Ravnborg static int __ref take_cpu_down(void *_param) 1981da177e4SLinus Torvalds { 199db912f96SAvi Kivity struct take_cpu_down_param *param = _param; 2001da177e4SLinus Torvalds int err; 2011da177e4SLinus Torvalds 202db912f96SAvi Kivity raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod, 203db912f96SAvi Kivity param->hcpu); 2041da177e4SLinus Torvalds /* Ensure this CPU doesn't handle any more interrupts. */ 2051da177e4SLinus Torvalds err = __cpu_disable(); 2061da177e4SLinus Torvalds if (err < 0) 207f3705136SZwane Mwaikambo return err; 208f3705136SZwane Mwaikambo 2091da177e4SLinus Torvalds /* Force idle task to run as soon as we yield: it should 2101da177e4SLinus Torvalds immediately notice cpu is offline and die quickly. */ 2111da177e4SLinus Torvalds sched_idle_next(); 212f3705136SZwane Mwaikambo return 0; 2131da177e4SLinus Torvalds } 2141da177e4SLinus Torvalds 215e3920fb4SRafael J. Wysocki /* Requires cpu_add_remove_lock to be held */ 216514a20a5SSam Ravnborg static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) 2171da177e4SLinus Torvalds { 218e7407dccSHeiko Carstens int err, nr_calls = 0; 2191da177e4SLinus Torvalds struct task_struct *p; 2201da177e4SLinus Torvalds cpumask_t old_allowed, tmp; 221e7407dccSHeiko Carstens void *hcpu = (void *)(long)cpu; 2228bb78442SRafael J. Wysocki unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; 223db912f96SAvi Kivity struct take_cpu_down_param tcd_param = { 224db912f96SAvi Kivity .mod = mod, 225db912f96SAvi Kivity .hcpu = hcpu, 226db912f96SAvi Kivity }; 2271da177e4SLinus Torvalds 228e3920fb4SRafael J. Wysocki if (num_online_cpus() == 1) 229e3920fb4SRafael J. Wysocki return -EBUSY; 2301da177e4SLinus Torvalds 231e3920fb4SRafael J. Wysocki if (!cpu_online(cpu)) 232e3920fb4SRafael J. Wysocki return -EINVAL; 2331da177e4SLinus Torvalds 234d221938cSGautham R Shenoy cpu_hotplug_begin(); 2358bb78442SRafael J. Wysocki err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, 236e7407dccSHeiko Carstens hcpu, -1, &nr_calls); 2371da177e4SLinus Torvalds if (err == NOTIFY_BAD) { 238a0d8cdb6SAkinobu Mita nr_calls--; 2398bb78442SRafael J. Wysocki __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, 2408bb78442SRafael J. Wysocki hcpu, nr_calls, NULL); 2411da177e4SLinus Torvalds printk("%s: attempt to take down CPU %u failed\n", 242af1f16d0SHarvey Harrison __func__, cpu); 243baaca49fSGautham R Shenoy err = -EINVAL; 244baaca49fSGautham R Shenoy goto out_release; 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds /* Ensure that we are not runnable on dying cpu */ 2481da177e4SLinus Torvalds old_allowed = current->cpus_allowed; 249f70316daSMike Travis cpus_setall(tmp); 2501da177e4SLinus Torvalds cpu_clear(cpu, tmp); 251f70316daSMike Travis set_cpus_allowed_ptr(current, &tmp); 2521da177e4SLinus Torvalds 253db912f96SAvi Kivity p = __stop_machine_run(take_cpu_down, &tcd_param, cpu); 254aa953877SLinus Torvalds 2558fa1d7d3SSatoru Takeuchi if (IS_ERR(p) || cpu_online(cpu)) { 2561da177e4SLinus Torvalds /* CPU didn't die: tell everyone. Can't complain. */ 2578bb78442SRafael J. Wysocki if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, 258e7407dccSHeiko Carstens hcpu) == NOTIFY_BAD) 2591da177e4SLinus Torvalds BUG(); 2601da177e4SLinus Torvalds 2618fa1d7d3SSatoru Takeuchi if (IS_ERR(p)) { 2621da177e4SLinus Torvalds err = PTR_ERR(p); 2631da177e4SLinus Torvalds goto out_allowed; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds goto out_thread; 2668fa1d7d3SSatoru Takeuchi } 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds /* Wait for it to sleep (leaving idle task). */ 2691da177e4SLinus Torvalds while (!idle_cpu(cpu)) 2701da177e4SLinus Torvalds yield(); 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds /* This actually kills the CPU. */ 2731da177e4SLinus Torvalds __cpu_die(cpu); 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds /* CPU is completely dead: tell everyone. Too late to complain. */ 2768bb78442SRafael J. Wysocki if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD | mod, 2778bb78442SRafael J. Wysocki hcpu) == NOTIFY_BAD) 2781da177e4SLinus Torvalds BUG(); 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds check_for_tasks(cpu); 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds out_thread: 2831da177e4SLinus Torvalds err = kthread_stop(p); 2841da177e4SLinus Torvalds out_allowed: 285f70316daSMike Travis set_cpus_allowed_ptr(current, &old_allowed); 286baaca49fSGautham R Shenoy out_release: 287d221938cSGautham R Shenoy cpu_hotplug_done(); 288*3da1c84cSOleg Nesterov if (!err) { 289*3da1c84cSOleg Nesterov if (raw_notifier_call_chain(&cpu_chain, CPU_POST_DEAD | mod, 290*3da1c84cSOleg Nesterov hcpu) == NOTIFY_BAD) 291*3da1c84cSOleg Nesterov BUG(); 292*3da1c84cSOleg Nesterov } 293e3920fb4SRafael J. Wysocki return err; 294e3920fb4SRafael J. Wysocki } 295e3920fb4SRafael J. Wysocki 296514a20a5SSam Ravnborg int __ref cpu_down(unsigned int cpu) 297e3920fb4SRafael J. Wysocki { 298e3920fb4SRafael J. Wysocki int err = 0; 299e3920fb4SRafael J. Wysocki 300d221938cSGautham R Shenoy cpu_maps_update_begin(); 301e761b772SMax Krasnyansky 302e761b772SMax Krasnyansky if (cpu_hotplug_disabled) { 303e3920fb4SRafael J. Wysocki err = -EBUSY; 304e761b772SMax Krasnyansky goto out; 305e761b772SMax Krasnyansky } 306e761b772SMax Krasnyansky 307e761b772SMax Krasnyansky cpu_clear(cpu, cpu_active_map); 308e761b772SMax Krasnyansky 30939b0fad7SMax Krasnyansky /* 31039b0fad7SMax Krasnyansky * Make sure the all cpus did the reschedule and are not 31139b0fad7SMax Krasnyansky * using stale version of the cpu_active_map. 31239b0fad7SMax Krasnyansky * This is not strictly necessary becuase stop_machine() 31339b0fad7SMax Krasnyansky * that we run down the line already provides the required 31439b0fad7SMax Krasnyansky * synchronization. But it's really a side effect and we do not 31539b0fad7SMax Krasnyansky * want to depend on the innards of the stop_machine here. 31639b0fad7SMax Krasnyansky */ 31739b0fad7SMax Krasnyansky synchronize_sched(); 31839b0fad7SMax Krasnyansky 3198bb78442SRafael J. Wysocki err = _cpu_down(cpu, 0); 320e3920fb4SRafael J. Wysocki 321e761b772SMax Krasnyansky if (cpu_online(cpu)) 322e761b772SMax Krasnyansky cpu_set(cpu, cpu_active_map); 323e761b772SMax Krasnyansky 324e761b772SMax Krasnyansky out: 325d221938cSGautham R Shenoy cpu_maps_update_done(); 3261da177e4SLinus Torvalds return err; 3271da177e4SLinus Torvalds } 328b62b8ef9SZhang Rui EXPORT_SYMBOL(cpu_down); 3291da177e4SLinus Torvalds #endif /*CONFIG_HOTPLUG_CPU*/ 3301da177e4SLinus Torvalds 331e3920fb4SRafael J. Wysocki /* Requires cpu_add_remove_lock to be held */ 3328bb78442SRafael J. Wysocki static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) 3331da177e4SLinus Torvalds { 334baaca49fSGautham R Shenoy int ret, nr_calls = 0; 3351da177e4SLinus Torvalds void *hcpu = (void *)(long)cpu; 3368bb78442SRafael J. Wysocki unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; 3371da177e4SLinus Torvalds 338e3920fb4SRafael J. Wysocki if (cpu_online(cpu) || !cpu_present(cpu)) 339e3920fb4SRafael J. Wysocki return -EINVAL; 34090d45d17SAshok Raj 341d221938cSGautham R Shenoy cpu_hotplug_begin(); 3428bb78442SRafael J. Wysocki ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE | mod, hcpu, 343baaca49fSGautham R Shenoy -1, &nr_calls); 3441da177e4SLinus Torvalds if (ret == NOTIFY_BAD) { 345a0d8cdb6SAkinobu Mita nr_calls--; 3461da177e4SLinus Torvalds printk("%s: attempt to bring up CPU %u failed\n", 347af1f16d0SHarvey Harrison __func__, cpu); 3481da177e4SLinus Torvalds ret = -EINVAL; 3491da177e4SLinus Torvalds goto out_notify; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /* Arch-specific enabling code. */ 3531da177e4SLinus Torvalds ret = __cpu_up(cpu); 3541da177e4SLinus Torvalds if (ret != 0) 3551da177e4SLinus Torvalds goto out_notify; 3566978c705SEric Sesterhenn BUG_ON(!cpu_online(cpu)); 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds /* Now call notifier in preparation. */ 3598bb78442SRafael J. Wysocki raw_notifier_call_chain(&cpu_chain, CPU_ONLINE | mod, hcpu); 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds out_notify: 3621da177e4SLinus Torvalds if (ret != 0) 363baaca49fSGautham R Shenoy __raw_notifier_call_chain(&cpu_chain, 3648bb78442SRafael J. Wysocki CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); 365d221938cSGautham R Shenoy cpu_hotplug_done(); 366e3920fb4SRafael J. Wysocki 3671da177e4SLinus Torvalds return ret; 3681da177e4SLinus Torvalds } 369e3920fb4SRafael J. Wysocki 370b282b6f8SGautham R Shenoy int __cpuinit cpu_up(unsigned int cpu) 371e3920fb4SRafael J. Wysocki { 372e3920fb4SRafael J. Wysocki int err = 0; 37373e753a5SKAMEZAWA Hiroyuki if (!cpu_isset(cpu, cpu_possible_map)) { 37473e753a5SKAMEZAWA Hiroyuki printk(KERN_ERR "can't online cpu %d because it is not " 37573e753a5SKAMEZAWA Hiroyuki "configured as may-hotadd at boot time\n", cpu); 37673e753a5SKAMEZAWA Hiroyuki #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) || defined(CONFIG_S390) 37773e753a5SKAMEZAWA Hiroyuki printk(KERN_ERR "please check additional_cpus= boot " 37873e753a5SKAMEZAWA Hiroyuki "parameter\n"); 37973e753a5SKAMEZAWA Hiroyuki #endif 38073e753a5SKAMEZAWA Hiroyuki return -EINVAL; 38173e753a5SKAMEZAWA Hiroyuki } 382e3920fb4SRafael J. Wysocki 383d221938cSGautham R Shenoy cpu_maps_update_begin(); 384e761b772SMax Krasnyansky 385e761b772SMax Krasnyansky if (cpu_hotplug_disabled) { 386e3920fb4SRafael J. Wysocki err = -EBUSY; 387e761b772SMax Krasnyansky goto out; 388e761b772SMax Krasnyansky } 389e761b772SMax Krasnyansky 3908bb78442SRafael J. Wysocki err = _cpu_up(cpu, 0); 391e3920fb4SRafael J. Wysocki 392e761b772SMax Krasnyansky if (cpu_online(cpu)) 393e761b772SMax Krasnyansky cpu_set(cpu, cpu_active_map); 394e761b772SMax Krasnyansky 395e761b772SMax Krasnyansky out: 396d221938cSGautham R Shenoy cpu_maps_update_done(); 397e3920fb4SRafael J. Wysocki return err; 398e3920fb4SRafael J. Wysocki } 399e3920fb4SRafael J. Wysocki 400f3de4be9SRafael J. Wysocki #ifdef CONFIG_PM_SLEEP_SMP 401e3920fb4SRafael J. Wysocki static cpumask_t frozen_cpus; 402e3920fb4SRafael J. Wysocki 403e3920fb4SRafael J. Wysocki int disable_nonboot_cpus(void) 404e3920fb4SRafael J. Wysocki { 405e1d9fd2eSIngo Molnar int cpu, first_cpu, error = 0; 406e3920fb4SRafael J. Wysocki 407d221938cSGautham R Shenoy cpu_maps_update_begin(); 4081d64b9cbSRafael J. Wysocki first_cpu = first_cpu(cpu_online_map); 409e3920fb4SRafael J. Wysocki /* We take down all of the non-boot CPUs in one shot to avoid races 410e3920fb4SRafael J. Wysocki * with the userspace trying to use the CPU hotplug at the same time 411e3920fb4SRafael J. Wysocki */ 412e3920fb4SRafael J. Wysocki cpus_clear(frozen_cpus); 413e3920fb4SRafael J. Wysocki printk("Disabling non-boot CPUs ...\n"); 414e3920fb4SRafael J. Wysocki for_each_online_cpu(cpu) { 415e3920fb4SRafael J. Wysocki if (cpu == first_cpu) 416e3920fb4SRafael J. Wysocki continue; 4178bb78442SRafael J. Wysocki error = _cpu_down(cpu, 1); 418e3920fb4SRafael J. Wysocki if (!error) { 419e3920fb4SRafael J. Wysocki cpu_set(cpu, frozen_cpus); 420e3920fb4SRafael J. Wysocki printk("CPU%d is down\n", cpu); 421e3920fb4SRafael J. Wysocki } else { 422e3920fb4SRafael J. Wysocki printk(KERN_ERR "Error taking CPU%d down: %d\n", 423e3920fb4SRafael J. Wysocki cpu, error); 424e3920fb4SRafael J. Wysocki break; 425e3920fb4SRafael J. Wysocki } 426e3920fb4SRafael J. Wysocki } 427e3920fb4SRafael J. Wysocki if (!error) { 428e3920fb4SRafael J. Wysocki BUG_ON(num_online_cpus() > 1); 429e3920fb4SRafael J. Wysocki /* Make sure the CPUs won't be enabled by someone else */ 430e3920fb4SRafael J. Wysocki cpu_hotplug_disabled = 1; 431e3920fb4SRafael J. Wysocki } else { 432e1d9fd2eSIngo Molnar printk(KERN_ERR "Non-boot CPUs are not disabled\n"); 433e3920fb4SRafael J. Wysocki } 434d221938cSGautham R Shenoy cpu_maps_update_done(); 435e3920fb4SRafael J. Wysocki return error; 436e3920fb4SRafael J. Wysocki } 437e3920fb4SRafael J. Wysocki 438fa7303e2SSam Ravnborg void __ref enable_nonboot_cpus(void) 439e3920fb4SRafael J. Wysocki { 440e3920fb4SRafael J. Wysocki int cpu, error; 441e3920fb4SRafael J. Wysocki 442e3920fb4SRafael J. Wysocki /* Allow everyone to use the CPU hotplug again */ 443d221938cSGautham R Shenoy cpu_maps_update_begin(); 444e3920fb4SRafael J. Wysocki cpu_hotplug_disabled = 0; 445ed746e3bSRafael J. Wysocki if (cpus_empty(frozen_cpus)) 4461d64b9cbSRafael J. Wysocki goto out; 447e3920fb4SRafael J. Wysocki 448e3920fb4SRafael J. Wysocki printk("Enabling non-boot CPUs ...\n"); 449363ab6f1SMike Travis for_each_cpu_mask_nr(cpu, frozen_cpus) { 4508bb78442SRafael J. Wysocki error = _cpu_up(cpu, 1); 451e3920fb4SRafael J. Wysocki if (!error) { 452e3920fb4SRafael J. Wysocki printk("CPU%d is up\n", cpu); 453e3920fb4SRafael J. Wysocki continue; 454e3920fb4SRafael J. Wysocki } 4551d64b9cbSRafael J. Wysocki printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); 456e3920fb4SRafael J. Wysocki } 457e3920fb4SRafael J. Wysocki cpus_clear(frozen_cpus); 4581d64b9cbSRafael J. Wysocki out: 459d221938cSGautham R Shenoy cpu_maps_update_done(); 460e3920fb4SRafael J. Wysocki } 461f3de4be9SRafael J. Wysocki #endif /* CONFIG_PM_SLEEP_SMP */ 46268f4f1ecSMax Krasnyansky 46368f4f1ecSMax Krasnyansky #endif /* CONFIG_SMP */ 464