aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-05-09 05:35:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:56 -0400
commit8bb7844286fb8c9fce6f65d8288aeb09d03a5e0d (patch)
treef4e305edaedbde05774bb1e4acd89a9475661d2e /kernel/cpu.c
parentf37bc2712b54ec641e0c0c8634f1a4b61d9956c0 (diff)
Add suspend-related notifications for CPU hotplug
Since nonboot CPUs are now disabled after tasks and devices have been frozen and the CPU hotplug infrastructure is used for this purpose, we need special CPU hotplug notifications that will help the CPU-hotplug-aware subsystems distinguish normal CPU hotplug events from CPU hotplug events related to a system-wide suspend or resume operation in progress. This patch introduces such notifications and causes them to be used during suspend and resume transitions. It also changes all of the CPU-hotplug-aware subsystems to take these notifications into consideration (for now they are handled in the same way as the corresponding "normal" ones). [oleg@tv-sign.ru: cleanups] Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Gautham R Shenoy <ego@in.ibm.com> Cc: Pavel Machek <pavel@ucw.cz> Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c34
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 */
123static int _cpu_down(unsigned int cpu) 123static 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:
186out_allowed: 188out_allowed:
187 set_cpus_allowed(current, old_allowed); 189 set_cpus_allowed(current, old_allowed);
188out_release: 190out_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 */
210static int __cpuinit _cpu_up(unsigned int cpu) 211static 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
239out_notify: 241out_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;