From d608ab9917fbe9926704c07b27df72ac78133870 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Mon, 26 Jun 2006 18:18:11 +0200 Subject: [PATCH 1/4] [SERIAL] dz: Fix compilation error Fix the following compilation error in the dz serial driver that got introduced with the "kernel console should send CRLF not LFCR" change. CC drivers/serial/dz.o drivers/serial/dz.c: In function 'dz_console_putchar': drivers/serial/dz.c:679: error: 'uport' undeclared (first use in this function) drivers/serial/dz.c:679: error: (Each undeclared identifier is reported only once drivers/serial/dz.c:679: error: for each function it appears in.) Signed-off-by: Martin Michlmayr Signed-off-by: Russell King --- drivers/serial/dz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index d119c8296a78..8a98aae80e22 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -673,7 +673,7 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE -static void dz_console_putchar(struct uart_port *port, int ch) +static void dz_console_putchar(struct uart_port *uport, int ch) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; From c65b15cfd6b8b74c6f2b3635bf47ee661d351ef3 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sun, 9 Jul 2006 20:40:17 +0200 Subject: [PATCH 2/4] [SERIAL] IP22: fix serial console hangs The patch below fixes serial console hangs as seen on IP22 machines. Typically, while booting, the machine hangs for ~1 minute displaying "INIT: ", then the same thing happens again when init enters in the designated runlevel and finally the getty process on ttyS0 hangs indefinitely (though strace'ing it helps). strace (-e raw=ioctl, otherwise the ioctl() translation is utterly bogus) reveals that getty hangs on ioctl() 0x540f which happens to be TCSETSW (I saw it hang on another console ioctl() but couldn't reproduce that one). A diff between ip22zilog and sunzilog revealed the following differences: 1. the channel A flag being set on up.port.flags instead of up.flags 2. the channel A flag being set on what is marked as being channel B 3. sunzilog has a call to uart_update_timeout(port, termios->c_cflag, baud); at the end of sunzilog_set_termios(), which ip22zilog lacks (on purpose ?) The patch below addresses point 1 and fixes the serial console hangs just fine. However point 2 should be investigated by someone familiar with the IP22 Zilog; it's probably OK as is but even if it is, a comment in ip22zilog.c is badly needed. Point 3 is left as an exercise for whoever feels like digging into ip22zilog :) These are the main obvious differences between ip22zilog and sunzilog. Newer versions of sunzilog (Linus's git tree as of today) are more close to ip22zilog as the sbus_{write,read}b have been changed into simple {write,read}b, which shrinks the diff by a fair amount. Resyncing both drivers should be doable in a few hours time now for someone familiar with the IP22 Zilog hardware. Signed-off-by: Julien BLACHE Signed-off-by: Russell King --- drivers/serial/ip22zilog.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 342042889f6e..5ff269fb604c 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -1143,9 +1143,8 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.fifosize = 1; up[(chip * 2) + 1].port.ops = &ip22zilog_pops; up[(chip * 2) + 1].port.type = PORT_IP22ZILOG; - up[(chip * 2) + 1].port.flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; up[(chip * 2) + 1].port.line = (chip * 2) + 1; - up[(chip * 2) + 1].flags = 0; + up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; } } From 3be91ec7388bae3cf1bfb4febcee5ab6c65f409f Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Fri, 30 Jun 2006 02:29:58 -0700 Subject: [PATCH 3/4] [SERIAL] 8250: add tsi108 serial support The following patch gets rid of CONFIG_TSI108_BRIDGE. I add UPIO_TSI to handle IIR and IER register in serial_in and serial_out. (1) the reason to rewrite serial_in: TSI108 rev Z1 version ERRATA. Reading the UART's Interrupt Identification Register (IIR) clears the Transmit Holding Register Empty (THRE) and Transmit buffer Empty (TEMP) interrupts even if they are not enabled in the Interrupt Enable Register (IER). This leads to loss of the interrupts. Interrupts are not cleared when reading UART registers as 32-bit word. (2) the reason to rewrite serial_out: Check for UART_IER_UUE bit in the autoconfig routine. This section of autoconfig is excluded for Tsi108/109 because bits 7 and 6 are reserved for internal use. They are R/W bits. In addition to incorrect identification, changing these bits (from 00) will make Tsi108/109 UART non-functional. Signed-off-by: Roy Zang Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/serial/8250.c | 12 ++++++++++++ drivers/serial/serial_core.c | 1 + include/linux/serial_core.h | 1 + 3 files changed, 14 insertions(+) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 0995430e4cf1..5443fcd38355 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -299,6 +299,7 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) static unsigned int serial_in(struct uart_8250_port *up, int offset) { + unsigned int tmp; offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { @@ -317,6 +318,13 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset) return __raw_readl(up->port.membase + offset); #endif + case UPIO_TSI: + if (offset == UART_IIR) { + tmp = readl((u32 *)(up->port.membase + UART_RX)); + return (cpu_to_le32(tmp) >> 8) & 0xff; + } else + return readb(up->port.membase + offset); + default: return inb(up->port.iobase + offset); } @@ -346,6 +354,10 @@ serial_out(struct uart_8250_port *up, int offset, int value) __raw_writel(value, up->port.membase + offset); break; #endif + case UPIO_TSI: + if (!((offset == UART_IER) && (value & UART_IER_UUE))) + writeb(value, up->port.membase + offset); + break; default: outb(value, up->port.iobase + offset); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index d5f636fbf29a..80ef7d482756 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2036,6 +2036,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) case UPIO_MEM: case UPIO_MEM32: case UPIO_AU: + case UPIO_TSI: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 058cba70818a..86501a3de2ac 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -227,6 +227,7 @@ struct uart_port { #define UPIO_MEM (2) #define UPIO_MEM32 (3) #define UPIO_AU (4) /* Au1x00 type IO */ +#define UPIO_TSI (5) /* Tsi108/109 type IO */ unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ From 68aa2c0d4a36b43ea9c6d77134c94b4501fd2eb4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jun 2006 02:29:59 -0700 Subject: [PATCH 4/4] [SERIAL] 8250: sysrq deadlock fix Fix http://bugzilla.kernel.org/show_bug.cgi?id=6716 Doing a sysrq over a serial line into an SMP machine presently deadlocks. Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/serial/8250.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 5443fcd38355..0ae9ced00ed4 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2252,10 +2252,14 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); - if (oops_in_progress) { - locked = spin_trylock_irqsave(&up->port.lock, flags); + local_irq_save(flags); + if (up->port.sysrq) { + /* serial8250_handle_port() already took the lock */ + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); } else - spin_lock_irqsave(&up->port.lock, flags); + spin_lock(&up->port.lock); /* * First save the IER then disable the interrupts @@ -2277,7 +2281,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial_out(up, UART_IER, ier); if (locked) - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock(&up->port.lock); + local_irq_restore(flags); } static int serial8250_console_setup(struct console *co, char *options)