Blame view

kernel/reboot.c 14.3 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
15d94b825   Robin Holt   reboot: move shut...
2
3
4
5
6
  /*
   *  linux/kernel/reboot.c
   *
   *  Copyright (C) 2013  Linus Torvalds
   */
972ee83df   Robin Holt   reboot: checkpatc...
7
  #define pr_fmt(fmt)	"reboot: " fmt
1b3a5d02e   Robin Holt   reboot: move arch...
8
  #include <linux/ctype.h>
15d94b825   Robin Holt   reboot: move shut...
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  #include <linux/export.h>
  #include <linux/kexec.h>
  #include <linux/kmod.h>
  #include <linux/kmsg_dump.h>
  #include <linux/reboot.h>
  #include <linux/suspend.h>
  #include <linux/syscalls.h>
  #include <linux/syscore_ops.h>
  #include <linux/uaccess.h>
  
  /*
   * this indicates whether you can reboot with ctrl-alt-del: the default is yes
   */
  
  int C_A_D = 1;
  struct pid *cad_pid;
  EXPORT_SYMBOL(cad_pid);
fb37409a0   Mike Rapoport   arch: remove unic...
26
  #if defined(CONFIG_ARM)
1b3a5d02e   Robin Holt   reboot: move arch...
27
28
29
30
31
  #define DEFAULT_REBOOT_MODE		= REBOOT_HARD
  #else
  #define DEFAULT_REBOOT_MODE
  #endif
  enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
14e014655   Elliot Berman   FROMLIST: reboot:...
32
  EXPORT_SYMBOL_GPL(reboot_mode);
b287a25a7   Aaro Koskinen   panic/reboot: all...
33
  enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED;
14e014655   Elliot Berman   FROMLIST: reboot:...
34
  EXPORT_SYMBOL_GPL(panic_reboot_mode);
1b3a5d02e   Robin Holt   reboot: move arch...
35

e2f0b88e8   Chuansheng Liu   kernel/reboot.c: ...
36
37
38
39
40
41
42
43
  /*
   * This variable is used privately to keep track of whether or not
   * reboot_type is still set to its default value (i.e., reboot= hasn't
   * been set on the command line).  This is needed so that we can
   * suppress DMI scanning for reboot quirks.  Without it, it's
   * impossible to override a faulty reboot quirk without recompiling.
   */
  int reboot_default = 1;
1b3a5d02e   Robin Holt   reboot: move arch...
44
45
46
  int reboot_cpu;
  enum reboot_type reboot_type = BOOT_ACPI;
  int reboot_force;
15d94b825   Robin Holt   reboot: move shut...
47
48
49
50
51
  /*
   * If set, this is used for preparing the system to power off.
   */
  
  void (*pm_power_off_prepare)(void);
74f008f25   Oleksij Rempel   kernel/reboot.c: ...
52
  EXPORT_SYMBOL_GPL(pm_power_off_prepare);
15d94b825   Robin Holt   reboot: move shut...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  /**
   *	emergency_restart - reboot the system
   *
   *	Without shutting down any hardware or taking any locks
   *	reboot the system.  This is called when we know we are in
   *	trouble so this is our best effort to reboot.  This is
   *	safe to call in interrupt context.
   */
  void emergency_restart(void)
  {
  	kmsg_dump(KMSG_DUMP_EMERG);
  	machine_emergency_restart();
  }
  EXPORT_SYMBOL_GPL(emergency_restart);
  
  void kernel_restart_prepare(char *cmd)
  {
  	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
  	system_state = SYSTEM_RESTART;
  	usermodehelper_disable();
  	device_shutdown();
  }
  
  /**
   *	register_reboot_notifier - Register function to be called at reboot time
   *	@nb: Info about notifier function to be called
   *
   *	Registers a function with the list of functions
   *	to be called at reboot time.
   *
   *	Currently always returns zero, as blocking_notifier_chain_register()
   *	always returns zero.
   */
  int register_reboot_notifier(struct notifier_block *nb)
  {
  	return blocking_notifier_chain_register(&reboot_notifier_list, nb);
  }
  EXPORT_SYMBOL(register_reboot_notifier);
  
  /**
   *	unregister_reboot_notifier - Unregister previously registered reboot notifier
   *	@nb: Hook to be unregistered
   *
   *	Unregisters a previously registered reboot
   *	notifier function.
   *
   *	Returns zero on success, or %-ENOENT on failure.
   */
  int unregister_reboot_notifier(struct notifier_block *nb)
  {
  	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
  }
  EXPORT_SYMBOL(unregister_reboot_notifier);
