| @@ -20,6 +20,7 @@ · 19 unmodified lines |
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ | 21 | #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ |
| 22 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
| | 23 | #include <linux/sysrq.h> |
| 23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 24 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 25 | #include <linux/security.h> | 26 | #include <linux/security.h> |
| @@ -40,6 +41,8 @@ static struct lock_class_key port_lock_key; · 14 unmodified lines |
| 40 | | 41 | |
| 41 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 42 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
| 42 | | 43 | |
| | 44 | #define SYSRQ_TIMEOUT (HZ * 5) |
| | 45 | |
| 43 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | 46 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
| 44 | struct ktermios *old_termios); | 47 | struct ktermios *old_termios); |
| 45 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 48 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
| @@ -3084,6 +3087,56 @@ void uart_insert_char(struct uart_port *port, unsigned int status, · 3038 unmodified lines |
| 3084 | } | 3087 | } |
| 3085 | EXPORT_SYMBOL_GPL(uart_insert_char); | 3088 | EXPORT_SYMBOL_GPL(uart_insert_char); |
| 3086 | | 3089 | |
| | 3090 | #ifdef CONFIG_MAGIC_SYSRQ_SERIAL |
| | 3091 | static const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; |
| | 3092 | |
| | 3093 | static void uart_sysrq_on(struct work_struct *w) |
| | 3094 | { |
| | 3095 | sysrq_toggle_support(1); |
| | 3096 | pr_info("SysRq is enabled by magic sequence on serial\n"); |
| | 3097 | } |
| | 3098 | static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); |
| | 3099 | |
| | 3100 | /** |
| | 3101 | * uart_try_toggle_sysrq - Enables SysRq from serial line |
| | 3102 | * @port: uart_port structure where char(s) after BREAK met |
| | 3103 | * @ch: new character in the sequence after received BREAK |
| | 3104 | * |
| | 3105 | * Enables magic SysRq when the required sequence is met on port |
| | 3106 | * (see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE). |
| | 3107 | * |
| | 3108 | * Returns false if @ch is out of enabling sequence and should be |
| | 3109 | * handled some other way, true if @ch was consumed. |
| | 3110 | */ |
| | 3111 | static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) |
| | 3112 | { |
| | 3113 | if (ARRAY_SIZE(sysrq_toggle_seq) <= 1) |
| | 3114 | return false; |
| | 3115 | |
| | 3116 | BUILD_BUG_ON(ARRAY_SIZE(sysrq_toggle_seq) >= U8_MAX); |
| | 3117 | if (sysrq_toggle_seq[port->sysrq_seq] != ch) { |
| | 3118 | port->sysrq_seq = 0; |
| | 3119 | return false; |
| | 3120 | } |
| | 3121 | |
| | 3122 | /* Without the last \0 */ |
| | 3123 | if (++port->sysrq_seq < (ARRAY_SIZE(sysrq_toggle_seq) - 1)) { |
| | 3124 | port->sysrq = jiffies + SYSRQ_TIMEOUT; |
| | 3125 | return true; |
| | 3126 | } |
| | 3127 | |
| | 3128 | schedule_work(&sysrq_enable_work); |
| | 3129 | |
| | 3130 | port->sysrq = 0; |
| | 3131 | return true; |
| | 3132 | } |
| | 3133 | #else |
| | 3134 | static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) |
| | 3135 | { |
| | 3136 | return false; |
| | 3137 | } |
| | 3138 | #endif |
| | 3139 | |
| 3087 | int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) | 3140 | int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) |
| 3088 | { | 3141 | { |
| 3089 | if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) | 3142 | if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) |
| @@ -3093,9 +3146,13 @@ int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) · 3 unmodified lines |
| 3093 | return 0; | 3146 | return 0; |
| 3094 | | 3147 | |
| 3095 | if (ch && time_before(jiffies, port->sysrq)) { | 3148 | if (ch && time_before(jiffies, port->sysrq)) { |
| 3096 | handle_sysrq(ch); | 3149 | if (sysrq_mask()) { |
| 3097 | port->sysrq = 0; | 3150 | handle_sysrq(ch); |
| 3098 | return 1; | 3151 | port->sysrq = 0; |
| | 3152 | return 1; |
| | 3153 | } |
| | 3154 | if (uart_try_toggle_sysrq(port, ch)) |
| | 3155 | return 1; |
| 3099 | } | 3156 | } |
| 3100 | port->sysrq = 0; | 3157 | port->sysrq = 0; |
| 3101 | | 3158 | |
| @@ -3112,9 +3169,13 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) · 10 unmodified lines |
| 3112 | return 0; | 3169 | return 0; |
| 3113 | | 3170 | |
| 3114 | if (ch && time_before(jiffies, port->sysrq)) { | 3171 | if (ch && time_before(jiffies, port->sysrq)) { |
| 3115 | port->sysrq_ch = ch; | 3172 | if (sysrq_mask()) { |
| 3116 | port->sysrq = 0; | 3173 | port->sysrq_ch = ch; |
| 3117 | return 1; | 3174 | port->sysrq = 0; |
| | 3175 | return 1; |
| | 3176 | } |
| | 3177 | if (uart_try_toggle_sysrq(port, ch)) |
| | 3178 | return 1; |
| 3118 | } | 3179 | } |
| 3119 | port->sysrq = 0; | 3180 | port->sysrq = 0; |
| 3120 | | 3181 | |
| @@ -3154,7 +3215,7 @@ int uart_handle_break(struct uart_port *port) · 33 unmodified lines |
| 3154 | if (port->has_sysrq) { | 3215 | if (port->has_sysrq) { |
| 3155 | if (port->cons && port->cons->index == port->line) { | 3216 | if (port->cons && port->cons->index == port->line) { |
| 3156 | if (!port->sysrq) { | 3217 | if (!port->sysrq) { |
| 3157 | port->sysrq = jiffies + HZ*5; | 3218 | port->sysrq = jiffies + SYSRQ_TIMEOUT; |
| 3158 | return 1; | 3219 | return 1; |
| 3159 | } | 3220 | } |
| 3160 | port->sysrq = 0; | 3221 | port->sysrq = 0; |