Blame view

kernel/cpu.c 15.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /* CPU control.
   * (C) 2001, 2002, 2003, 2004 Rusty Russell
   *
   * This code is licenced under the GPL.
   */
  #include <linux/proc_fs.h>
  #include <linux/smp.h>
  #include <linux/init.h>
  #include <linux/notifier.h>
  #include <linux/sched.h>
  #include <linux/unistd.h>
  #include <linux/cpu.h>
9984de1a5   Paul Gortmaker   kernel: Map most ...
13
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/kthread.h>
  #include <linux/stop_machine.h>
81615b624   Ingo Molnar   [PATCH] Convert k...
16
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/gfp.h>
79cfbdfa8   Srivatsa S. Bhat   PM / Sleep: Fix r...
18
  #include <linux/suspend.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19

98a79d6a5   Rusty Russell   cpumask: centrali...
20
  #ifdef CONFIG_SMP
b3199c025   Rusty Russell   cpumask: switch o...
21
  /* Serializes the updates to cpu_online_mask, cpu_present_mask */
aa9538777   Linus Torvalds   cpu hotplug: simp...
22
  static DEFINE_MUTEX(cpu_add_remove_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

79a6cdeb7   Lai Jiangshan   cpuhotplug: do no...
24
25
26
27
28
29
30
31
32
33
34
35
36
  /*
   * The following two API's must be used when attempting
   * to serialize the updates to cpu_online_mask, cpu_present_mask.
   */
  void cpu_maps_update_begin(void)
  {
  	mutex_lock(&cpu_add_remove_lock);
  }
  
  void cpu_maps_update_done(void)
  {
  	mutex_unlock(&cpu_add_remove_lock);
  }
5c113fbee   Daniel J Blueman   fix cpu_chain sec...
37
  static RAW_NOTIFIER_HEAD(cpu_chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
39
40
41
42
  /* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
   * Should always be manipulated under cpu_add_remove_lock
   */
  static int cpu_hotplug_disabled;
79a6cdeb7   Lai Jiangshan   cpuhotplug: do no...
43
  #ifdef CONFIG_HOTPLUG_CPU
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
44
45
46
47
48
49
50
51
  static struct {
  	struct task_struct *active_writer;
  	struct mutex lock; /* Synchronizes accesses to refcount, */
  	/*
  	 * Also blocks the new readers during
  	 * an ongoing cpu hotplug operation.
  	 */
  	int refcount;
31950eb66   Linus Torvalds   mm/init: cpu_hotp...
52
53
54
55
56
  } cpu_hotplug = {
  	.active_writer = NULL,
  	.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
  	.refcount = 0,
  };
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
57

86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
58
  void get_online_cpus(void)
a9d9baa1e   Ashok Raj   [PATCH] clean up ...
59
  {
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
60
61
  	might_sleep();
  	if (cpu_hotplug.active_writer == current)
aa9538777   Linus Torvalds   cpu hotplug: simp...
62
  		return;
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
63
64
65
  	mutex_lock(&cpu_hotplug.lock);
  	cpu_hotplug.refcount++;
  	mutex_unlock(&cpu_hotplug.lock);
a9d9baa1e   Ashok Raj   [PATCH] clean up ...
66
  }
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
67
  EXPORT_SYMBOL_GPL(get_online_cpus);
90d45d17f   Ashok Raj   [PATCH] cpu hotpl...
68

86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
69
  void put_online_cpus(void)
a9d9baa1e   Ashok Raj   [PATCH] clean up ...
70
  {
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
71
  	if (cpu_hotplug.active_writer == current)
aa9538777   Linus Torvalds   cpu hotplug: simp...
72
  		return;
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
73
  	mutex_lock(&cpu_hotplug.lock);
d2ba7e2ae   Oleg Nesterov   simplify cpu_hotp...
74
75
  	if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
  		wake_up_process(cpu_hotplug.active_writer);
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
76
  	mutex_unlock(&cpu_hotplug.lock);
a9d9baa1e   Ashok Raj   [PATCH] clean up ...
77
  }
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
78
  EXPORT_SYMBOL_GPL(put_online_cpus);
a9d9baa1e   Ashok Raj   [PATCH] clean up ...
79

d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
80
81
82
83
84
85
86
  /*
   * This ensures that the hotplug operation can begin only when the
   * refcount goes to zero.
   *
   * Note that during a cpu-hotplug operation, the new readers, if any,
   * will be blocked by the cpu_hotplug.lock
   *
d2ba7e2ae   Oleg Nesterov   simplify cpu_hotp...
87
88
   * Since cpu_hotplug_begin() is always called after invoking
   * cpu_maps_update_begin(), we can be sure that only one writer is active.
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
89
90
91
92
93
94
95
96
97
98
   *
   * Note that theoretically, there is a possibility of a livelock:
   * - Refcount goes to zero, last reader wakes up the sleeping
   *   writer.
   * - Last reader unlocks the cpu_hotplug.lock.
   * - A new reader arrives at this moment, bumps up the refcount.
   * - The writer acquires the cpu_hotplug.lock finds the refcount
   *   non zero and goes to sleep again.
   *
   * However, this is very difficult to achieve in practice since
86ef5c9a8   Gautham R Shenoy   cpu-hotplug: repl...
99
   * get_online_cpus() not an api which is called all that often.
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
100
101
102
103
   *
   */
  static void cpu_hotplug_begin(void)
  {
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
104
  	cpu_hotplug.active_writer = current;
d2ba7e2ae   Oleg Nesterov   simplify cpu_hotp...
105
106
107
108
109
110
  
  	for (;;) {
  		mutex_lock(&cpu_hotplug.lock);
  		if (likely(!cpu_hotplug.refcount))
  			break;
  		__set_current_state(TASK_UNINTERRUPTIBLE);
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
111
112
  		mutex_unlock(&cpu_hotplug.lock);
  		schedule();
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
113
  	}
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
114
115
116
117
118
119
120
  }
  
  static void cpu_hotplug_done(void)
  {
  	cpu_hotplug.active_writer = NULL;
  	mutex_unlock(&cpu_hotplug.lock);
  }
79a6cdeb7   Lai Jiangshan   cpuhotplug: do no...
121
122
123
124
  
  #else /* #if CONFIG_HOTPLUG_CPU */
  static void cpu_hotplug_begin(void) {}
  static void cpu_hotplug_done(void) {}
25985edce   Lucas De Marchi   Fix common misspe...
125
  #endif	/* #else #if CONFIG_HOTPLUG_CPU */
79a6cdeb7   Lai Jiangshan   cpuhotplug: do no...
126

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  /* Need to know about CPUs going up/down? */
f7b16c108   Sam Ravnborg   cpu: fix section ...
128
  int __ref register_cpu_notifier(struct notifier_block *nb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
bd5349cfd   Neil Brown   [PATCH] Convert c...
130
  	int ret;
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
131
  	cpu_maps_update_begin();
bd5349cfd   Neil Brown   [PATCH] Convert c...
132
  	ret = raw_notifier_chain_register(&cpu_chain, nb);
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
133
  	cpu_maps_update_done();
bd5349cfd   Neil Brown   [PATCH] Convert c...
134
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  }
65edc68c3   Chandra Seetharaman   [PATCH] cpu hotpl...
136

e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
137
138
139
  static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
  			int *nr_calls)
  {
e6bde73b0   Akinobu Mita   cpu-hotplug: retu...
140
141
142
  	int ret;
  
  	ret = __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call,
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
143
  					nr_calls);
e6bde73b0   Akinobu Mita   cpu-hotplug: retu...
144
145
  
  	return notifier_to_errno(ret);
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
146
147
148
149
150
151
  }
  
  static int cpu_notify(unsigned long val, void *v)
  {
  	return __cpu_notify(val, v, -1, NULL);
  }
