Messages in this thread Patch in this message | | | Date | Mon, 15 Sep 2008 19:30:05 +0300 | From | Eran Liberty <> | Subject | [PATCH 2.6.26] SERIAL DRIVER: Handle Multiple consecutive sysrq from the serial |
| |
Dear Penguins,
Let me start of by saying my particular hardware must be buggy in some way. When I issue a sysrq (Ctrl A+ F from minicom) I get a lot of sysrq triggers.
I have worked around the problem and I think this workaround is a viable patch even for platforms which do not exhibit this peculiar behavior.
upon getting numerous interrupts which request sysrq the function uart_handle_break in include/linux/serial_core.h is hit multiple times. The current code which looks like this:
static inline int uart_handle_break(struct uart_port *port) { struct uart_info *info = port->info; #ifdef SUPPORT_SYSRQ if (port->cons && port->cons->index == port->line) { if (!port->sysrq) { port->sysrq = jiffies + HZ*5; return 1; } port->sysrq = 0; } #endif if (port->flags & UPF_SAK) do_SAK(info->tty); return 0; }
Will basicly toggle port->sysrq between a timeout value and zero. If you are lucky this penguin rullet will stop on timeout and the next character hit will trigger the sysrq in the function "uart_handle_sysrq_char". But if you are not so lucky the last sysrq interupt will toggle port->sysrq to zero and the next char hit will be ignored (not trigger sysrq).
The suggested patch will do the next few things:
1. "port->sysrq" is now the time when the last sysrq was triggered and not the timeout for the the next char 2. Stamped "port->sysrq" every time there is a sysrq rather then toggled it up and down. 3. Always continue to consider UPF_SAK. 4. "port->sysrq" is toggled back to zero only in uart_handle_break() and only if the a char has been accepted after the sysrq timeout (5 sec) 5. uart_handle_break() will ignore extra chars received in super human speed after the last sysrq (0.01 sec)
Liberty
Signed-off-by: Eran Liberty <liberty@extricom.org> ---
Index: include/linux/serial_core.h =================================================================== --- include/linux/serial_core.h (revision 119) +++ include/linux/serial_core.h (revision 120) @@ -447,8 +447,8 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) { #ifdef SUPPORT_SYSRQ - if (port->sysrq) { - if (ch && time_before(jiffies, port->sysrq)) { + if (port->sysrq && time_after(jiffies, port->sysrq + (unsigned long)(HZ*0.01))) { + if (ch && time_before(jiffies, port->sysrq + HZ*5)) { handle_sysrq(ch, port->info ? port->info->tty : NULL); port->sysrq = 0; return 1; @@ -467,19 +467,17 @@ */ static inline int uart_handle_break(struct uart_port *port) { + int ret = 0; struct uart_info *info = port->info; #ifdef SUPPORT_SYSRQ if (port->cons && port->cons->index == port->line) { - if (!port->sysrq) { - port->sysrq = jiffies + HZ*5; - return 1; - } - port->sysrq = 0; + port->sysrq = jiffies; + ret = 1; } #endif if (port->flags & UPF_SAK) do_SAK(info->tty); - return 0; + return ret; } /** | |