On 1/10/20 4:46 PM, Greg Kroah-Hartman wrote: [..] >> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c >> index 6ac9dfed3423..f70eba032d0b 100644 >> --- a/drivers/tty/serial/serial_core.c >> +++ b/drivers/tty/serial/serial_core.c >> @@ -3081,6 +3081,38 @@ void uart_insert_char(struct uart_port *port, unsigned int status, >> } >> EXPORT_SYMBOL_GPL(uart_insert_char); >> >> +const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; >> + >> +static void uart_sysrq_on(struct work_struct *w) >> +{ >> + sysrq_toggle_support(1); >> + pr_info("SysRq is enabled by magic sequience on serial\n"); > > Do we want to say what serial port it is enabled on? Makes sense, will add. > And why is this done in a workqueue? uart_try_toggle_sysrq() sometimes is called under spin_lock_irqsave(&port->lock, flags); And sysrq_toggle_support() calls input_register_handler() internally which can sleep. >> +} >> +static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); >> + >> +static int uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) >> +{ >> + if (sysrq_toggle_seq[0] == '\0') >> + return 0; > > Is constantly checking the data stream like this going to slow things > down overall? Ah, we are just checking this after BREAK, right? So > that hopefully will not be that bad... Yes, it's after BREAK. In my POV it's fine as originally it would cause sysrq handler being called (if sysrq is enabled). > >> + >> + BUILD_BUG_ON(ARRAY_SIZE(sysrq_toggle_seq) >= sizeof(port->sysrq_seq)*U8_MAX); >> + if (sysrq_toggle_seq[port->sysrq_seq] != ch) { >> + port->sysrq_seq = 0; >> + return 0; >> + } >> + >> + /* Without the last \0 */ >> + if (++port->sysrq_seq < (ARRAY_SIZE(sysrq_toggle_seq) - 1)) { >> + port->sysrq = jiffies + HZ*5; > > 5 second delay? You should document what this value is for somewhere > here... Fair enough, I'll add #define SYSRQ_TIMEOUT (HZ*5) And use it in uart_handle_break() too. >> @@ -3090,9 +3122,13 @@ int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) >> return 0; >> >> if (ch && time_before(jiffies, port->sysrq)) { >> - handle_sysrq(ch); >> - port->sysrq = 0; >> - return 1; >> + if (sysrq_get_mask()) { >> + handle_sysrq(ch); >> + port->sysrq = 0; >> + return 1; >> + } > > Isn't this change to test for sysrq_get_mask() a different change than > checking for the "magic" data stream? It's for the case when sysrq is already enabled. Than sysrq_get_mask() will return something and it makes uart call handle_sysrq() instead of checking the toggle sequence. >> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h >> index 255e86a474e9..1f4443db5474 100644 >> --- a/include/linux/serial_core.h >> +++ b/include/linux/serial_core.h >> @@ -243,10 +243,10 @@ struct uart_port { >> unsigned long sysrq; /* sysrq timeout */ >> unsigned int sysrq_ch; /* char for sysrq */ >> unsigned char has_sysrq; >> + unsigned char sysrq_seq; /* index in sysrq_toggle_seq */ >> >> unsigned char hub6; /* this should be in the 8250 driver */ >> unsigned char suspended; >> - unsigned char unused; > > This is an unrelated change, let's leave it for a different patch that > cleans up the layout of this structure, ok? Yes, sure. Thanks, Dmitry