2d8364bae   Andrey Smirnov   kernel/reboot.c: ...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  static void devm_unregister_reboot_notifier(struct device *dev, void *res)
  {
  	WARN_ON(unregister_reboot_notifier(*(struct notifier_block **)res));
  }
  
  int devm_register_reboot_notifier(struct device *dev, struct notifier_block *nb)
  {
  	struct notifier_block **rcnb;
  	int ret;
  
  	rcnb = devres_alloc(devm_unregister_reboot_notifier,
  			    sizeof(*rcnb), GFP_KERNEL);
  	if (!rcnb)
  		return -ENOMEM;
  
  	ret = register_reboot_notifier(nb);
  	if (!ret) {
  		*rcnb = nb;
  		devres_add(dev, rcnb);
  	} else {
  		devres_free(rcnb);
  	}
  
  	return ret;
  }
  EXPORT_SYMBOL(devm_register_reboot_notifier);
b63adb979   Guenter Roeck   kernel: add suppo...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  /*
   *	Notifier list for kernel code which wants to be called
   *	to restart the system.
   */
  static ATOMIC_NOTIFIER_HEAD(restart_handler_list);
  
  /**
   *	register_restart_handler - Register function to be called to reset
   *				   the system
   *	@nb: Info about handler function to be called
   *	@nb->priority:	Handler priority. Handlers should follow the
   *			following guidelines for setting priorities.
   *			0:	Restart handler of last resort,
   *				with limited restart capabilities
   *			128:	Default restart handler; use if no other
   *				restart handler is expected to be available,
   *				and/or if restart functionality is
   *				sufficient to restart the entire system
   *			255:	Highest priority restart handler, will
   *				preempt all other restart handlers
   *
   *	Registers a function with code to be called to restart the
   *	system.
   *
   *	Registered functions will be called from machine_restart as last
   *	step of the restart sequence (if the architecture specific
   *	machine_restart function calls do_kernel_restart - see below
   *	for details).
   *	Registered functions are expected to restart the system immediately.
   *	If more than one function is registered, the restart handler priority
   *	selects which function will be called first.
   *
   *	Restart handlers are expected to be registered from non-architecture
   *	code, typically from drivers. A typical use case would be a system
   *	where restart functionality is provided through a watchdog. Multiple
   *	restart handlers may exist; for example, one restart handler might
   *	restart the entire system, while another only restarts the CPU.
   *	In such cases, the restart handler which only restarts part of the
   *	hardware is expected to register with low priority to ensure that
   *	it only runs if no other means to restart the system is available.
   *
   *	Currently always returns zero, as atomic_notifier_chain_register()
   *	always returns zero.
   */
  int register_restart_handler(struct notifier_block *nb)
  {
  	return atomic_notifier_chain_register(&restart_handler_list, nb);
  }
  EXPORT_SYMBOL(register_restart_handler);
  
  /**
   *	unregister_restart_handler - Unregister previously registered
   *				     restart handler
   *	@nb: Hook to be unregistered
   *
   *	Unregisters a previously registered restart handler function.
   *
   *	Returns zero on success, or %-ENOENT on failure.
   */
  int unregister_restart_handler(struct notifier_block *nb)
  {
  	return atomic_notifier_chain_unregister(&restart_handler_list, nb);
  }
  EXPORT_SYMBOL(unregister_restart_handler);
  
  /**
   *	do_kernel_restart - Execute kernel restart handler call chain
   *
   *	Calls functions registered with register_restart_handler.
   *
   *	Expected to be called from machine_restart as last step of the restart
   *	sequence.
   *
   *	Restarts the system immediately if a restart handler function has been
   *	registered. Otherwise does nothing.
   */
  void do_kernel_restart(char *cmd)
  {
  	atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);
  }
