diff options
-rw-r--r-- | drivers/serial/serial_core.c | 153 | ||||
-rw-r--r-- | include/linux/serial.h | 2 | ||||
-rw-r--r-- | include/linux/serial_core.h | 48 |
3 files changed, 98 insertions, 105 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 4af3364dd811..744dec9301fb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -29,10 +29,10 @@ #include <linux/console.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <linux/serial_core.h> #include <linux/smp_lock.h> #include <linux/device.h> #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ +#include <linux/serial_core.h> #include <linux/delay.h> #include <linux/mutex.h> @@ -146,7 +146,7 @@ static int uart_startup(struct uart_state *state, int init_hw) unsigned long page; int retval = 0; - if (state->flags & UIF_INITIALIZED) + if (port->flags & ASYNC_INITIALIZED) return 0; /* @@ -189,14 +189,14 @@ static int uart_startup(struct uart_state *state, int init_hw) uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } - if (state->flags & UIF_CTS_FLOW) { + if (port->flags & ASYNC_CTS_FLOW) { spin_lock_irq(&uport->lock); if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) port->tty->hw_stopped = 1; spin_unlock_irq(&uport->lock); } - state->flags |= UIF_INITIALIZED; + set_bit(ASYNCB_INITIALIZED, &port->flags); clear_bit(TTY_IO_ERROR, &port->tty->flags); } @@ -214,7 +214,7 @@ static int uart_startup(struct uart_state *state, int init_hw) */ static void uart_shutdown(struct uart_state *state) { - struct uart_port *port = state->uart_port; + struct uart_port *uport = state->uart_port; struct tty_struct *tty = state->port.tty; /* @@ -223,14 +223,12 @@ static void uart_shutdown(struct uart_state *state) if (tty) set_bit(TTY_IO_ERROR, &tty->flags); - if (state->flags & UIF_INITIALIZED) { - state->flags &= ~UIF_INITIALIZED; - + if (test_and_clear_bit(ASYNCB_INITIALIZED, &state->port.flags)) { /* * Turn off DTR and RTS early. */ if (!tty || (tty->termios->c_cflag & HUPCL)) - uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); + uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); /* * clear delta_msr_wait queue to avoid mem leaks: we may free @@ -244,12 +242,12 @@ static void uart_shutdown(struct uart_state *state) /* * Free the IRQ and disable the port. */ - port->ops->shutdown(port); + uport->ops->shutdown(uport); /* * Ensure that the IRQ handler isn't running on another CPU. */ - synchronize_irq(port->irq); + synchronize_irq(uport->irq); } /* @@ -429,15 +427,16 @@ EXPORT_SYMBOL(uart_get_divisor); static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { - struct tty_struct *tty = state->port.tty; - struct uart_port *port = state->uart_port; + struct tty_port *port = &state->port; + struct tty_struct *tty = port->tty; + struct uart_port *uport = state->uart_port; struct ktermios *termios; /* * If we have no tty, termios, or the port does not exist, * then we can't set the parameters for this port. */ - if (!tty || !tty->termios || port->type == PORT_UNKNOWN) + if (!tty || !tty->termios || uport->type == PORT_UNKNOWN) return; termios = tty->termios; @@ -446,16 +445,16 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) * Set flags based on termios cflag */ if (termios->c_cflag & CRTSCTS) - state->flags |= UIF_CTS_FLOW; + set_bit(ASYNCB_CTS_FLOW, &port->flags); else - state->flags &= ~UIF_CTS_FLOW; + clear_bit(ASYNCB_CTS_FLOW, &port->flags); if (termios->c_cflag & CLOCAL) - state->flags &= ~UIF_CHECK_CD; + clear_bit(ASYNCB_CHECK_CD, &port->flags); else - state->flags |= UIF_CHECK_CD; + set_bit(ASYNCB_CHECK_CD, &port->flags); - port->ops->set_termios(port, termios, old_termios); + uport->ops->set_termios(uport, termios, old_termios); } static inline int @@ -848,7 +847,7 @@ static int uart_set_info(struct uart_state *state, retval = 0; if (uport->type == PORT_UNKNOWN) goto exit; - if (state->flags & UIF_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { if (((old_flags ^ uport->flags) & UPF_SPD_MASK) || old_custom_divisor != uport->custom_divisor) { /* @@ -1306,7 +1305,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * At this point, we stop accepting input. To do this, we * disable the receive line status interrupts. */ - if (state->flags & UIF_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { unsigned long flags; spin_lock_irqsave(&port->lock, flags); uport->ops->stop_rx(uport); @@ -1337,7 +1336,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) /* * Wake up anyone trying to open this port. */ - state->flags &= ~UIF_NORMAL_ACTIVE; + clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); wake_up_interruptible(&port->open_wait); done: @@ -1418,11 +1417,11 @@ static void uart_hangup(struct tty_struct *tty) pr_debug("uart_hangup(%d)\n", state->uart_port->line); mutex_lock(&state->mutex); - if (state->flags & UIF_NORMAL_ACTIVE) { + if (port->flags & ASYNC_NORMAL_ACTIVE) { uart_flush_buffer(tty); uart_shutdown(state); port->count = 0; - state->flags &= ~UIF_NORMAL_ACTIVE; + clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); port->tty = NULL; wake_up_interruptible(&port->open_wait); wake_up_interruptible(&state->delta_msr_wait); @@ -1493,7 +1492,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) /* * If the port has been closed, tell userspace/restart open. */ - if (!(state->flags & UIF_INITIALIZED)) + if (!(port->flags & ASYNC_INITIALIZED)) break; /* @@ -1662,8 +1661,8 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If this is the first open to succeed, adjust things to suit. */ - if (retval == 0 && !(state->flags & UIF_NORMAL_ACTIVE)) { - state->flags |= UIF_NORMAL_ACTIVE; + if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { + set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); uart_update_termios(state); } @@ -1985,63 +1984,64 @@ static int serial_match_port(struct device *dev, void *data) return dev->devt == devt; /* Actually, only one tty per port */ } -int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) +int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) { - struct uart_state *state = drv->state + port->line; + struct uart_state *state = drv->state + uport->line; + struct tty_port *port = &state->port; struct device *tty_dev; - struct uart_match match = {port, drv}; + struct uart_match match = {uport, drv}; mutex_lock(&state->mutex); - if (!console_suspend_enabled && uart_console(port)) { + if (!console_suspend_enabled && uart_console(uport)) { /* we're going to avoid suspending serial console */ mutex_unlock(&state->mutex); return 0; } - tty_dev = device_find_child(port->dev, &match, serial_match_port); + tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (device_may_wakeup(tty_dev)) { - enable_irq_wake(port->irq); + enable_irq_wake(uport->irq); put_device(tty_dev); mutex_unlock(&state->mutex); return 0; } - port->suspended = 1; + uport->suspended = 1; - if (state->flags & UIF_INITIALIZED) { - const struct uart_ops *ops = port->ops; + if (port->flags & ASYNC_INITIALIZED) { + const struct uart_ops *ops = uport->ops; int tries; - state->flags = (state->flags & ~UIF_INITIALIZED) - | UIF_SUSPENDED; + set_bit(ASYNCB_SUSPENDED, &port->flags); + clear_bit(ASYNCB_INITIALIZED, &port->flags); - spin_lock_irq(&port->lock); - ops->stop_tx(port); - ops->set_mctrl(port, 0); - ops->stop_rx(port); - spin_unlock_irq(&port->lock); + spin_lock_irq(&uport->lock); + ops->stop_tx(uport); + ops->set_mctrl(uport, 0); + ops->stop_rx(uport); + spin_unlock_irq(&uport->lock); /* * Wait for the transmitter to empty. */ - for (tries = 3; !ops->tx_empty(port) && tries; tries--) + for (tries = 3; !ops->tx_empty(uport) && tries; tries--) msleep(10); if (!tries) printk(KERN_ERR "%s%s%s%d: Unable to drain " "transmitter\n", - port->dev ? dev_name(port->dev) : "", - port->dev ? ": " : "", + uport->dev ? dev_name(uport->dev) : "", + uport->dev ? ": " : "", drv->dev_name, - drv->tty_driver->name_base + port->line); + drv->tty_driver->name_base + uport->line); - ops->shutdown(port); + ops->shutdown(uport); } /* * Disable the console device before suspending. */ - if (uart_console(port)) - console_stop(port->cons); + if (uart_console(uport)) + console_stop(uport->cons); uart_change_pm(state, 3); @@ -2050,67 +2050,68 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) return 0; } -int uart_resume_port(struct uart_driver *drv, struct uart_port *port) +int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) { - struct uart_state *state = drv->state + port->line; + struct uart_state *state = drv->state + uport->line; + struct tty_port *port = &state->port; struct device *tty_dev; - struct uart_match match = {port, drv}; + struct uart_match match = {uport, drv}; mutex_lock(&state->mutex); - if (!console_suspend_enabled && uart_console(port)) { + if (!console_suspend_enabled && uart_console(uport)) { /* no need to resume serial console, it wasn't suspended */ mutex_unlock(&state->mutex); return 0; } - tty_dev = device_find_child(port->dev, &match, serial_match_port); - if (!port->suspended && device_may_wakeup(tty_dev)) { - disable_irq_wake(port->irq); + tty_dev = device_find_child(uport->dev, &match, serial_match_port); + if (!uport->suspended && device_may_wakeup(tty_dev)) { + disable_irq_wake(uport->irq); mutex_unlock(&state->mutex); return 0; } - port->suspended = 0; + uport->suspended = 0; /* * Re-enable the console device after suspending. */ - if (uart_console(port)) { + if (uart_console(uport)) { struct ktermios termios; /* * First try to use the console cflag setting. */ memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = port->cons->cflag; + termios.c_cflag = uport->cons->cflag; /* * If that's unset, use the tty termios setting. */ - if (state->port.tty && termios.c_cflag == 0) - termios = *state->port.tty->termios; + if (port->tty && termios.c_cflag == 0) + termios = *port->tty->termios; uart_change_pm(state, 0); - port->ops->set_termios(port, &termios, NULL); - console_start(port->cons); + uport->ops->set_termios(uport, &termios, NULL); + console_start(uport->cons); } - if (state->flags & UIF_SUSPENDED) { - const struct uart_ops *ops = port->ops; + if (port->flags & ASYNC_SUSPENDED) { + const struct uart_ops *ops = uport->ops; int ret; uart_change_pm(state, 0); - spin_lock_irq(&port->lock); - ops->set_mctrl(port, 0); - spin_unlock_irq(&port->lock); - ret = ops->startup(port); + spin_lock_irq(&uport->lock); + ops->set_mctrl(uport, 0); + spin_unlock_irq(&uport->lock); + ret = ops->startup(uport); if (ret == 0) { uart_change_speed(state, NULL); - spin_lock_irq(&port->lock); - ops->set_mctrl(port, port->mctrl); - ops->start_tx(port); - spin_unlock_irq(&port->lock); - state->flags |= UIF_INITIALIZED; + spin_lock_irq(&uport->lock); + ops->set_mctrl(uport, uport->mctrl); + ops->start_tx(uport); + spin_unlock_irq(&uport->lock); + set_bit(ASYNCB_INITIALIZED, &port->flags); } else { /* * Failed to resume - maybe hardware went away? @@ -2120,7 +2121,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) uart_shutdown(state); } - state->flags &= ~UIF_SUSPENDED; + clear_bit(ASYNCB_SUSPENDED, &port->flags); } mutex_unlock(&state->mutex); diff --git a/include/linux/serial.h b/include/linux/serial.h index e5bb75a63802..c8613c3ff9d3 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -122,6 +122,7 @@ struct serial_uart_config { /* Internal flags used only by kernel */ #define ASYNCB_INITIALIZED 31 /* Serial port was initialized */ +#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */ #define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */ #define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */ #define ASYNCB_CLOSING 27 /* Serial port is closing */ @@ -133,6 +134,7 @@ struct serial_uart_config { #define ASYNCB_FIRST_KERNEL 22 #define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY) +#define ASYNC_SUSPENDED (1U << ASYNCB_SUSPENDED) #define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT) #define ASYNC_SAK (1U << ASYNCB_SAK) #define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 63ad90966db2..284ef7f54890 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -20,6 +20,8 @@ #ifndef LINUX_SERIAL_CORE_H #define LINUX_SERIAL_CORE_H +#include <linux/serial.h> + /* * The type definitions. These are from Ted Ts'o's serial.h */ @@ -356,19 +358,6 @@ struct uart_state { int pm_state; struct circ_buf xmit; - uif_t flags; - -/* - * Definitions for info->flags. These are _private_ to serial_core, and - * are specific to this structure. They may be queried by low level drivers. - * - * FIXME: use the ASY_ definitions - */ -#define UIF_CHECK_CD ((__force uif_t) (1 << 25)) -#define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) -#define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) -#define UIF_INITIALIZED ((__force uif_t) (1 << 31)) -#define UIF_SUSPENDED ((__force uif_t) (1 << 30)) struct tasklet_struct tlet; wait_queue_head_t delta_msr_wait; @@ -509,22 +498,23 @@ static inline int uart_handle_break(struct uart_port *port) * @status: new carrier detect status, nonzero if active */ static inline void -uart_handle_dcd_change(struct uart_port *port, unsigned int status) +uart_handle_dcd_change(struct uart_port *uport, unsigned int status) { - struct uart_state *state = port->state; + struct uart_state *state = uport->state; + struct tty_port *port = &state->port; - port->icount.dcd++; + uport->icount.dcd++; #ifdef CONFIG_HARD_PPS - if ((port->flags & UPF_HARDPPS_CD) && status) + if ((uport->flags & UPF_HARDPPS_CD) && status) hardpps(); #endif - if (state->flags & UIF_CHECK_CD) { + if (port->flags & ASYNC_CHECK_CD) { if (status) - wake_up_interruptible(&state->port.open_wait); - else if (state->port.tty) - tty_hangup(state->port.tty); + wake_up_interruptible(&port->open_wait); + else if (port->tty) + tty_hangup(port->tty); } } @@ -534,24 +524,24 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) * @status: new clear to send status, nonzero if active */ static inline void -uart_handle_cts_change(struct uart_port *port, unsigned int status) +uart_handle_cts_change(struct uart_port *uport, unsigned int status) { - struct uart_state *state = port->state; - struct tty_struct *tty = state->port.tty; + struct tty_port *port = &uport->state->port; + struct tty_struct *tty = port->tty; - port->icount.cts++; + uport->icount.cts++; - if (state->flags & UIF_CTS_FLOW) { + if (port->flags & ASYNC_CTS_FLOW) { if (tty->hw_stopped) { if (status) { tty->hw_stopped = 0; - port->ops->start_tx(port); - uart_write_wakeup(port); + uport->ops->start_tx(uport); + uart_write_wakeup(uport); } } else { if (!status) { tty->hw_stopped = 1; - port->ops->stop_tx(port); + uport->ops->stop_tx(uport); } } } |