blob: 7ef6866b521d21394e8fe41cf69880864d432992 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * poweroff.c - sysrq handler to gracefully power down machine.
3 *
4 * This file is released under the GPL v2
5 */
6
7#include <linux/kernel.h>
8#include <linux/sysrq.h>
9#include <linux/init.h>
10#include <linux/pm.h>
11#include <linux/workqueue.h>
Eric W. Biedermanff319772005-07-26 11:47:32 -060012#include <linux/reboot.h>
Zhang Rui2f15fc42008-07-23 21:28:40 -070013#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
15/*
16 * When the user hits Sys-Rq o to power down the machine this is the
17 * callback we use.
18 */
19
David Howells65f27f32006-11-22 14:55:48 +000020static void do_poweroff(struct work_struct *dummy)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021{
Eric W. Biedermanff319772005-07-26 11:47:32 -060022 kernel_power_off();
Linus Torvalds1da177e2005-04-16 15:20:36 -070023}
24
David Howells65f27f32006-11-22 14:55:48 +000025static DECLARE_WORK(poweroff_work, do_poweroff);
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Dmitry Torokhov1495cc92010-08-17 21:15:46 -070027static void handle_poweroff(int key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070028{
Zhang Rui2f15fc42008-07-23 21:28:40 -070029 /* run sysrq poweroff on boot cpu */
Rusty Russell41c7bb92009-01-01 10:12:28 +103030 schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -070031}
32
33static struct sysrq_key_op sysrq_poweroff_op = {
34 .handler = handle_poweroff,
zhangwei(Jovi)28ad5852013-04-30 15:28:52 -070035 .help_msg = "poweroff(o)",
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 .action_msg = "Power Off",
Manish Katiyar1dc492a2009-02-22 10:24:27 +053037 .enable_mask = SYSRQ_ENABLE_BOOT,
Linus Torvalds1da177e2005-04-16 15:20:36 -070038};
39
Jan Beulichbbdc18a2012-09-10 12:05:18 +000040static int __init pm_sysrq_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041{
42 register_sysrq_key('o', &sysrq_poweroff_op);
43 return 0;
44}
45
46subsys_initcall(pm_sysrq_init);