c97102ba9   Vivek Goyal   kexec: migrate to...
213
  void migrate_to_reboot_cpu(void)
15d94b825   Robin Holt   reboot: move shut...
214
215
  {
  	/* The boot cpu is always logical cpu 0 */
1b3a5d02e   Robin Holt   reboot: move arch...
216
  	int cpu = reboot_cpu;
15d94b825   Robin Holt   reboot: move shut...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  
  	cpu_hotplug_disable();
  
  	/* Make certain the cpu I'm about to reboot on is online */
  	if (!cpu_online(cpu))
  		cpu = cpumask_first(cpu_online_mask);
  
  	/* Prevent races with other tasks migrating this task */
  	current->flags |= PF_NO_SETAFFINITY;
  
  	/* Make certain I only run on the appropriate processor */
  	set_cpus_allowed_ptr(current, cpumask_of(cpu));
  }
  
  /**
   *	kernel_restart - reboot the system
   *	@cmd: pointer to buffer containing command to execute for restart
   *		or %NULL
   *
   *	Shutdown everything and perform a clean reboot.
   *	This is not safe to call in interrupt context.
   */
  void kernel_restart(char *cmd)
  {
  	kernel_restart_prepare(cmd);
  	migrate_to_reboot_cpu();
  	syscore_shutdown();
  	if (!cmd)
972ee83df   Robin Holt   reboot: checkpatc...
245
246
  		pr_emerg("Restarting system
  ");
15d94b825   Robin Holt   reboot: move shut...
247
  	else
972ee83df   Robin Holt   reboot: checkpatc...
248
249
  		pr_emerg("Restarting system with command '%s'
  ", cmd);
6d3cf962d   Kees Cook   printk: Collapse ...
250
  	kmsg_dump(KMSG_DUMP_SHUTDOWN);
15d94b825   Robin Holt   reboot: move shut...
251
252
253
254
255
256
257
  	machine_restart(cmd);
  }
  EXPORT_SYMBOL_GPL(kernel_restart);
  
  static void kernel_shutdown_prepare(enum system_states state)
  {
  	blocking_notifier_call_chain(&reboot_notifier_list,
972ee83df   Robin Holt   reboot: checkpatc...
258
  		(state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
15d94b825   Robin Holt   reboot: move shut...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  	system_state = state;
  	usermodehelper_disable();
  	device_shutdown();
  }
  /**
   *	kernel_halt - halt the system
   *
   *	Shutdown everything and perform a clean system halt.
   */
  void kernel_halt(void)
  {
  	kernel_shutdown_prepare(SYSTEM_HALT);
  	migrate_to_reboot_cpu();
  	syscore_shutdown();
972ee83df   Robin Holt   reboot: checkpatc...
273
274
  	pr_emerg("System halted
  ");
6d3cf962d   Kees Cook   printk: Collapse ...
275
  	kmsg_dump(KMSG_DUMP_SHUTDOWN);
15d94b825   Robin Holt   reboot: move shut...
276
277
  	machine_halt();
  }
15d94b825   Robin Holt   reboot: move shut...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  EXPORT_SYMBOL_GPL(kernel_halt);
  
  /**
   *	kernel_power_off - power_off the system
   *
   *	Shutdown everything and perform a clean system power_off.
   */
  void kernel_power_off(void)
  {
  	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
  	if (pm_power_off_prepare)
  		pm_power_off_prepare();
  	migrate_to_reboot_cpu();
  	syscore_shutdown();
972ee83df   Robin Holt   reboot: checkpatc...
292
293
  	pr_emerg("Power down
  ");
6d3cf962d   Kees Cook   printk: Collapse ...
294
  	kmsg_dump(KMSG_DUMP_SHUTDOWN);
15d94b825   Robin Holt   reboot: move shut...
295
296
297
  	machine_power_off();
  }
  EXPORT_SYMBOL_GPL(kernel_power_off);
55f2503c3   Pingfan Liu   PM / reboot: Elim...
298
  DEFINE_MUTEX(system_transition_mutex);
15d94b825   Robin Holt   reboot: move shut...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  
  /*
   * Reboot system call: for obvious reasons only root may call it,
   * and even root needs to set up some magic numbers in the registers
   * so that some mistake won't make this reboot the whole machine.
   * You can also set the meaning of the ctrl-alt-del-key here.
   *
   * reboot doesn't sync: do that yourself before calling this.
   */
  SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
  		void __user *, arg)
  {
  	struct pid_namespace *pid_ns = task_active_pid_ns(current);
  	char buffer[256];
  	int ret = 0;
  
  	/* We only trust the superuser with rebooting the system. */
  	if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
  		return -EPERM;
  
  	/* For safety, we require "magic" arguments. */
  	if (magic1 != LINUX_REBOOT_MAGIC1 ||
972ee83df   Robin Holt   reboot: checkpatc...
321
322
  			(magic2 != LINUX_REBOOT_MAGIC2 &&
  			magic2 != LINUX_REBOOT_MAGIC2A &&
15d94b825   Robin Holt   reboot: move shut...
323
  			magic2 != LINUX_REBOOT_MAGIC2B &&
972ee83df   Robin Holt   reboot: checkpatc...
324
  			magic2 != LINUX_REBOOT_MAGIC2C))
15d94b825   Robin Holt   reboot: move shut...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  		return -EINVAL;
  
  	/*
  	 * If pid namespaces are enabled and the current task is in a child
  	 * pid_namespace, the command is handled by reboot_pid_ns() which will
  	 * call do_exit().
  	 */
  	ret = reboot_pid_ns(pid_ns, cmd);
  	if (ret)
  		return ret;
  
  	/* Instead of trying to make the power_off code look like
  	 * halt when pm_power_off is not set do it the easy way.
  	 */
  	if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
  		cmd = LINUX_REBOOT_CMD_HALT;
55f2503c3   Pingfan Liu   PM / reboot: Elim...
341
  	mutex_lock(&system_transition_mutex);
15d94b825   Robin Holt   reboot: move shut...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  	switch (cmd) {
  	case LINUX_REBOOT_CMD_RESTART:
  		kernel_restart(NULL);
  		break;
  
  	case LINUX_REBOOT_CMD_CAD_ON:
  		C_A_D = 1;
  		break;
  
  	case LINUX_REBOOT_CMD_CAD_OFF:
  		C_A_D = 0;
  		break;
  
  	case LINUX_REBOOT_CMD_HALT:
  		kernel_halt();
  		do_exit(0);
  		panic("cannot halt");
  
  	case LINUX_REBOOT_CMD_POWER_OFF:
  		kernel_power_off();
  		do_exit(0);
  		break;
  
  	case LINUX_REBOOT_CMD_RESTART2:
972ee83df   Robin Holt   reboot: checkpatc...
366
367
  		ret = strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1);
  		if (ret < 0) {
15d94b825   Robin Holt   reboot: move shut...
368
369
370
371
372
373
374
  			ret = -EFAULT;
  			break;
  		}
  		buffer[sizeof(buffer) - 1] = '\0';
  
  		kernel_restart(buffer);
  		break;
2965faa5e   Dave Young   kexec: split kexe...
375
  #ifdef CONFIG_KEXEC_CORE
15d94b825   Robin Holt   reboot: move shut...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  	case LINUX_REBOOT_CMD_KEXEC:
  		ret = kernel_kexec();
  		break;
  #endif
  
  #ifdef CONFIG_HIBERNATION
  	case LINUX_REBOOT_CMD_SW_SUSPEND:
  		ret = hibernate();
  		break;
  #endif
  
  	default:
  		ret = -EINVAL;
  		break;
  	}
55f2503c3   Pingfan Liu   PM / reboot: Elim...
391
  	mutex_unlock(&system_transition_mutex);
15d94b825   Robin Holt   reboot: move shut...
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  	return ret;
  }
  
  static void deferred_cad(struct work_struct *dummy)
  {
  	kernel_restart(NULL);
  }
  
  /*
   * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
   * As it's called within an interrupt, it may NOT sync: the only choice
   * is whether to reboot at once, or just ignore the ctrl-alt-del.
   */
  void ctrl_alt_del(void)
  {
  	static DECLARE_WORK(cad_work, deferred_cad);
  
  	if (C_A_D)
  		schedule_work(&cad_work);
  	else
  		kill_cad_pid(SIGINT, 1);
  }
  
  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
7a54f46b3   Joel Stanley   kernel/reboot.c: ...
416
  static const char reboot_cmd[] = "/sbin/reboot";
15d94b825   Robin Holt   reboot: move shut...
417

7a54f46b3   Joel Stanley   kernel/reboot.c: ...
418
  static int run_cmd(const char *cmd)
15d94b825   Robin Holt   reboot: move shut...
419
420
421
422
423
424
425
426
  {
  	char **argv;
  	static char *envp[] = {
  		"HOME=/",
  		"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
  		NULL
  	};
  	int ret;
7a54f46b3   Joel Stanley   kernel/reboot.c: ...
427
  	argv = argv_split(GFP_KERNEL, cmd, NULL);
15d94b825   Robin Holt   reboot: move shut...
428
429
430
431
  	if (argv) {
  		ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
  		argv_free(argv);
  	} else {
15d94b825   Robin Holt   reboot: move shut...
432
433
  		ret = -ENOMEM;
  	}
7a54f46b3   Joel Stanley   kernel/reboot.c: ...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  	return ret;
  }
  
  static int __orderly_reboot(void)
  {
  	int ret;
  
  	ret = run_cmd(reboot_cmd);
  
  	if (ret) {
  		pr_warn("Failed to start orderly reboot: forcing the issue
  ");
  		emergency_sync();
  		kernel_restart(NULL);
  	}
  
  	return ret;
  }
  
  static int __orderly_poweroff(bool force)
  {
  	int ret;
  
  	ret = run_cmd(poweroff_cmd);
15d94b825   Robin Holt   reboot: move shut...
458
  	if (ret && force) {
972ee83df   Robin Holt   reboot: checkpatc...
459
460
  		pr_warn("Failed to start orderly shutdown: forcing the issue
  ");
7a54f46b3   Joel Stanley   kernel/reboot.c: ...
461

15d94b825   Robin Holt   reboot: move shut...
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
  		/*
  		 * I guess this should try to kick off some daemon to sync and
  		 * poweroff asap.  Or not even bother syncing if we're doing an
  		 * emergency shutdown?
  		 */
  		emergency_sync();
  		kernel_power_off();
  	}
  
  	return ret;
  }
  
  static bool poweroff_force;
  
  static void poweroff_work_func(struct work_struct *work)
  {
  	__orderly_poweroff(poweroff_force);
  }
  
  static DECLARE_WORK(poweroff_work, poweroff_work_func);
  
  /**
   * orderly_poweroff - Trigger an orderly system poweroff
   * @force: force poweroff if command execution fails
   *
   * This may be called from any context to trigger a system shutdown.
   * If the orderly shutdown fails, it will force an immediate shutdown.
   */
7a54f46b3   Joel Stanley   kernel/reboot.c: ...
490
  void orderly_poweroff(bool force)
15d94b825   Robin Holt   reboot: move shut...
491
492
493
494
  {
  	if (force) /* do not override the pending "true" */
  		poweroff_force = true;
  	schedule_work(&poweroff_work);
15d94b825   Robin Holt   reboot: move shut...
495
496
  }
  EXPORT_SYMBOL_GPL(orderly_poweroff);
1b3a5d02e   Robin Holt   reboot: move arch...
497

7a54f46b3   Joel Stanley   kernel/reboot.c: ...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  static void reboot_work_func(struct work_struct *work)
  {
  	__orderly_reboot();
  }
  
  static DECLARE_WORK(reboot_work, reboot_work_func);
  
  /**
   * orderly_reboot - Trigger an orderly system reboot
   *
   * This may be called from any context to trigger a system reboot.
   * If the orderly reboot fails, it will force an immediate reboot.
   */
  void orderly_reboot(void)
  {
  	schedule_work(&reboot_work);
  }
  EXPORT_SYMBOL_GPL(orderly_reboot);
1b3a5d02e   Robin Holt   reboot: move arch...
516
517
518
  static int __init reboot_setup(char *str)
  {
  	for (;;) {
b287a25a7   Aaro Koskinen   panic/reboot: all...
519
  		enum reboot_mode *mode;
1b3a5d02e   Robin Holt   reboot: move arch...
520
521
522
523
524
525
  		/*
  		 * Having anything passed on the command line via
  		 * reboot= will cause us to disable DMI checking
  		 * below.
  		 */
  		reboot_default = 0;
b287a25a7   Aaro Koskinen   panic/reboot: all...
526
527
528
529
530
531
  		if (!strncmp(str, "panic_", 6)) {
  			mode = &panic_reboot_mode;
  			str += 6;
  		} else {
  			mode = &reboot_mode;
  		}
1b3a5d02e   Robin Holt   reboot: move arch...
532
533
  		switch (*str) {
  		case 'w':
b287a25a7   Aaro Koskinen   panic/reboot: all...
534
  			*mode = REBOOT_WARM;
1b3a5d02e   Robin Holt   reboot: move arch...
535
536
537
  			break;
  
  		case 'c':
b287a25a7   Aaro Koskinen   panic/reboot: all...
538
  			*mode = REBOOT_COLD;
1b3a5d02e   Robin Holt   reboot: move arch...
539
540
541
  			break;
  
  		case 'h':
b287a25a7   Aaro Koskinen   panic/reboot: all...
542
  			*mode = REBOOT_HARD;
1b3a5d02e   Robin Holt   reboot: move arch...
543
544
545
  			break;
  
  		case 's':
8b92c4ff4   Matteo Croce   Revert "kernel/re...
546
547
548
549
550
551
  			if (isdigit(*(str+1)))
  				reboot_cpu = simple_strtoul(str+1, NULL, 0);
  			else if (str[1] == 'm' && str[2] == 'p' &&
  							isdigit(*(str+3)))
  				reboot_cpu = simple_strtoul(str+3, NULL, 0);
  			else
b287a25a7   Aaro Koskinen   panic/reboot: all...
552
  				*mode = REBOOT_SOFT;
df5b0ab3e   Matteo Croce   reboot: fix overf...
553
554
555
556
557
558
559
560
  			if (reboot_cpu >= num_possible_cpus()) {
  				pr_err("Ignoring the CPU number in reboot= option. "
  				       "CPU %d exceeds possible cpu number %d
  ",
  				       reboot_cpu, num_possible_cpus());
  				reboot_cpu = 0;
  				break;
  			}
1b3a5d02e   Robin Holt   reboot: move arch...
561
  			break;
8b92c4ff4   Matteo Croce   Revert "kernel/re...
562

1b3a5d02e   Robin Holt   reboot: move arch...
563
  		case 'g':
b287a25a7   Aaro Koskinen   panic/reboot: all...
564
  			*mode = REBOOT_GPIO;
1b3a5d02e   Robin Holt   reboot: move arch...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  			break;
  
  		case 'b':
  		case 'a':
  		case 'k':
  		case 't':
  		case 'e':
  		case 'p':
  			reboot_type = *str;
  			break;
  
  		case 'f':
  			reboot_force = 1;
  			break;
  		}
  
  		str = strchr(str, ',');
  		if (str)
  			str++;
  		else
  			break;
  	}
  	return 1;
  }
  __setup("reboot=", reboot_setup);