From: Benjamin Herrenschmidt pmac_zilog wasn't properly updating port->timeout, thus broke with serial console. I'm not sure if that timeout thing was added recently or not, since the driver used to work fine. This patch fixes that, and adds some proper SYSRQ support. By default, BREAK is used for sysrq, though some Apple zilog's seem to have non-working BREAK detection logic, thus the driver has a #define option you can manually enable when debugging to do SYSRQ with ctrl-O instead (like pSeries virtual consoles). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton --- 25-akpm/drivers/serial/pmac_zilog.c | 50 ++++++++++++++++++++++++++++-------- 25-akpm/drivers/serial/pmac_zilog.h | 1 2 files changed, 40 insertions(+), 11 deletions(-) diff -puN drivers/serial/pmac_zilog.c~fix-pmac_zilog-as-console drivers/serial/pmac_zilog.c --- 25/drivers/serial/pmac_zilog.c~fix-pmac_zilog-as-console 2004-11-04 19:39:06.560540016 -0800 +++ 25-akpm/drivers/serial/pmac_zilog.c 2004-11-04 19:39:06.567538952 -0800 @@ -29,6 +29,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * 2004-08-06 Harald Welte + * - Enable BREAK interrupt + * - Add support for sysreq + * * TODO: - Add DMA support * - Defer port shutdown to a few seconds after close * - maybe put something right into uap->clk_divisor @@ -36,6 +40,7 @@ #undef DEBUG #undef DEBUG_HARD +#undef USE_CTRL_O_SYSRQ #include #include @@ -54,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +70,10 @@ #include #include +#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include @@ -259,8 +269,27 @@ static struct tty_struct *pmz_receive_ch } ch &= uap->parity_mask; - if (ch == 0 && uap->prev_status & BRK_ABRT) - r1 |= BRK_ABRT; + if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) { + uap->flags &= ~PMACZILOG_FLAG_BREAK; + } + +#ifdef CONFIG_MAGIC_SYSRQ +#ifdef USE_CTRL_O_SYSRQ + /* Handle the SysRq ^O Hack */ + if (ch == '\x0f') { + uap->port.sysrq = jiffies + HZ*5; + goto next_char; + } +#endif /* USE_CTRL_O_SYSRQ */ + if (uap->port.sysrq) { + int swallow; + spin_unlock(&uap->port.lock); + swallow = uart_handle_sysrq_char(&uap->port, ch, regs); + spin_lock(&uap->port.lock); + if (swallow) + goto next_char; + } +#endif /* CONFIG_MAGIC_SYSRQ */ /* A real serial line, record the character and status. */ if (drop) @@ -276,10 +305,8 @@ static struct tty_struct *pmz_receive_ch pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) { - pmz_debug("pmz: do handle break !\n"); + if (uart_handle_break(&uap->port)) goto next_char; - } } else if (r1 & PAR_ERR) uap->port.icount.parity++; @@ -295,10 +322,6 @@ static struct tty_struct *pmz_receive_ch else if (r1 & CRC_ERR) *tty->flip.flag_buf_ptr = TTY_FRAME; } - if (uart_handle_sysrq_char(&uap->port, ch, regs)) { - pmz_debug("pmz: sysrq swallowed the char\n"); - goto next_char; - } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->port.ignore_status_mask) == 0) { @@ -364,6 +387,9 @@ static void pmz_status_handle(struct uar wake_up_interruptible(&uap->port.info->delta_msr_wait); } + if (status & BRK_ABRT) + uap->flags |= PMACZILOG_FLAG_BREAK; + uap->prev_status = status; } @@ -872,8 +898,8 @@ static int __pmz_startup(struct uart_pma uap->curregs[R13] = 0; uap->curregs[R14] = BRENAB; - /* Clear handshaking */ - uap->curregs[R15] = 0; + /* Clear handshaking, enable BREAK interrupts */ + uap->curregs[R15] = BRKIE; /* Master interrupt enable */ uap->curregs[R9] |= NV | MIE; @@ -1308,6 +1334,8 @@ static void __pmz_set_termios(struct uar /* Load registers to the chip */ pmz_maybe_update_regs(uap); } + uart_update_timeout(port, termios->c_cflag, baud); + pmz_debug("pmz: set_termios() done.\n"); } diff -puN drivers/serial/pmac_zilog.h~fix-pmac_zilog-as-console drivers/serial/pmac_zilog.h --- 25/drivers/serial/pmac_zilog.h~fix-pmac_zilog-as-console 2004-11-04 19:39:06.561539864 -0800 +++ 25-akpm/drivers/serial/pmac_zilog.h 2004-11-04 19:39:06.567538952 -0800 @@ -47,6 +47,7 @@ struct uart_pmac_port { #define PMACZILOG_FLAG_IS_OPEN 0x00002000 #define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000 #define PMACZILOG_FLAG_IS_EXTCLK 0x00008000 +#define PMACZILOG_FLAG_BREAK 0x00010000 unsigned char parity_mask; unsigned char prev_status; _