#include <linux/uaccess.h>
#include <linux/moduleparam.h>
#include <linux/jiffies.h>
+#include <linux/syscalls.h>
+#include <linux/of.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
/* reset sequence handling */
bool reset_canceled;
+ bool reset_requested;
unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
int reset_seq_len;
int reset_seq_cnt;
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)
{
+ if (state->reset_requested)
+ __handle_sysrq(sysrq_xlate[KEY_B], false);
+
if (sysrq_reset_downtime_ms)
mod_timer(&state->keyreset_timer,
jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms));
else
- sysrq_do_reset(0);
+ sysrq_do_reset((unsigned long)state);
}
static void sysrq_detect_reset_sequence(struct sysrq_state *state,
}
}
+#ifdef CONFIG_OF
+static void sysrq_of_get_keyreset_config(void)
+{
+ u32 key;
+ struct device_node *np;
+ struct property *prop;
+ const __be32 *p;
+
+ np = of_find_node_by_path("/chosen/linux,sysrq-reset-seq");
+ if (!np) {
+ pr_debug("No sysrq node found");
+ return;
+ }
+
+ /* Reset in case a __weak definition was present */
+ sysrq_reset_seq_len = 0;
+
+ of_property_for_each_u32(np, "keyset", prop, p, key) {
+ if (key == KEY_RESERVED || key > KEY_MAX ||
+ sysrq_reset_seq_len == SYSRQ_KEY_RESET_MAX)
+ break;
+
+ sysrq_reset_seq[sysrq_reset_seq_len++] = (unsigned short)key;
+ }
+
+ /* Get reset timeout if any. */
+ of_property_read_u32(np, "timeout-ms", &sysrq_reset_downtime_ms);
+}
+#else
+static void sysrq_of_get_keyreset_config(void)
+{
+}
+#endif
+
static void sysrq_reinject_alt_sysrq(struct work_struct *work)
{
struct sysrq_state *sysrq =
sysrq->handle.handler = handler;
sysrq->handle.name = "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);
if (error) {
int error;
int i;
+ /* First check if a __weak interface was instantiated. */
for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
key = platform_sysrq_reset_seq[i];
if (key == KEY_RESERVED || key > KEY_MAX)
sysrq_reset_seq[sysrq_reset_seq_len++] = key;
}
+ /*
+ * DT configuration takes precedence over anything that would
+ * have been defined via the __weak interface.
+ */
+ sysrq_of_get_keyreset_config();
+
error = input_register_handler(&sysrq_handler);
if (error)
pr_err("Failed to register input handler, error %d", error);