aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250/8250.c
diff options
context:
space:
mode:
authorFlavio Leitner <fbl@redhat.com>2012-09-18 16:21:32 -0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-21 09:53:15 -0700
commitbd21f551c365e50a241b4cee4bc8be72914ff236 (patch)
treec67fce569d97f38504fd145bf1f173345aeedbec /drivers/tty/serial/8250/8250.c
parentpty: Fix locking bug on error path (diff)
downloadlinux-dev-bd21f551c365e50a241b4cee4bc8be72914ff236.tar.xz
linux-dev-bd21f551c365e50a241b4cee4bc8be72914ff236.zip
8250: fix autoconfig to work with serial console
The autoconfig prints messages while holding the port's spinlock and that causes a deadlock when using serial console. Signed-off-by: Flavio Leitner <fbl@redhat.com> Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250/8250.c')
-rw-r--r--drivers/tty/serial/8250/8250.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index d4e0b07cb130..932a216aa5bc 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1037,6 +1037,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
unsigned char save_lcr, save_mcr;
struct uart_port *port = &up->port;
unsigned long flags;
+ unsigned int old_capabilities;
if (!port->iobase && !port->mapbase && !port->membase)
return;
@@ -1087,6 +1088,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
/*
* We failed; there's nothing here
*/
+ spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
scratch2, scratch3);
goto out;
@@ -1110,6 +1112,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
status1 = serial_in(up, UART_MSR) & 0xF0;
serial_out(up, UART_MCR, save_mcr);
if (status1 != 0x90) {
+ spin_unlock_irqrestore(&port->lock, flags);
DEBUG_AUTOCONF("LOOP test failed (%02x) ",
status1);
goto out;
@@ -1132,8 +1135,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(up, UART_IIR) >> 6;
- DEBUG_AUTOCONF("iir=%d ", scratch);
-
switch (scratch) {
case 0:
autoconfig_8250(up);
@@ -1167,19 +1168,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
serial_out(up, UART_LCR, save_lcr);
- if (up->capabilities != uart_config[port->type].flags) {
- printk(KERN_WARNING
- "ttyS%d: detected caps %08x should be %08x\n",
- serial_index(port), up->capabilities,
- uart_config[port->type].flags);
- }
-
port->fifosize = uart_config[up->port.type].fifo_size;
+ old_capabilities = up->capabilities;
up->capabilities = uart_config[port->type].flags;
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (port->type == PORT_UNKNOWN)
- goto out;
+ goto out_lock;
/*
* Reset the UART.
@@ -1196,8 +1191,16 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
else
serial_out(up, UART_IER, 0);
- out:
+out_lock:
spin_unlock_irqrestore(&port->lock, flags);
+ if (up->capabilities != old_capabilities) {
+ printk(KERN_WARNING
+ "ttyS%d: detected caps %08x should be %08x\n",
+ serial_index(port), old_capabilities,
+ up->capabilities);
+ }
+out:
+ DEBUG_AUTOCONF("iir=%d ", scratch);
DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
}