/* Requires cpu_add_remove_lock to be held */ static int _cpu_up(unsigned int cpu, int tasks_frozen) { int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; if (cpu_online(cpu) || !cpu_present(cpu)) return -EINVAL; cpu_hotplug_begin(); ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n", __func__, cpu); goto out_notify; } /* Arch-specific enabling code. */ ret = __cpu_up(cpu); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); /* Now call notifier in preparation. */ cpu_notify(CPU_ONLINE | mod, hcpu); out_notify: if (ret != 0) __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); cpu_hotplug_done(); return ret; }
/* Requires cpu_add_remove_lock to be held */ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) { int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; struct task_struct *idle; cpu_hotplug_begin(); if (cpu_online(cpu)) { ret = 0; goto out; } if (!cpu_present(cpu)) { ret = -EINVAL; goto out; } idle = idle_thread_get(cpu); if (IS_ERR(idle)) { ret = PTR_ERR(idle); goto out; } ret = smpboot_create_threads(cpu); if (ret) goto out; ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n", __func__, cpu); goto out_notify; } /* Arch-specific enabling code. */ ret = __cpu_up(cpu, idle); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); /* Wake the per cpu threads */ smpboot_unpark_threads(cpu); /* Now call notifier in preparation. */ cpu_notify(CPU_ONLINE | mod, hcpu); out_notify: if (ret != 0) __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); out: cpu_hotplug_done(); trace_sched_cpu_hotplug(cpu, ret, 1); return ret; }
static int bringup_cpu(unsigned int cpu) { struct task_struct *idle = idle_thread_get(cpu); int ret; /* Arch-specific enabling code. */ ret = __cpu_up(cpu, idle); if (ret) { cpu_notify(CPU_UP_CANCELED, cpu); return ret; } ret = bringup_wait_for_ap(cpu); BUG_ON(!cpu_online(cpu)); return ret; }
static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) { int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; if (cpu_online(cpu) || !cpu_present(cpu)) return -EINVAL; cpu_hotplug_begin(); ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n", __func__, cpu); goto out_notify; } ret = __cpu_up(cpu); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); cpu_notify(CPU_ONLINE | mod, hcpu); #ifdef CONFIG_HTC_ACPU_DEBUG { unsigned int status = 1; msm_proc_comm(PCOM_BACKUP_CPU_STATUS, (unsigned*)&cpu, (unsigned*) &status); } #endif out_notify: if (ret != 0) __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); cpu_hotplug_done(); return ret; }
int cpu_up(unsigned int cpu) { int notifier_rc, err = 0; void *hcpu = (void *)(long)cpu; struct notifier_block *nb = NULL; if ( !cpu_hotplug_begin() ) return -EBUSY; if ( (cpu >= NR_CPUS) || cpu_online(cpu) || !cpu_present(cpu) ) { cpu_hotplug_done(); return -EINVAL; } notifier_rc = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu, &nb); if ( notifier_rc != NOTIFY_DONE ) { err = notifier_to_errno(notifier_rc); goto fail; } err = __cpu_up(cpu); if ( err < 0 ) goto fail; notifier_rc = notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu, NULL); BUG_ON(notifier_rc != NOTIFY_DONE); send_guest_global_virq(dom0, VIRQ_PCPU_STATE); cpu_hotplug_done(); return 0; fail: notifier_rc = notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu, &nb); BUG_ON(notifier_rc != NOTIFY_DONE); cpu_hotplug_done(); return err; }