All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: mathieu.poirier@linaro.org
Cc: linux-kernel@vger.kernel.org, arve@android.com,
	kernel-team@android.com, john.stultz@linaro.org,
	alan@lxorguk.ukuu.org.uk
Subject: Re: [PATCH v4] drivers/tty: Folding Android's keyreset driver in sysRQ
Date: Sun, 18 Nov 2012 23:25:25 -0800	[thread overview]
Message-ID: <20121119072525.GA16730@core.coreip.homeip.net> (raw)
In-Reply-To: <1352665488-13818-1-git-send-email-mathieu.poirier@linaro.org>

Hi Mathieu,

On Sun, Nov 11, 2012 at 01:24:48PM -0700, mathieu.poirier@linaro.org wrote:
> From: "Mathieu J. Poirier" <mathieu.poirier@linaro.org>
> 
> This patch adds keyreset functionality to the sysrq driver. It
> allows certain button/key combinations to be used in order to
> trigger device resets.
> 
> The first time the key-combo is detected a work function that syncs
> the filesystems is scheduled and the kernel rebooted. If all the keys
> are released and then pressed again, it calls panic. Reboot on panic
> should be set for this to work.
> 
> Redefining the '__weak sysrq_keyreset_get_params' function is required
> to trigger the feature.  Alternatively keys can be passed to the
> driver via the "/sys/module/sysrq" interface.
> 
> This functionality comes from the keyreset driver submitted by
> Arve Hjønnevåg in the Android kernel.

Thank you for making the changes. This still looks pretty complicated,
how about if we trim it a bit, like in the patch below.

Thanks.

-- 
Dmitry

Input: sysrq - allow specifying alternate reset sequence

From: Mathieu J. Poirier <mathieu.poirier@linaro.org>

This patch adds keyreset functionality to the sysrq driver. It allows
certain button/key combinations to be used in order to trigger emergency
reboots.

Redefining the '__weak platform_sysrq_reset_seq' variable is required
to trigger the feature.  Alternatively keys can be passed to the driver
via a module parameter.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/tty/sysrq.c |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 16ee6ce..9dddaf7 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/uaccess.h>
+#include <linux/moduleparam.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -576,8 +577,73 @@ struct sysrq_state {
 	bool active;
 	bool need_reinject;
 	bool reinjecting;
+
+	/* reset sequence handling */
+	bool reset_canceled;
+	unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
+	int reset_seq_len;
+	int reset_seq_cnt;
+	int reset_seq_version;
 };
 
