diff options
Diffstat (limited to 'drivers/tty/serial/8250/8250.c')
-rw-r--r-- | drivers/tty/serial/8250/8250.c | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d4e0b07cb130..3ba4234592bc 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -290,6 +290,9 @@ static const struct serial8250_config uart_config[] = { UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, + [PORT_8250_CIR] = { + .name = "CIR port" + } }; /* Uart divisor latch read */ @@ -1037,6 +1040,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 +1091,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 +1115,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 +1138,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 +1171,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 +1194,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); } @@ -1897,6 +1903,9 @@ static int serial8250_startup(struct uart_port *port) unsigned char lsr, iir; int retval; + if (port->type == PORT_8250_CIR) + return -ENODEV; + port->fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; @@ -2554,7 +2563,10 @@ static int serial8250_request_port(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); - int ret = 0; + int ret; + + if (port->type == PORT_8250_CIR) + return -ENODEV; ret = serial8250_request_std_resource(up); if (ret == 0 && port->type == PORT_RSA) { @@ -2573,6 +2585,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) int probeflags = PROBE_ANY; int ret; + if (port->type == PORT_8250_CIR) + return; + /* * Find the region that we can probe for. This in turn * tells us whether we can probe for the type of port. @@ -2672,6 +2687,9 @@ static void __init serial8250_isa_init_ports(void) return; first = 0; + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; struct uart_port *port = &up->port; @@ -2681,6 +2699,7 @@ static void __init serial8250_isa_init_ports(void) init_timer(&up->timer); up->timer.function = serial8250_timeout; + up->cur_iotype = 0xFF; /* * ALPHA_KLUDGE_MCR needs to be killed. @@ -2732,13 +2751,9 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; - up->cur_iotype = 0xFF; - } - serial8250_isa_init_ports(); - - for (i = 0; i < nr_uarts; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; + if (up->port.dev) + continue; up->port.dev = dev; @@ -2863,9 +2878,6 @@ static struct console serial8250_console = { static int __init serial8250_console_init(void) { - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; - serial8250_isa_init_ports(); register_console(&serial8250_console); return 0; @@ -3147,8 +3159,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up) mutex_lock(&serial_mutex); uart = serial8250_find_match_or_unused(&up->port); - if (uart) { - uart_remove_one_port(&serial8250_reg, &uart->port); + if (uart && uart->port.type != PORT_8250_CIR) { + if (uart->port.dev) + uart_remove_one_port(&serial8250_reg, &uart->port); uart->port.iobase = up->port.iobase; uart->port.membase = up->port.membase; @@ -3232,8 +3245,7 @@ static int __init serial8250_init(void) { int ret; - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; + serial8250_isa_init_ports(); printk(KERN_INFO "Serial: 8250/16550 driver, " "%d ports, IRQ sharing %sabled\n", nr_uarts, @@ -3248,11 +3260,15 @@ static int __init serial8250_init(void) if (ret) goto out; + ret = serial8250_pnp_init(); + if (ret) + goto unreg_uart_drv; + serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY); if (!serial8250_isa_devs) { ret = -ENOMEM; - goto unreg_uart_drv; + goto unreg_pnp; } ret = platform_device_add(serial8250_isa_devs); @@ -3268,6 +3284,8 @@ static int __init serial8250_init(void) platform_device_del(serial8250_isa_devs); put_dev: platform_device_put(serial8250_isa_devs); +unreg_pnp: + serial8250_pnp_exit(); unreg_uart_drv: #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); @@ -3292,6 +3310,8 @@ static void __exit serial8250_exit(void) platform_driver_unregister(&serial8250_isa_driver); platform_device_unregister(isa_dev); + serial8250_pnp_exit(); + #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); #else |