00b9b0af5   Linus Torvalds   Avoid warning whe...
152
  #ifdef CONFIG_HOTPLUG_CPU
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
153
154
  static void cpu_notify_nofail(unsigned long val, void *v)
  {
00b9b0af5   Linus Torvalds   Avoid warning whe...
155
  	BUG_ON(cpu_notify(val, v));
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
156
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  EXPORT_SYMBOL(register_cpu_notifier);
9647155ff   Sam Ravnborg   cpu: fix section ...
158
  void __ref unregister_cpu_notifier(struct notifier_block *nb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  {
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
160
  	cpu_maps_update_begin();
bd5349cfd   Neil Brown   [PATCH] Convert c...
161
  	raw_notifier_chain_unregister(&cpu_chain, nb);
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
162
  	cpu_maps_update_done();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  }
  EXPORT_SYMBOL(unregister_cpu_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
  static inline void check_for_tasks(int cpu)
  {
  	struct task_struct *p;
  
  	write_lock_irq(&tasklist_lock);
  	for_each_process(p) {
11854247e   Peter Zijlstra   sched: Fix incorr...
171
  		if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
648616343   Martin Schwidefsky   [S390] cputime: a...
172
  		    (p->utime || p->stime))
9d3cfc4c1   Frans Pop   sched: Correct pr...
173
174
175
176
177
  			printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d "
  				"(state = %ld, flags = %x)
  ",
  				p->comm, task_pid_nr(p), cpu,
  				p->state, p->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
  	}
  	write_unlock_irq(&tasklist_lock);
  }
db912f963   Avi Kivity   HOTPLUG: Add CPU_...
181
182
183
184
  struct take_cpu_down_param {
  	unsigned long mod;
  	void *hcpu;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  /* Take this CPU down. */
514a20a5d   Sam Ravnborg   cpu: fix section ...
186
  static int __ref take_cpu_down(void *_param)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  {
db912f963   Avi Kivity   HOTPLUG: Add CPU_...
188
  	struct take_cpu_down_param *param = _param;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
  	/* Ensure this CPU doesn't handle any more interrupts. */
  	err = __cpu_disable();
  	if (err < 0)
f37051364   Zwane Mwaikambo   [PATCH] i386 CPU ...
193
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
195
  	cpu_notify(CPU_DYING | param->mod, param->hcpu);
f37051364   Zwane Mwaikambo   [PATCH] i386 CPU ...
196
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  }
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
198
  /* Requires cpu_add_remove_lock to be held */
514a20a5d   Sam Ravnborg   cpu: fix section ...
199
  static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  {
e7407dcc6   Heiko Carstens   call cpu_chain wi...
201
  	int err, nr_calls = 0;
e7407dcc6   Heiko Carstens   call cpu_chain wi...
202
  	void *hcpu = (void *)(long)cpu;
8bb784428   Rafael J. Wysocki   Add suspend-relat...
203
  	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
db912f963   Avi Kivity   HOTPLUG: Add CPU_...
204
205
206
207
  	struct take_cpu_down_param tcd_param = {
  		.mod = mod,
  		.hcpu = hcpu,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
209
210
  	if (num_online_cpus() == 1)
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
212
213
  	if (!cpu_online(cpu))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
215
  	cpu_hotplug_begin();
4d51985e4   Michael Rodriguez   kernel/cpu.c: fix...
216

e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
217
  	err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
e6bde73b0   Akinobu Mita   cpu-hotplug: retu...
218
  	if (err) {
a0d8cdb65   Akinobu Mita   cpu hotplug: cpu:...
219
  		nr_calls--;
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
220
  		__cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  		printk("%s: attempt to take down CPU %u failed
  ",
af1f16d08   Harvey Harrison   kernel: replace r...
223
  				__func__, cpu);
baaca49f4   Gautham R Shenoy   Define and use ne...
224
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  	}
e0b582ec5   Rusty Russell   cpumask: convert ...
226
  	err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
043215875   Rusty Russell   Hotplug CPU: don'...
227
  	if (err) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		/* CPU didn't die: tell everyone.  Can't complain. */
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
229
  		cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230

6a1bdc1b5   Oleg Nesterov   sched: _cpu_down(...
231
  		goto out_release;
8fa1d7d3b   Satoru Takeuchi   [PATCH] cpu-hotpl...
232
  	}
043215875   Rusty Russell   Hotplug CPU: don'...
233
  	BUG_ON(cpu_online(cpu));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234

48c5ccae8   Peter Zijlstra   sched: Simplify c...
235
236
237
238
  	/*
  	 * The migration_call() CPU_DYING callback will have removed all
  	 * runnable tasks from the cpu, there's only the idle task left now
  	 * that the migration thread is done doing the stop_machine thing.
51a96c778   Peter Zijlstra   cpu: Remove incor...
239
240
  	 *
  	 * Wait for the stop thread to go away.
48c5ccae8   Peter Zijlstra   sched: Simplify c...
241
  	 */
51a96c778   Peter Zijlstra   cpu: Remove incor...
242
243
  	while (!idle_cpu(cpu))
  		cpu_relax();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
246
  
  	/* This actually kills the CPU. */
  	__cpu_die(cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	/* CPU is completely dead: tell everyone.  Too late to complain. */
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
248
  	cpu_notify_nofail(CPU_DEAD | mod, hcpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
  
  	check_for_tasks(cpu);
baaca49f4   Gautham R Shenoy   Define and use ne...
251
  out_release:
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
252
  	cpu_hotplug_done();
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
253
254
  	if (!err)
  		cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
255
256
  	return err;
  }
514a20a5d   Sam Ravnborg   cpu: fix section ...
257
  int __ref cpu_down(unsigned int cpu)
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
258
  {
9ea09af3b   Heiko Carstens   stop_machine: int...
259
  	int err;
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
260

d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
261
  	cpu_maps_update_begin();
e761b7725   Max Krasnyansky   cpu hotplug, sche...
262
263
  
  	if (cpu_hotplug_disabled) {
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
264
  		err = -EBUSY;
e761b7725   Max Krasnyansky   cpu hotplug, sche...
265
266
  		goto out;
  	}
e761b7725   Max Krasnyansky   cpu hotplug, sche...
267
  	err = _cpu_down(cpu, 0);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
268

e761b7725   Max Krasnyansky   cpu hotplug, sche...
269
  out:
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
270
  	cpu_maps_update_done();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
  	return err;
  }
b62b8ef90   Zhang Rui   force offline the...
273
  EXPORT_SYMBOL(cpu_down);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  #endif /*CONFIG_HOTPLUG_CPU*/
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
275
  /* Requires cpu_add_remove_lock to be held */
8bb784428   Rafael J. Wysocki   Add suspend-relat...
276
  static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
baaca49f4   Gautham R Shenoy   Define and use ne...
278
  	int ret, nr_calls = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  	void *hcpu = (void *)(long)cpu;
8bb784428   Rafael J. Wysocki   Add suspend-relat...
280
  	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
282
283
  	if (cpu_online(cpu) || !cpu_present(cpu))
  		return -EINVAL;
90d45d17f   Ashok Raj   [PATCH] cpu hotpl...
284

d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
285
  	cpu_hotplug_begin();
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
286
  	ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
e6bde73b0   Akinobu Mita   cpu-hotplug: retu...
287
  	if (ret) {
a0d8cdb65   Akinobu Mita   cpu hotplug: cpu:...
288
  		nr_calls--;
4d51985e4   Michael Rodriguez   kernel/cpu.c: fix...
289
290
  		printk(KERN_WARNING "%s: attempt to bring up CPU %u failed
  ",
af1f16d08   Harvey Harrison   kernel: replace r...
291
  				__func__, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
298
  		goto out_notify;
  	}
  
  	/* Arch-specific enabling code. */
  	ret = __cpu_up(cpu);
  	if (ret != 0)
  		goto out_notify;
6978c7052   Eric Sesterhenn   BUG_ON() Conversi...
299
  	BUG_ON(!cpu_online(cpu));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
  
  	/* Now call notifier in preparation. */
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
302
  	cpu_notify(CPU_ONLINE | mod, hcpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
  
  out_notify:
  	if (ret != 0)
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
306
  		__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
307
  	cpu_hotplug_done();
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
308
309
310
  
  	return ret;
  }
b282b6f8a   Gautham R Shenoy   [PATCH] Change cp...
311
  int __cpuinit cpu_up(unsigned int cpu)
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
312
313
  {
  	int err = 0;
cf23422b9   minskey guo   cpu/mem hotplug: ...
314
315
316
317
318
  
  #ifdef	CONFIG_MEMORY_HOTPLUG
  	int nid;
  	pg_data_t	*pgdat;
  #endif
e0b582ec5   Rusty Russell   cpumask: convert ...
319
  	if (!cpu_possible(cpu)) {
73e753a50   KAMEZAWA Hiroyuki   CPU HOTPLUG: avoi...
320
321
322
  		printk(KERN_ERR "can't online cpu %d because it is not "
  			"configured as may-hotadd at boot time
  ", cpu);
87d5e0236   Chen Gong   kernel/cpu.c: del...
323
  #if defined(CONFIG_IA64)
73e753a50   KAMEZAWA Hiroyuki   CPU HOTPLUG: avoi...
324
325
326
327
328
329
  		printk(KERN_ERR "please check additional_cpus= boot "
  				"parameter
  ");
  #endif
  		return -EINVAL;
  	}
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
330

cf23422b9   minskey guo   cpu/mem hotplug: ...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  #ifdef	CONFIG_MEMORY_HOTPLUG
  	nid = cpu_to_node(cpu);
  	if (!node_online(nid)) {
  		err = mem_online_node(nid);
  		if (err)
  			return err;
  	}
  
  	pgdat = NODE_DATA(nid);
  	if (!pgdat) {
  		printk(KERN_ERR
  			"Can't online cpu %d due to NULL pgdat
  ", cpu);
  		return -ENOMEM;
  	}
4eaf3f643   Haicheng Li   mem-hotplug: fix ...
346
347
  	if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
  		mutex_lock(&zonelists_mutex);
1f522509c   Haicheng Li   mem-hotplug: avoi...
348
  		build_all_zonelists(NULL);
4eaf3f643   Haicheng Li   mem-hotplug: fix ...
349
350
  		mutex_unlock(&zonelists_mutex);
  	}
cf23422b9   minskey guo   cpu/mem hotplug: ...
351
  #endif
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
352
  	cpu_maps_update_begin();
e761b7725   Max Krasnyansky   cpu hotplug, sche...
353
354
  
  	if (cpu_hotplug_disabled) {
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
355
  		err = -EBUSY;
e761b7725   Max Krasnyansky   cpu hotplug, sche...
356
357
358
359
  		goto out;
  	}
  
  	err = _cpu_up(cpu, 0);
e761b7725   Max Krasnyansky   cpu hotplug, sche...
360
  out:
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
361
  	cpu_maps_update_done();
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
362
363
  	return err;
  }
a513f6bab   Paul E. McKenney   cpu: Export cpu_up()
364
  EXPORT_SYMBOL_GPL(cpu_up);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
365

f3de4be9d   Rafael J. Wysocki   PM: Fix dependenc...
366
  #ifdef CONFIG_PM_SLEEP_SMP
e0b582ec5   Rusty Russell   cpumask: convert ...
367
  static cpumask_var_t frozen_cpus;
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
368

3fb82d56a   Suresh Siddha   x86, suspend: Avo...
369
370
371
372
373
374
375
  void __weak arch_disable_nonboot_cpus_begin(void)
  {
  }
  
  void __weak arch_disable_nonboot_cpus_end(void)
  {
  }
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
376
377
  int disable_nonboot_cpus(void)
  {
e9a5f426b   Rafael J. Wysocki   CPU: Avoid using ...
378
  	int cpu, first_cpu, error = 0;
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
379

d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
380
  	cpu_maps_update_begin();
e0b582ec5   Rusty Russell   cpumask: convert ...
381
  	first_cpu = cpumask_first(cpu_online_mask);
9ee349ad6   Xiaotian Feng   sched: Fix set_cp...
382
383
  	/*
  	 * We take down all of the non-boot CPUs in one shot to avoid races
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
384
385
  	 * with the userspace trying to use the CPU hotplug at the same time
  	 */
e0b582ec5   Rusty Russell   cpumask: convert ...
386
  	cpumask_clear(frozen_cpus);
3fb82d56a   Suresh Siddha   x86, suspend: Avo...
387
  	arch_disable_nonboot_cpus_begin();
6ad4c1888   Peter Zijlstra   sched: Fix balanc...
388

e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
389
390
391
392
393
  	printk("Disabling non-boot CPUs ...
  ");
  	for_each_online_cpu(cpu) {
  		if (cpu == first_cpu)
  			continue;
8bb784428   Rafael J. Wysocki   Add suspend-relat...
394
  		error = _cpu_down(cpu, 1);
feae3203d   Mike Travis   timers, init: Lim...
395
  		if (!error)
e0b582ec5   Rusty Russell   cpumask: convert ...
396
  			cpumask_set_cpu(cpu, frozen_cpus);
feae3203d   Mike Travis   timers, init: Lim...
397
  		else {
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
398
399
400
401
402
403
  			printk(KERN_ERR "Error taking CPU%d down: %d
  ",
  				cpu, error);
  			break;
  		}
  	}
86886e55b   Joseph Cihula   x86, intel_txt: I...
404

3fb82d56a   Suresh Siddha   x86, suspend: Avo...
405
  	arch_disable_nonboot_cpus_end();
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
406
407
408
409
410
  	if (!error) {
  		BUG_ON(num_online_cpus() > 1);
  		/* Make sure the CPUs won't be enabled by someone else */
  		cpu_hotplug_disabled = 1;
  	} else {
e1d9fd2e3   Ingo Molnar   [PATCH] suspend: ...
411
412
  		printk(KERN_ERR "Non-boot CPUs are not disabled
  ");
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
413
  	}
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
414
  	cpu_maps_update_done();
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
415
416
  	return error;
  }
d0af9eed5   Suresh Siddha   x86, pat/mtrr: Re...
417
418
419
420
421
422
423
  void __weak arch_enable_nonboot_cpus_begin(void)
  {
  }
  
  void __weak arch_enable_nonboot_cpus_end(void)
  {
  }
fa7303e22   Sam Ravnborg   cpu: fix section ...
424
  void __ref enable_nonboot_cpus(void)
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
425
426
427
428
  {
  	int cpu, error;
  
  	/* Allow everyone to use the CPU hotplug again */
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
429
  	cpu_maps_update_begin();
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
430
  	cpu_hotplug_disabled = 0;
e0b582ec5   Rusty Russell   cpumask: convert ...
431
  	if (cpumask_empty(frozen_cpus))
1d64b9cb1   Rafael J. Wysocki   [PATCH] Fix micro...
432
  		goto out;
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
433

4d51985e4   Michael Rodriguez   kernel/cpu.c: fix...
434
435
  	printk(KERN_INFO "Enabling non-boot CPUs ...
  ");
d0af9eed5   Suresh Siddha   x86, pat/mtrr: Re...
436
437
  
  	arch_enable_nonboot_cpus_begin();
e0b582ec5   Rusty Russell   cpumask: convert ...
438
  	for_each_cpu(cpu, frozen_cpus) {
8bb784428   Rafael J. Wysocki   Add suspend-relat...
439
  		error = _cpu_up(cpu, 1);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
440
  		if (!error) {
4d51985e4   Michael Rodriguez   kernel/cpu.c: fix...
441
442
  			printk(KERN_INFO "CPU%d is up
  ", cpu);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
443
444
  			continue;
  		}
1d64b9cb1   Rafael J. Wysocki   [PATCH] Fix micro...
445
446
  		printk(KERN_WARNING "Error taking CPU%d up: %d
  ", cpu, error);
e3920fb42   Rafael J. Wysocki   [PATCH] Disable C...
447
  	}
d0af9eed5   Suresh Siddha   x86, pat/mtrr: Re...
448
449
  
  	arch_enable_nonboot_cpus_end();
e0b582ec5   Rusty Russell   cpumask: convert ...
450
  	cpumask_clear(frozen_cpus);
1d64b9cb1   Rafael J. Wysocki   [PATCH] Fix micro...
451
  out:
d221938c0   Gautham R Shenoy   cpu-hotplug: refc...
452
  	cpu_maps_update_done();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  }
e0b582ec5   Rusty Russell   cpumask: convert ...
454

d7268a31c   Fenghua Yu   CPU: Add right qu...
455
  static int __init alloc_frozen_cpus(void)
e0b582ec5   Rusty Russell   cpumask: convert ...
456
457
458
459
460
461
  {
  	if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
  		return -ENOMEM;
  	return 0;
  }
  core_initcall(alloc_frozen_cpus);
79cfbdfa8   Srivatsa S. Bhat   PM / Sleep: Fix r...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  
  /*
   * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
   * hotplug when tasks are about to be frozen. Also, don't allow the freezer
   * to continue until any currently running CPU hotplug operation gets
   * completed.
   * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
   * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
   * CPU hotplug path and released only after it is complete. Thus, we
   * (and hence the freezer) will block here until any currently running CPU
   * hotplug operation gets completed.
   */
  void cpu_hotplug_disable_before_freeze(void)
  {
  	cpu_maps_update_begin();
  	cpu_hotplug_disabled = 1;
  	cpu_maps_update_done();
  }
  
  
  /*
   * When tasks have been thawed, re-enable regular CPU hotplug (which had been
   * disabled while beginning to freeze tasks).
   */
  void cpu_hotplug_enable_after_thaw(void)
  {
  	cpu_maps_update_begin();
  	cpu_hotplug_disabled = 0;
  	cpu_maps_update_done();
  }
  
  /*
   * When callbacks for CPU hotplug notifications are being executed, we must
   * ensure that the state of the system with respect to the tasks being frozen
   * or not, as reported by the notification, remains unchanged *throughout the
   * duration* of the execution of the callbacks.
   * Hence we need to prevent the freezer from racing with regular CPU hotplug.
   *
   * This synchronization is implemented by mutually excluding regular CPU
   * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/
   * Hibernate notifications.
   */
  static int
  cpu_hotplug_pm_callback(struct notifier_block *nb,
  			unsigned long action, void *ptr)
  {
  	switch (action) {
  
  	case PM_SUSPEND_PREPARE:
  	case PM_HIBERNATION_PREPARE:
  		cpu_hotplug_disable_before_freeze();
  		break;
  
  	case PM_POST_SUSPEND:
  	case PM_POST_HIBERNATION:
  		cpu_hotplug_enable_after_thaw();
  		break;
  
  	default:
  		return NOTIFY_DONE;
  	}
  
  	return NOTIFY_OK;
  }
d7268a31c   Fenghua Yu   CPU: Add right qu...
526
  static int __init cpu_hotplug_pm_sync_init(void)
79cfbdfa8   Srivatsa S. Bhat   PM / Sleep: Fix r...
527
528
529
530
531
  {
  	pm_notifier(cpu_hotplug_pm_callback, 0);
  	return 0;
  }
  core_initcall(cpu_hotplug_pm_sync_init);
f3de4be9d   Rafael J. Wysocki   PM: Fix dependenc...
532
  #endif /* CONFIG_PM_SLEEP_SMP */
68f4f1ec0   Max Krasnyansky   sched: Move cpu m...
533

e545a6140   Manfred Spraul   kernel/cpu.c: cre...
534
535
536
537
538
539
540
541
  /**
   * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
   * @cpu: cpu that just started
   *
   * This function calls the cpu_chain notifiers with CPU_STARTING.
   * It must be called by the arch code on the new cpu, before the new cpu
   * enables interrupts and before the "boot" cpu returns from __cpu_up().
   */
841964145   Al Viro   cpuinit fixes in ...
542
  void __cpuinit notify_cpu_starting(unsigned int cpu)
e545a6140   Manfred Spraul   kernel/cpu.c: cre...
543
544
545
546
  {
  	unsigned long val = CPU_STARTING;
  
  #ifdef CONFIG_PM_SLEEP_SMP
e0b582ec5   Rusty Russell   cpumask: convert ...
547
  	if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
e545a6140   Manfred Spraul   kernel/cpu.c: cre...
548
549
  		val = CPU_STARTING_FROZEN;
  #endif /* CONFIG_PM_SLEEP_SMP */
e9fb7631e   Akinobu Mita   cpu-hotplug: intr...
550
  	cpu_notify(val, (void *)(long)cpu);
e545a6140   Manfred Spraul   kernel/cpu.c: cre...
551
  }
68f4f1ec0   Max Krasnyansky   sched: Move cpu m...
552
  #endif /* CONFIG_SMP */
b8d317d10   Mike Travis   cpumask: make cpu...
553

e56b3bc79   Linus Torvalds   cpu masks: optimi...
554
555
556
557
  /*
   * cpu_bit_bitmap[] is a special, "compressed" data structure that
   * represents all NR_CPUS bits binary values of 1<<nr.
   *
e0b582ec5   Rusty Russell   cpumask: convert ...
558
   * It is used by cpumask_of() to get a constant address to a CPU
e56b3bc79   Linus Torvalds   cpu masks: optimi...
559
560
   * mask value that has a single bit set only.
   */
b8d317d10   Mike Travis   cpumask: make cpu...
561

e56b3bc79   Linus Torvalds   cpu masks: optimi...
562
  /* cpu_bit_bitmap[0] is empty - so we can back into it */
4d51985e4   Michael Rodriguez   kernel/cpu.c: fix...
563
  #define MASK_DECLARE_1(x)	[x+1][0] = (1UL << (x))
e56b3bc79   Linus Torvalds   cpu masks: optimi...
564
565
566
  #define MASK_DECLARE_2(x)	MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
  #define MASK_DECLARE_4(x)	MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
  #define MASK_DECLARE_8(x)	MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
b8d317d10   Mike Travis   cpumask: make cpu...
567

e56b3bc79   Linus Torvalds   cpu masks: optimi...
568
569
570
571
572
573
574
  const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
  
  	MASK_DECLARE_8(0),	MASK_DECLARE_8(8),
  	MASK_DECLARE_8(16),	MASK_DECLARE_8(24),
  #if BITS_PER_LONG > 32
  	MASK_DECLARE_8(32),	MASK_DECLARE_8(40),
  	MASK_DECLARE_8(48),	MASK_DECLARE_8(56),
b8d317d10   Mike Travis   cpumask: make cpu...
575
576
  #endif
  };
e56b3bc79   Linus Torvalds   cpu masks: optimi...
577
  EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
2d3854a37   Rusty Russell   cpumask: introduc...
578
579
580
  
  const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
  EXPORT_SYMBOL(cpu_all_bits);
b3199c025   Rusty Russell   cpumask: switch o...
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  
  #ifdef CONFIG_INIT_ALL_POSSIBLE
  static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
  	= CPU_BITS_ALL;
  #else
  static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
  #endif
  const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
  EXPORT_SYMBOL(cpu_possible_mask);
  
  static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
  const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
  EXPORT_SYMBOL(cpu_online_mask);
  
  static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;
  const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
  EXPORT_SYMBOL(cpu_present_mask);
  
  static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;
  const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);
  EXPORT_SYMBOL(cpu_active_mask);
3fa415206   Rusty Russell   cpumask: make set...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  
  void set_cpu_possible(unsigned int cpu, bool possible)
  {
  	if (possible)
  		cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
  	else
  		cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
  }
  
  void set_cpu_present(unsigned int cpu, bool present)
  {
  	if (present)
  		cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
  	else
  		cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
  }
  
  void set_cpu_online(unsigned int cpu, bool online)
  {
  	if (online)
  		cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
  	else
  		cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
  }
  
  void set_cpu_active(unsigned int cpu, bool active)
  {
  	if (active)
  		cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
  	else
  		cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));
  }
  
  void init_cpu_present(const struct cpumask *src)
  {
  	cpumask_copy(to_cpumask(cpu_present_bits), src);
  }
  
  void init_cpu_possible(const struct cpumask *src)
  {
  	cpumask_copy(to_cpumask(cpu_possible_bits), src);
  }
  
  void init_cpu_online(const struct cpumask *src)
  {
  	cpumask_copy(to_cpumask(cpu_online_bits), src);
  }