瀏覽代碼

Input: sysrq - request graceful shutdown for key reset

Attempt to reboot the system gracefully when a key combo is detected.
If the reste combination is pressed the 2nd time we assume that graceful
reboot failed and perform emergency reboot. This fucntionality is useful
when UI is stuck but the system is otherwise working fine.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Mathieu J. Poirier 12 年之前
父節點
當前提交
3d289517df
共有 1 個文件被更改,包括 15 次插入4 次删除
  1. 15 4
      drivers/tty/sysrq.c

+ 15 - 4
drivers/tty/sysrq.c

@@ -44,6 +44,7 @@
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
+#include <linux/syscalls.h>
 
 
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
 #include <asm/irq_regs.h>
@@ -586,6 +587,7 @@ struct sysrq_state {
 
 
 	/* reset sequence handling */
 	/* reset sequence handling */
 	bool reset_canceled;
 	bool reset_canceled;
+	bool reset_requested;
 	unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
 	unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
 	int reset_seq_len;
 	int reset_seq_len;
 	int reset_seq_cnt;
 	int reset_seq_cnt;
@@ -624,18 +626,26 @@ static void sysrq_parse_reset_sequence(struct sysrq_state *state)
 	state->reset_seq_version = sysrq_reset_seq_version;
 	state->reset_seq_version = sysrq_reset_seq_version;
 }
 }
 
 
-static void sysrq_do_reset(unsigned long dummy)
+static void sysrq_do_reset(unsigned long _state)
 {
 {
-	__handle_sysrq(sysrq_xlate[KEY_B], false);
+	struct sysrq_state *state = (struct sysrq_state *) _state;
+
+	state->reset_requested = true;
+
+	sys_sync();
+	kernel_restart(NULL);
 }
 }
 
 
 static void sysrq_handle_reset_request(struct sysrq_state *state)
 static void sysrq_handle_reset_request(struct sysrq_state *state)
 {
 {
+	if (state->reset_requested)
+		__handle_sysrq(sysrq_xlate[KEY_B], false);
+
 	if (sysrq_reset_downtime_ms)
 	if (sysrq_reset_downtime_ms)
 		mod_timer(&state->keyreset_timer,
 		mod_timer(&state->keyreset_timer,
 			jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms));
 			jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms));
 	else
 	else
-		sysrq_do_reset(0);
+		sysrq_do_reset((unsigned long)state);
 }
 }
 
 
 static void sysrq_detect_reset_sequence(struct sysrq_state *state,
 static void sysrq_detect_reset_sequence(struct sysrq_state *state,
@@ -837,7 +847,8 @@ static int sysrq_connect(struct input_handler *handler,
 	sysrq->handle.handler = handler;
 	sysrq->handle.handler = handler;
 	sysrq->handle.name = "sysrq";
 	sysrq->handle.name = "sysrq";
 	sysrq->handle.private = sysrq;
 	sysrq->handle.private = sysrq;
-	setup_timer(&sysrq->keyreset_timer, sysrq_do_reset, 0);
+	setup_timer(&sysrq->keyreset_timer,
+		    sysrq_do_reset, (unsigned long)sysrq);
 
 
 	error = input_register_handle(&sysrq->handle);
 	error = input_register_handle(&sysrq->handle);
 	if (error) {
 	if (error) {