aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/reboot.c')
-rw-r--r--kernel/reboot.c134
1 files changed, 129 insertions, 5 deletions
diff --git a/kernel/reboot.c b/kernel/reboot.c
index a3a9e240fcdb..d20c85d9f8c0 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -104,6 +104,87 @@ int unregister_reboot_notifier(struct notifier_block *nb)
104} 104}
105EXPORT_SYMBOL(unregister_reboot_notifier); 105EXPORT_SYMBOL(unregister_reboot_notifier);
106 106
107/*
108 * Notifier list for kernel code which wants to be called
109 * to restart the system.
110 */
111static ATOMIC_NOTIFIER_HEAD(restart_handler_list);
112
113/**
114 * register_restart_handler - Register function to be called to reset
115 * the system
116 * @nb: Info about handler function to be called
117 * @nb->priority: Handler priority. Handlers should follow the
118 * following guidelines for setting priorities.
119 * 0: Restart handler of last resort,
120 * with limited restart capabilities
121 * 128: Default restart handler; use if no other
122 * restart handler is expected to be available,
123 * and/or if restart functionality is
124 * sufficient to restart the entire system
125 * 255: Highest priority restart handler, will
126 * preempt all other restart handlers
127 *
128 * Registers a function with code to be called to restart the
129 * system.
130 *
131 * Registered functions will be called from machine_restart as last
132 * step of the restart sequence (if the architecture specific
133 * machine_restart function calls do_kernel_restart - see below
134 * for details).
135 * Registered functions are expected to restart the system immediately.
136 * If more than one function is registered, the restart handler priority
137 * selects which function will be called first.
138 *
139 * Restart handlers are expected to be registered from non-architecture
140 * code, typically from drivers. A typical use case would be a system
141 * where restart functionality is provided through a watchdog. Multiple
142 * restart handlers may exist; for example, one restart handler might
143 * restart the entire system, while another only restarts the CPU.
144 * In such cases, the restart handler which only restarts part of the
145 * hardware is expected to register with low priority to ensure that
146 * it only runs if no other means to restart the system is available.
147 *
148 * Currently always returns zero, as atomic_notifier_chain_register()
149 * always returns zero.
150 */
151int register_restart_handler(struct notifier_block *nb)
152{
153 return atomic_notifier_chain_register(&restart_handler_list, nb);
154}
155EXPORT_SYMBOL(register_restart_handler);
156
157/**
158 * unregister_restart_handler - Unregister previously registered
159 * restart handler
160 * @nb: Hook to be unregistered
161 *
162 * Unregisters a previously registered restart handler function.
163 *
164 * Returns zero on success, or %-ENOENT on failure.
165 */
166int unregister_restart_handler(struct notifier_block *nb)
167{
168 return atomic_notifier_chain_unregister(&restart_handler_list, nb);
169}
170EXPORT_SYMBOL(unregister_restart_handler);
171
172/**
173 * do_kernel_restart - Execute kernel restart handler call chain
174 *
175 * Calls functions registered with register_restart_handler.
176 *
177 * Expected to be called from machine_restart as last step of the restart
178 * sequence.
179 *
180 * Restarts the system immediately if a restart handler function has been
181 * registered. Otherwise does nothing.
182 */
183void do_kernel_restart(char *cmd)
184{
185 atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);
186}
187
107void migrate_to_reboot_cpu(void) 188void migrate_to_reboot_cpu(void)
108{ 189{
109 /* The boot cpu is always logical cpu 0 */ 190 /* The boot cpu is always logical cpu 0 */
@@ -306,8 +387,9 @@ void ctrl_alt_del(void)
306} 387}
307 388
308char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; 389char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
390static const char reboot_cmd[] = "/sbin/reboot";
309 391
310static int __orderly_poweroff(bool force) 392static int run_cmd(const char *cmd)
311{ 393{
312 char **argv; 394 char **argv;
313 static char *envp[] = { 395 static char *envp[] = {
@@ -316,8 +398,7 @@ static int __orderly_poweroff(bool force)
316 NULL 398 NULL
317 }; 399 };
318 int ret; 400 int ret;
319 401 argv = argv_split(GFP_KERNEL, cmd, NULL);
320 argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
321 if (argv) { 402 if (argv) {
322 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); 403 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
323 argv_free(argv); 404 argv_free(argv);
@@ -325,8 +406,33 @@ static int __orderly_poweroff(bool force)
325 ret = -ENOMEM; 406 ret = -ENOMEM;
326 } 407 }
327 408
409 return ret;
410}
411
412static int __orderly_reboot(void)
413{
414 int ret;
415
416 ret = run_cmd(reboot_cmd);
417
418 if (ret) {
419 pr_warn("Failed to start orderly reboot: forcing the issue\n");
420 emergency_sync();
421 kernel_restart(NULL);
422 }
423
424 return ret;
425}
426
427static int __orderly_poweroff(bool force)
428{
429 int ret;
430
431 ret = run_cmd(poweroff_cmd);
432
328 if (ret && force) { 433 if (ret && force) {
329 pr_warn("Failed to start orderly shutdown: forcing the issue\n"); 434 pr_warn("Failed to start orderly shutdown: forcing the issue\n");
435
330 /* 436 /*
331 * I guess this should try to kick off some daemon to sync and 437 * I guess this should try to kick off some daemon to sync and
332 * poweroff asap. Or not even bother syncing if we're doing an 438 * poweroff asap. Or not even bother syncing if we're doing an
@@ -355,15 +461,33 @@ static DECLARE_WORK(poweroff_work, poweroff_work_func);
355 * This may be called from any context to trigger a system shutdown. 461 * This may be called from any context to trigger a system shutdown.
356 * If the orderly shutdown fails, it will force an immediate shutdown. 462 * If the orderly shutdown fails, it will force an immediate shutdown.
357 */ 463 */
358int orderly_poweroff(bool force) 464void orderly_poweroff(bool force)
359{ 465{
360 if (force) /* do not override the pending "true" */ 466 if (force) /* do not override the pending "true" */
361 poweroff_force = true; 467 poweroff_force = true;
362 schedule_work(&poweroff_work); 468 schedule_work(&poweroff_work);
363 return 0;
364} 469}
365EXPORT_SYMBOL_GPL(orderly_poweroff); 470EXPORT_SYMBOL_GPL(orderly_poweroff);
366 471
472static void reboot_work_func(struct work_struct *work)
473{
474 __orderly_reboot();
475}
476
477static DECLARE_WORK(reboot_work, reboot_work_func);
478
479/**
480 * orderly_reboot - Trigger an orderly system reboot
481 *
482 * This may be called from any context to trigger a system reboot.
483 * If the orderly reboot fails, it will force an immediate reboot.
484 */
485void orderly_reboot(void)
486{
487 schedule_work(&reboot_work);
488}
489EXPORT_SYMBOL_GPL(orderly_reboot);
490
367static int __init reboot_setup(char *str) 491static int __init reboot_setup(char *str)
368{ 492{
369 for (;;) { 493 for (;;) {