+#define SYSRQ_KEY_RESET_MAX	20 /* Should be plenty */
+static unsigned short sysrq_reset_seq[SYSRQ_KEY_RESET_MAX];
+static unsigned int sysrq_reset_seq_len;
+static unsigned int sysrq_reset_seq_version = 1;
+
+static void sysrq_parse_reset_sequence(struct sysrq_state *state)
+{
+	int i;
+	unsigned short key;
+
+	state->reset_seq_cnt = 0;
+
+	for (i = 0; i < sysrq_reset_seq_len; i++) {
+		key = sysrq_reset_seq[i];
+
+		if (key == KEY_RESERVED || key > KEY_MAX)
+			break;
+
+		__set_bit(key, state->reset_keybit);
+		state->reset_seq_len++;
+
+		if (test_bit(key, state->key_down))
+			state->reset_seq_cnt++;
+	}
+}
+
+static bool sysrq_detect_reset_sequence(struct sysrq_state *state,
+					unsigned int code, int value)
+{
+	if (state->reset_seq_version != sysrq_reset_seq_version) {
+		sysrq_parse_reset_sequence(state);
+		/* Disable reset until old keys are not released */
+		state->reset_canceled = state->reset_seq_cnt != 0;
+		state->reset_seq_version = sysrq_reset_seq_version;
+	}
+
+	if (!test_bit(code, state->reset_keybit)) {
+		/*
+		 * Pressing any key _not_ in reset sequence cancels
+		 * the reset sequence.
+		 */
+		if (value && state->reset_seq_cnt)
+			state->reset_canceled = true;
+	} else if (value == 0) {
+		/* key release */
+		if (--state->reset_seq_cnt == 0)
+			state->reset_canceled = false;
+	} else if (value == 1) {
+		/* key press, not autorepeat */
+		if (++state->reset_seq_cnt == state->reset_seq_len &&
+		    !state->reset_canceled) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static void sysrq_reinject_alt_sysrq(struct work_struct *work)
 {
 	struct sysrq_state *sysrq =
@@ -690,6 +756,11 @@ static bool sysrq_filter(struct input_handle *handle,
 			if (was_active)
 				schedule_work(&sysrq->reinject_work);
 
+			if (sysrq_detect_reset_sequence(sysrq, code, value)) {
+				/* Force emergency reboot */
+				__handle_sysrq(sysrq_xlate[KEY_B], false);
+			}
+
 		} else if (value == 0 &&
 			   test_and_clear_bit(code, sysrq->key_down)) {
 			/*
@@ -785,7 +856,20 @@ static bool sysrq_handler_registered;
 
 static inline void sysrq_register_handler(void)
 {
+	extern unsigned short platform_sysrq_reset_seq[] __weak;
+	unsigned short key;
 	int error;
+	int i;
+
+	if (platform_sysrq_reset_seq) {
+		for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
+			key = platform_sysrq_reset_seq[i];
+			if (key == KEY_RESERVED || key > KEY_MAX)
+				break;
+
+			sysrq_reset_seq[sysrq_reset_seq_len++] = key;
+		}
+	}
 
 	error = input_register_handler(&sysrq_handler);
 	if (error)
@@ -802,6 +886,36 @@ static inline void sysrq_unregister_handler(void)
 	}
 }
 
+static int sysrq_reset_seq_param_set(const char *buffer,
+				     const struct kernel_param *kp)
+{
+	unsigned long val;
+	int error;
+
+	error = strict_strtoul(buffer, 0, &val);
+	if (error < 0)
+		return error;
+
+	if (val > KEY_MAX)
+		return -EINVAL;
+
+	*((unsigned short *)kp->arg) = val;
+	sysrq_reset_seq_version++;
+
+	return 0;
+}
+
+static struct kernel_param_ops param_ops_sysrq_reset_seq = {
+	.get	= param_get_ushort,
+	.set	= sysrq_reset_seq_param_set,
+};
+
+#define param_check_sysrq_reset_seq(name, p)	\
+	__param_check(name, p, unsigned short)
+
+module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
+			 &sysrq_reset_seq_len, 0644);
+
 #else
 
 static inline void sysrq_register_handler(void)

  reply	other threads:[~2012-11-19  7:25 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-11 20:24 [PATCH v4] drivers/tty: Folding Android's keyreset driver in sysRQ mathieu.poirier
2012-11-19  7:25 ` Dmitry Torokhov [this message]
     [not found]   ` <CAPM=9tw8mefcYTqELXFbZWZ44a--SNcPnRMAvMSGTiODzRpDhg@mail.gmail.com>
2013-02-27  8:26     ` Dave Airlie
2013-02-27 11:06       ` Dave Airlie
2013-02-27 11:10         ` Dave Airlie
2013-02-27 11:40           ` Dave Airlie
2013-02-27 16:57     ` Linus Torvalds
2013-02-27 17:58       ` Mathieu Poirier
2013-02-27 18:09         ` Linus Torvalds
2013-02-27 18:26           ` David Howells
2013-02-27 18:49         ` Dmitry Torokhov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121119072525.GA16730@core.coreip.homeip.net \
    --to=dmitry.torokhov@gmail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arve@android.com \
    --cc=john.stultz@linaro.org \
    --cc=kernel-team@android.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mathieu.poirier@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.