diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 16:20:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 16:20:04 -0400 |
commit | 251df49db3327c64bf917bfdba94491fde2b4ee0 (patch) | |
tree | 71eef72e1c393057f7b14cc4d8da5e48c7728336 /drivers/tty | |
parent | 8a72f3820c4d14b27ad5336aed00063a7a7f1bef (diff) | |
parent | bf61c8840efe60fd8f91446860b63338fb424158 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"Assorted fixes and cleanups to the existing drivers plus a new driver
for IMS Passenger Control Unit device they use for ther in-flight
entertainment system."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits)
Input: trackpoint - Optimize trackpoint init to use power-on reset
Input: apbps2 - convert to devm_ioremap_resource()
Input: ALPS - use %ph to print buffers
ARM - shmobile: Armadillo800EVA: Move st1232 reset pin handling
Input: st1232 - add reset pin handling
Input: st1232 - convert to devm_* infrastructure
Input: MT - handle semi-mt devices in core
Input: adxl34x - use spi_get_drvdata()
Input: ad7877 - use spi_get_drvdata() and spi_set_drvdata()
Input: ads7846 - use spi_get_drvdata() and spi_set_drvdata()
Input: ims-pcu - fix a memory leak on error
Input: sysrq - supplement reset sequence with timeout functionality
Input: tegra-kbc - support for defining row/columns based on SoC
Input: imx_keypad - switch to using managed resources
Input: arc_ps2 - add support for device tree
Input: mma8450 - fix signed 12bits to 32bits conversion
Input: eeti_ts - remove redundant null check
Input: edt-ft5x06 - remove redundant null check before kfree
Input: ad714x - add CONFIG_PM_SLEEP to suspend/resume functions
Input: adxl34x - add CONFIG_PM_SLEEP to suspend/resume functions
...
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/sysrq.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 0a0de333c765..b51c15408ff3 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/input.h> | 43 | #include <linux/input.h> |
44 | #include <linux/uaccess.h> | 44 | #include <linux/uaccess.h> |
45 | #include <linux/moduleparam.h> | 45 | #include <linux/moduleparam.h> |
46 | #include <linux/jiffies.h> | ||
46 | 47 | ||
47 | #include <asm/ptrace.h> | 48 | #include <asm/ptrace.h> |
48 | #include <asm/irq_regs.h> | 49 | #include <asm/irq_regs.h> |
@@ -51,6 +52,9 @@ | |||
51 | static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE; | 52 | static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE; |
52 | static bool __read_mostly sysrq_always_enabled; | 53 | static bool __read_mostly sysrq_always_enabled; |
53 | 54 | ||
55 | unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; | ||
56 | int sysrq_reset_downtime_ms __weak; | ||
57 | |||
54 | static bool sysrq_on(void) | 58 | static bool sysrq_on(void) |
55 | { | 59 | { |
56 | return sysrq_enabled || sysrq_always_enabled; | 60 | return sysrq_enabled || sysrq_always_enabled; |
@@ -586,6 +590,7 @@ struct sysrq_state { | |||
586 | int reset_seq_len; | 590 | int reset_seq_len; |
587 | int reset_seq_cnt; | 591 | int reset_seq_cnt; |
588 | int reset_seq_version; | 592 | int reset_seq_version; |
593 | struct timer_list keyreset_timer; | ||
589 | }; | 594 | }; |
590 | 595 | ||
591 | #define SYSRQ_KEY_RESET_MAX 20 /* Should be plenty */ | 596 | #define SYSRQ_KEY_RESET_MAX 20 /* Should be plenty */ |
@@ -619,29 +624,51 @@ static void sysrq_parse_reset_sequence(struct sysrq_state *state) | |||
619 | state->reset_seq_version = sysrq_reset_seq_version; | 624 | state->reset_seq_version = sysrq_reset_seq_version; |
620 | } | 625 | } |
621 | 626 | ||
622 | static bool sysrq_detect_reset_sequence(struct sysrq_state *state, | 627 | static void sysrq_do_reset(unsigned long dummy) |
628 | { | ||
629 | __handle_sysrq(sysrq_xlate[KEY_B], false); | ||
630 | } | ||
631 | |||
632 | static void sysrq_handle_reset_request(struct sysrq_state *state) | ||
633 | { | ||
634 | if (sysrq_reset_downtime_ms) | ||
635 | mod_timer(&state->keyreset_timer, | ||
636 | jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms)); | ||
637 | else | ||
638 | sysrq_do_reset(0); | ||
639 | } | ||
640 | |||
641 | static void sysrq_detect_reset_sequence(struct sysrq_state *state, | ||
623 | unsigned int code, int value) | 642 | unsigned int code, int value) |
624 | { | 643 | { |
625 | if (!test_bit(code, state->reset_keybit)) { | 644 | if (!test_bit(code, state->reset_keybit)) { |
626 | /* | 645 | /* |
627 | * Pressing any key _not_ in reset sequence cancels | 646 | * Pressing any key _not_ in reset sequence cancels |
628 | * the reset sequence. | 647 | * the reset sequence. Also cancelling the timer in |
648 | * case additional keys were pressed after a reset | ||
649 | * has been requested. | ||
629 | */ | 650 | */ |
630 | if (value && state->reset_seq_cnt) | 651 | if (value && state->reset_seq_cnt) { |
631 | state->reset_canceled = true; | 652 | state->reset_canceled = true; |
653 | del_timer(&state->keyreset_timer); | ||
654 | } | ||
632 | } else if (value == 0) { | 655 | } else if (value == 0) { |
633 | /* key release */ | 656 | /* |
657 | * Key release - all keys in the reset sequence need | ||
658 | * to be pressed and held for the reset timeout | ||
659 | * to hold. | ||
660 | */ | ||
661 | del_timer(&state->keyreset_timer); | ||
662 | |||
634 | if (--state->reset_seq_cnt == 0) | 663 | if (--state->reset_seq_cnt == 0) |
635 | state->reset_canceled = false; | 664 | state->reset_canceled = false; |
636 | } else if (value == 1) { | 665 | } else if (value == 1) { |
637 | /* key press, not autorepeat */ | 666 | /* key press, not autorepeat */ |
638 | if (++state->reset_seq_cnt == state->reset_seq_len && | 667 | if (++state->reset_seq_cnt == state->reset_seq_len && |
639 | !state->reset_canceled) { | 668 | !state->reset_canceled) { |
640 | return true; | 669 | sysrq_handle_reset_request(state); |
641 | } | 670 | } |
642 | } | 671 | } |
643 | |||
644 | return false; | ||
645 | } | 672 | } |
646 | 673 | ||
647 | static void sysrq_reinject_alt_sysrq(struct work_struct *work) | 674 | static void sysrq_reinject_alt_sysrq(struct work_struct *work) |
@@ -748,10 +775,8 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq, | |||
748 | if (was_active) | 775 | if (was_active) |
749 | schedule_work(&sysrq->reinject_work); | 776 | schedule_work(&sysrq->reinject_work); |
750 | 777 | ||
751 | if (sysrq_detect_reset_sequence(sysrq, code, value)) { | 778 | /* Check for reset sequence */ |
752 | /* Force emergency reboot */ | 779 | sysrq_detect_reset_sequence(sysrq, code, value); |
753 | __handle_sysrq(sysrq_xlate[KEY_B], false); | ||
754 | } | ||
755 | 780 | ||
756 | } else if (value == 0 && test_and_clear_bit(code, sysrq->key_down)) { | 781 | } else if (value == 0 && test_and_clear_bit(code, sysrq->key_down)) { |
757 | /* | 782 | /* |
@@ -812,6 +837,7 @@ static int sysrq_connect(struct input_handler *handler, | |||
812 | sysrq->handle.handler = handler; | 837 | sysrq->handle.handler = handler; |
813 | sysrq->handle.name = "sysrq"; | 838 | sysrq->handle.name = "sysrq"; |
814 | sysrq->handle.private = sysrq; | 839 | sysrq->handle.private = sysrq; |
840 | setup_timer(&sysrq->keyreset_timer, sysrq_do_reset, 0); | ||
815 | 841 | ||
816 | error = input_register_handle(&sysrq->handle); | 842 | error = input_register_handle(&sysrq->handle); |
817 | if (error) { | 843 | if (error) { |
@@ -841,6 +867,7 @@ static void sysrq_disconnect(struct input_handle *handle) | |||
841 | 867 | ||
842 | input_close_device(handle); | 868 | input_close_device(handle); |
843 | cancel_work_sync(&sysrq->reinject_work); | 869 | cancel_work_sync(&sysrq->reinject_work); |
870 | del_timer_sync(&sysrq->keyreset_timer); | ||
844 | input_unregister_handle(handle); | 871 | input_unregister_handle(handle); |
845 | kfree(sysrq); | 872 | kfree(sysrq); |
846 | } | 873 | } |
@@ -870,8 +897,6 @@ static struct input_handler sysrq_handler = { | |||
870 | 897 | ||
871 | static bool sysrq_handler_registered; | 898 | static bool sysrq_handler_registered; |
872 | 899 | ||
873 | unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; | ||
874 | |||
875 | static inline void sysrq_register_handler(void) | 900 | static inline void sysrq_register_handler(void) |
876 | { | 901 | { |
877 | unsigned short key; | 902 | unsigned short key; |
@@ -931,6 +956,8 @@ static struct kernel_param_ops param_ops_sysrq_reset_seq = { | |||
931 | module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq, | 956 | module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq, |
932 | &sysrq_reset_seq_len, 0644); | 957 | &sysrq_reset_seq_len, 0644); |
933 | 958 | ||
959 | module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644); | ||
960 | |||
934 | #else | 961 | #else |
935 | 962 | ||
936 | static inline void sysrq_register_handler(void) | 963 | static inline void sysrq_register_handler(void) |