X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_core.c;h=a9ca03ead3e5dc0337b9b7a1eecdf8bb4ce1569a;hb=233607dbbc823caf685e778cabc49fb7f679900b;hp=3bb5d241dd40b2a13424aa42a86acba5ff4b44a3;hpb=434a25d422db13729da14637325875dc64c05faf;p=linux-2.6 diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 3bb5d241dd..a9ca03ead3 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -58,7 +58,8 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios); +static void uart_change_speed(struct uart_state *state, + struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -129,8 +130,8 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) spin_unlock_irqrestore(&port->lock, flags); } -#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0) -#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear) +#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0) +#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear) /* * Startup the port. This will be called once per open. All calls @@ -290,7 +291,7 @@ uart_update_timeout(struct uart_port *port, unsigned int cflag, break; default: bits = 10; - break; // CS8 + break; /* CS8 */ } if (cflag & CSTOPB) @@ -371,7 +372,8 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, */ termios->c_cflag &= ~CBAUD; if (old) { - termios->c_cflag |= old->c_cflag & CBAUD; + baud = tty_termios_baud_rate(old); + tty_termios_encode_baud_rate(termios, baud, baud); old = NULL; continue; } @@ -380,7 +382,7 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, * As a last resort, if the quotient is zero, * default to 9600 bps */ - termios->c_cflag |= B9600; + tty_termios_encode_baud_rate(termios, 9600, 9600); } return 0; @@ -621,7 +623,7 @@ static int uart_get_info(struct uart_state *state, tmp.close_delay = state->close_delay / 10; tmp.closing_wait = state->closing_wait == USF_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : - state->closing_wait / 10; + state->closing_wait / 10; tmp.custom_divisor = port->custom_divisor; tmp.hub6 = port->hub6; tmp.io_type = port->iotype; @@ -787,7 +789,8 @@ static int uart_set_info(struct uart_state *state, * We failed anyway. */ retval = -EBUSY; - goto exit; // Added to return the correct error -Ram Gupta + /* Added to return the correct error -Ram Gupta */ + goto exit; } } @@ -857,7 +860,7 @@ static int uart_get_lsr_info(struct uart_state *state, ((uart_circ_chars_pending(&state->info->xmit) > 0) && !state->info->tty->stopped && !state->info->tty->hw_stopped)) result &= ~TIOCSER_TEMT; - + return put_user(result, value); } @@ -995,8 +998,8 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - ret = 0; - break; + ret = 0; + break; } schedule(); @@ -1136,7 +1139,8 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, return ret; } -static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +static void uart_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) { struct uart_state *state = tty->driver_data; unsigned long flags; @@ -1212,7 +1216,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) { struct uart_state *state = tty->driver_data; struct uart_port *port; - + BUG_ON(!kernel_locked()); if (!state || !state->port) @@ -1277,8 +1281,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uart_shutdown(state); uart_flush_buffer(tty); - tty_ldisc_flush(tty); - + tty_ldisc_flush(tty); + tty->closing = 0; state->info->tty = NULL; @@ -1340,7 +1344,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) expire = jiffies + timeout; pr_debug("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n", - port->line, jiffies, expire); + port->line, jiffies, expire); /* * Check whether the transmitter is empty every 'char_time'. @@ -1459,10 +1463,9 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * have set TTY_IO_ERROR for a non-existant port. */ if ((filp->f_flags & O_NONBLOCK) || - (info->tty->termios->c_cflag & CLOCAL) || - (info->tty->flags & (1 << TTY_IO_ERROR))) { + (info->tty->termios->c_cflag & CLOCAL) || + (info->tty->flags & (1 << TTY_IO_ERROR))) break; - } /* * Set DTR to allow modem to know we're waiting. Do @@ -1550,8 +1553,8 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) } /* - * In 2.4.5, calls to uart_open are serialised by the BKL in - * linux/fs/devices.c:chrdev_open() + * calls to uart_open are serialised by the BKL in + * fs/char_dev.c:chrdev_open() * Note that if this fails, then uart_close() _will_ be called. * * In time, we want to scrap the "opening nonpresent ports" @@ -1673,7 +1676,7 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) port->line, uart_type(port), mmio ? "mmio:0x" : "port:", mmio ? (unsigned long long)port->mapbase - : (unsigned long long) port->iobase, + : (unsigned long long) port->iobase, port->irq); if (port->type == PORT_UNKNOWN) { @@ -1681,8 +1684,7 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) return ret + 1; } - if(capable(CAP_SYS_ADMIN)) - { + if (capable(CAP_SYS_ADMIN)) { mutex_lock(&state->mutex); pm_state = state->pm_state; if (pm_state) @@ -1708,12 +1710,12 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) if (port->icount.overrun) ret += sprintf(buf + ret, " oe:%d", port->icount.overrun); - -#define INFOBIT(bit,str) \ + +#define INFOBIT(bit, str) \ if (port->mctrl & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) -#define STATBIT(bit,str) \ +#define STATBIT(bit, str) \ if (status & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) @@ -1729,7 +1731,7 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) if (stat_buf[0]) stat_buf[0] = ' '; strcat(stat_buf, "\n"); - + ret += sprintf(buf + ret, stat_buf); } else { strcat(buf, "\n"); @@ -1769,7 +1771,7 @@ static int uart_read_proc(char *page, char **start, off_t off, } #endif -#ifdef CONFIG_SERIAL_CORE_CONSOLE +#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) /* * uart_console_write - write a console message to a serial port * @port: the port to write the message @@ -1825,7 +1827,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) * options. The format of the string is , * eg: 115200n8r */ -void __init +void uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) { char *s = options; @@ -1840,6 +1842,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) if (*s) *flow = *s; } +EXPORT_SYMBOL_GPL(uart_parse_options); struct baud_rates { unsigned int rate; @@ -1870,7 +1873,7 @@ static const struct baud_rates baud_rates[] = { * @bits: number of data bits * @flow: flow control character - 'r' (rts) */ -int __init +int uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { @@ -1922,10 +1925,16 @@ uart_set_options(struct uart_port *port, struct console *co, port->mctrl |= TIOCM_DTR; port->ops->set_termios(port, &termios, &dummy); - co->cflag = termios.c_cflag; + /* + * Allow the setting of the UART parameters with a NULL console + * too: + */ + if (co) + co->cflag = termios.c_cflag; return 0; } +EXPORT_SYMBOL_GPL(uart_set_options); #endif /* CONFIG_SERIAL_CORE_CONSOLE */ static void uart_change_pm(struct uart_state *state, int pm_state) @@ -1977,6 +1986,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) if (state->info && state->info->flags & UIF_INITIALIZED) { const struct uart_ops *ops = port->ops; + int tries; state->info->flags = (state->info->flags & ~UIF_INITIALIZED) | UIF_SUSPENDED; @@ -1990,9 +2000,14 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) /* * Wait for the transmitter to empty. */ - while (!ops->tx_empty(port)) { + for (tries = 3; !ops->tx_empty(port) && tries; tries--) msleep(10); - } + if (!tries) + printk(KERN_ERR "%s%s%s%d: Unable to drain " + "transmitter\n", + port->dev ? port->dev->bus_id : "", + port->dev ? ": " : "", + drv->dev_name, port->line); ops->shutdown(port); } @@ -2029,8 +2044,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } port->suspended = 0; - uart_change_pm(state, 0); - /* * Re-enable the console device after suspending. */ @@ -2049,6 +2062,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) if (state->info && state->info->tty && termios.c_cflag == 0) termios = *state->info->tty->termios; + uart_change_pm(state, 0); port->ops->set_termios(port, &termios, NULL); console_start(port->cons); } @@ -2057,6 +2071,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) const struct uart_ops *ops = port->ops; int ret; + uart_change_pm(state, 0); ops->set_mctrl(port, 0); ret = ops->startup(port); if (ret == 0) { @@ -2150,10 +2165,11 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, /* * Ensure that the modem control lines are de-activated. + * keep the DTR setting that is set in uart_set_options() * We probably don't need a spinlock around this, but */ spin_lock_irqsave(&port->lock, flags); - port->ops->set_mctrl(port, 0); + port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR); spin_unlock_irqrestore(&port->lock, flags); /* @@ -2173,6 +2189,60 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, } } +#ifdef CONFIG_CONSOLE_POLL + +static int uart_poll_init(struct tty_driver *driver, int line, char *options) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (!state || !state->port) + return -1; + + port = state->port; + if (!(port->ops->poll_get_char && port->ops->poll_put_char)) + return -1; + + if (options) { + uart_parse_options(options, &baud, &parity, &bits, &flow); + return uart_set_options(port, NULL, baud, parity, bits, flow); + } + + return 0; +} + +static int uart_poll_get_char(struct tty_driver *driver, int line) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->port) + return -1; + + port = state->port; + return port->ops->poll_get_char(port); +} + +static void uart_poll_put_char(struct tty_driver *driver, int line, char ch) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->port) + return; + + port = state->port; + port->ops->poll_put_char(port, ch); +} +#endif + static const struct tty_operations uart_ops = { .open = uart_open, .close = uart_close, @@ -2197,6 +2267,11 @@ static const struct tty_operations uart_ops = { #endif .tiocmget = uart_tiocmget, .tiocmset = uart_tiocmset, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = uart_poll_init, + .poll_get_char = uart_poll_get_char, + .poll_put_char = uart_poll_put_char, +#endif }; /** @@ -2347,7 +2422,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) */ tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev); if (likely(!IS_ERR(tty_dev))) { - device_can_wakeup(tty_dev) = 1; + device_init_wakeup(tty_dev, 1); device_set_wakeup_enable(tty_dev, 0); } else printk(KERN_ERR "Cannot register tty device on line %d\n",