diff options
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r-- | kernel/cpu.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 28cb6c71a47a..369d2892687d 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -120,12 +120,13 @@ static int take_cpu_down(void *unused) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | /* Requires cpu_add_remove_lock to be held */ | 122 | /* Requires cpu_add_remove_lock to be held */ |
123 | static int _cpu_down(unsigned int cpu) | 123 | static int _cpu_down(unsigned int cpu, int tasks_frozen) |
124 | { | 124 | { |
125 | int err, nr_calls = 0; | 125 | int err, nr_calls = 0; |
126 | struct task_struct *p; | 126 | struct task_struct *p; |
127 | cpumask_t old_allowed, tmp; | 127 | cpumask_t old_allowed, tmp; |
128 | void *hcpu = (void *)(long)cpu; | 128 | void *hcpu = (void *)(long)cpu; |
129 | unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; | ||
129 | 130 | ||
130 | if (num_online_cpus() == 1) | 131 | if (num_online_cpus() == 1) |
131 | return -EBUSY; | 132 | return -EBUSY; |
@@ -134,11 +135,11 @@ static int _cpu_down(unsigned int cpu) | |||
134 | return -EINVAL; | 135 | return -EINVAL; |
135 | 136 | ||
136 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu); | 137 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu); |
137 | err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, | 138 | err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, |
138 | hcpu, -1, &nr_calls); | 139 | hcpu, -1, &nr_calls); |
139 | if (err == NOTIFY_BAD) { | 140 | if (err == NOTIFY_BAD) { |
140 | __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, hcpu, | 141 | __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, |
141 | nr_calls, NULL); | 142 | hcpu, nr_calls, NULL); |
142 | printk("%s: attempt to take down CPU %u failed\n", | 143 | printk("%s: attempt to take down CPU %u failed\n", |
143 | __FUNCTION__, cpu); | 144 | __FUNCTION__, cpu); |
144 | err = -EINVAL; | 145 | err = -EINVAL; |
@@ -157,7 +158,7 @@ static int _cpu_down(unsigned int cpu) | |||
157 | 158 | ||
158 | if (IS_ERR(p) || cpu_online(cpu)) { | 159 | if (IS_ERR(p) || cpu_online(cpu)) { |
159 | /* CPU didn't die: tell everyone. Can't complain. */ | 160 | /* CPU didn't die: tell everyone. Can't complain. */ |
160 | if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, | 161 | if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, |
161 | hcpu) == NOTIFY_BAD) | 162 | hcpu) == NOTIFY_BAD) |
162 | BUG(); | 163 | BUG(); |
163 | 164 | ||
@@ -176,7 +177,8 @@ static int _cpu_down(unsigned int cpu) | |||
176 | __cpu_die(cpu); | 177 | __cpu_die(cpu); |
177 | 178 | ||
178 | /* CPU is completely dead: tell everyone. Too late to complain. */ | 179 | /* CPU is completely dead: tell everyone. Too late to complain. */ |
179 | if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD, hcpu) == NOTIFY_BAD) | 180 | if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD | mod, |
181 | hcpu) == NOTIFY_BAD) | ||
180 | BUG(); | 182 | BUG(); |
181 | 183 | ||
182 | check_for_tasks(cpu); | 184 | check_for_tasks(cpu); |
@@ -186,8 +188,7 @@ out_thread: | |||
186 | out_allowed: | 188 | out_allowed: |
187 | set_cpus_allowed(current, old_allowed); | 189 | set_cpus_allowed(current, old_allowed); |
188 | out_release: | 190 | out_release: |
189 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, | 191 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, hcpu); |
190 | (void *)(long)cpu); | ||
191 | return err; | 192 | return err; |
192 | } | 193 | } |
193 | 194 | ||
@@ -199,7 +200,7 @@ int cpu_down(unsigned int cpu) | |||
199 | if (cpu_hotplug_disabled) | 200 | if (cpu_hotplug_disabled) |
200 | err = -EBUSY; | 201 | err = -EBUSY; |
201 | else | 202 | else |
202 | err = _cpu_down(cpu); | 203 | err = _cpu_down(cpu, 0); |
203 | 204 | ||
204 | mutex_unlock(&cpu_add_remove_lock); | 205 | mutex_unlock(&cpu_add_remove_lock); |
205 | return err; | 206 | return err; |
@@ -207,16 +208,17 @@ int cpu_down(unsigned int cpu) | |||
207 | #endif /*CONFIG_HOTPLUG_CPU*/ | 208 | #endif /*CONFIG_HOTPLUG_CPU*/ |
208 | 209 | ||
209 | /* Requires cpu_add_remove_lock to be held */ | 210 | /* Requires cpu_add_remove_lock to be held */ |
210 | static int __cpuinit _cpu_up(unsigned int cpu) | 211 | static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) |
211 | { | 212 | { |
212 | int ret, nr_calls = 0; | 213 | int ret, nr_calls = 0; |
213 | void *hcpu = (void *)(long)cpu; | 214 | void *hcpu = (void *)(long)cpu; |
215 | unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; | ||
214 | 216 | ||
215 | if (cpu_online(cpu) || !cpu_present(cpu)) | 217 | if (cpu_online(cpu) || !cpu_present(cpu)) |
216 | return -EINVAL; | 218 | return -EINVAL; |
217 | 219 | ||
218 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu); | 220 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu); |
219 | ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu, | 221 | ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE | mod, hcpu, |
220 | -1, &nr_calls); | 222 | -1, &nr_calls); |
221 | if (ret == NOTIFY_BAD) { | 223 | if (ret == NOTIFY_BAD) { |
222 | printk("%s: attempt to bring up CPU %u failed\n", | 224 | printk("%s: attempt to bring up CPU %u failed\n", |
@@ -234,12 +236,12 @@ static int __cpuinit _cpu_up(unsigned int cpu) | |||
234 | BUG_ON(!cpu_online(cpu)); | 236 | BUG_ON(!cpu_online(cpu)); |
235 | 237 | ||
236 | /* Now call notifier in preparation. */ | 238 | /* Now call notifier in preparation. */ |
237 | raw_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); | 239 | raw_notifier_call_chain(&cpu_chain, CPU_ONLINE | mod, hcpu); |
238 | 240 | ||
239 | out_notify: | 241 | out_notify: |
240 | if (ret != 0) | 242 | if (ret != 0) |
241 | __raw_notifier_call_chain(&cpu_chain, | 243 | __raw_notifier_call_chain(&cpu_chain, |
242 | CPU_UP_CANCELED, hcpu, nr_calls, NULL); | 244 | CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); |
243 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, hcpu); | 245 | raw_notifier_call_chain(&cpu_chain, CPU_LOCK_RELEASE, hcpu); |
244 | 246 | ||
245 | return ret; | 247 | return ret; |
@@ -253,7 +255,7 @@ int __cpuinit cpu_up(unsigned int cpu) | |||
253 | if (cpu_hotplug_disabled) | 255 | if (cpu_hotplug_disabled) |
254 | err = -EBUSY; | 256 | err = -EBUSY; |
255 | else | 257 | else |
256 | err = _cpu_up(cpu); | 258 | err = _cpu_up(cpu, 0); |
257 | 259 | ||
258 | mutex_unlock(&cpu_add_remove_lock); | 260 | mutex_unlock(&cpu_add_remove_lock); |
259 | return err; | 261 | return err; |
@@ -283,7 +285,7 @@ int disable_nonboot_cpus(void) | |||
283 | for_each_online_cpu(cpu) { | 285 | for_each_online_cpu(cpu) { |
284 | if (cpu == first_cpu) | 286 | if (cpu == first_cpu) |
285 | continue; | 287 | continue; |
286 | error = _cpu_down(cpu); | 288 | error = _cpu_down(cpu, 1); |
287 | if (!error) { | 289 | if (!error) { |
288 | cpu_set(cpu, frozen_cpus); | 290 | cpu_set(cpu, frozen_cpus); |
289 | printk("CPU%d is down\n", cpu); | 291 | printk("CPU%d is down\n", cpu); |
@@ -318,7 +320,7 @@ void enable_nonboot_cpus(void) | |||
318 | suspend_cpu_hotplug = 1; | 320 | suspend_cpu_hotplug = 1; |
319 | printk("Enabling non-boot CPUs ...\n"); | 321 | printk("Enabling non-boot CPUs ...\n"); |
320 | for_each_cpu_mask(cpu, frozen_cpus) { | 322 | for_each_cpu_mask(cpu, frozen_cpus) { |
321 | error = _cpu_up(cpu); | 323 | error = _cpu_up(cpu, 1); |
322 | if (!error) { | 324 | if (!error) { |
323 | printk("CPU%d is up\n", cpu); | 325 | printk("CPU%d is up\n", cpu); |
324 | continue; | 326 | continue; |