#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>
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-#define uart_users(state) ((state)->count + (state)->port.blocked_open)
-
#ifdef CONFIG_SERIAL_CORE_CONSOLE
#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
#else
unsigned long page;
int retval = 0;
- if (state->flags & UIF_INITIALIZED)
+ if (port->flags & ASYNC_INITIALIZED)
return 0;
/*
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);
}
*/
static void uart_shutdown(struct uart_state *state)
{
- struct uart_port *port = state->uart_port;
- struct tty_struct *tty = state->port.tty;
+ struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
+ struct tty_struct *tty = port->tty;
/*
* Set the TTY IO error marker
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, &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
* any outstanding file descriptors should be pointing at
* hung_up_tty_fops now.
*/
- wake_up_interruptible(&state->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
/*
* 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);
}
/*
if (flags == UPF_SPD_HI)
altbaud = 57600;
- if (flags == UPF_SPD_VHI)
+ else if (flags == UPF_SPD_VHI)
altbaud = 115200;
- if (flags == UPF_SPD_SHI)
+ else if (flags == UPF_SPD_SHI)
altbaud = 230400;
- if (flags == UPF_SPD_WARP)
+ else if (flags == UPF_SPD_WARP)
altbaud = 460800;
for (try = 0; try < 2; try++) {
}
/*
- * As a last resort, if the quotient is zero,
- * default to 9600 bps
+ * As a last resort, if the range cannot be met then clip to
+ * the nearest chip supported rate.
*/
- if (!hung_up)
- tty_termios_encode_baud_rate(termios, 9600, 9600);
+ if (!hung_up) {
+ if (baud <= min)
+ tty_termios_encode_baud_rate(termios,
+ min + 1, min + 1);
+ else
+ tty_termios_encode_baud_rate(termios,
+ max - 1, max - 1);
+ }
}
-
+ /* Should never happen */
+ WARN_ON(1);
return 0;
}
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;
* 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
static int uart_get_info(struct uart_state *state,
struct serial_struct __user *retinfo)
{
- struct uart_port *port = state->uart_port;
+ struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
struct serial_struct tmp;
memset(&tmp, 0, sizeof(tmp));
/* Ensure the state we copy is consistent and no hardware changes
occur as we go */
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
- tmp.type = port->type;
- tmp.line = port->line;
- tmp.port = port->iobase;
+ tmp.type = uport->type;
+ tmp.line = uport->line;
+ tmp.port = uport->iobase;
if (HIGH_BITS_OFFSET)
- tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
- tmp.irq = port->irq;
- tmp.flags = port->flags;
- tmp.xmit_fifo_size = port->fifosize;
- tmp.baud_base = port->uartclk / 16;
- tmp.close_delay = state->port.close_delay / 10;
- tmp.closing_wait = state->port.closing_wait == USF_CLOSING_WAIT_NONE ?
+ tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET;
+ tmp.irq = uport->irq;
+ tmp.flags = uport->flags;
+ tmp.xmit_fifo_size = uport->fifosize;
+ tmp.baud_base = uport->uartclk / 16;
+ tmp.close_delay = port->close_delay / 10;
+ tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
- state->port.closing_wait / 10;
- tmp.custom_divisor = port->custom_divisor;
- tmp.hub6 = port->hub6;
- tmp.io_type = port->iotype;
- tmp.iomem_reg_shift = port->regshift;
- tmp.iomem_base = (void *)(unsigned long)port->mapbase;
+ port->closing_wait / 10;
+ tmp.custom_divisor = uport->custom_divisor;
+ tmp.hub6 = uport->hub6;
+ tmp.io_type = uport->iotype;
+ tmp.iomem_reg_shift = uport->regshift;
+ tmp.iomem_base = (void *)(unsigned long)uport->mapbase;
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
new_serial.irq = irq_canonicalize(new_serial.irq);
close_delay = new_serial.close_delay * 10;
closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
- USF_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+ ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
/*
- * This semaphore protects state->count. It is also
+ * This semaphore protects port->count. It is also
* very useful to prevent opens. Also, take the
* port configuration semaphore to make sure that a
* module insertion/removal doesn't change anything
* under us.
*/
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
change_irq = !(uport->flags & UPF_FIXED_PORT)
&& new_serial.irq != uport->irq;
/*
* Make sure that we are the sole user of this port.
*/
- if (uart_users(state) > 1)
+ if (tty_port_users(port) > 1)
goto exit;
/*
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) {
/*
} else
retval = uart_startup(state, 1);
exit:
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return retval;
}
static int uart_tiocmget(struct tty_struct *tty, struct file *file)
{
struct uart_state *state = tty->driver_data;
+ struct tty_port *port = &state->port;
struct uart_port *uport = state->uart_port;
int result = -EIO;
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
result = uport->mctrl;
result |= uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
}
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return result;
}
{
struct uart_state *state = tty->driver_data;
struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
int ret = -EIO;
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
uart_update_mctrl(uport, set, clear);
ret = 0;
}
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return ret;
}
static int uart_break_ctl(struct tty_struct *tty, int break_state)
{
struct uart_state *state = tty->driver_data;
+ struct tty_port *port = &state->port;
struct uart_port *uport = state->uart_port;
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if (uport->type != PORT_UNKNOWN)
uport->ops->break_ctl(uport, break_state);
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return 0;
}
static int uart_do_autoconfig(struct uart_state *state)
{
struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
int flags, ret;
if (!capable(CAP_SYS_ADMIN))
* changing, and hence any extra opens of the port while
* we're auto-configuring.
*/
- if (mutex_lock_interruptible(&state->mutex))
+ if (mutex_lock_interruptible(&port->mutex))
return -ERESTARTSYS;
ret = -EBUSY;
- if (uart_users(state) == 1) {
+ if (tty_port_users(port) == 1) {
uart_shutdown(state);
/*
ret = uart_startup(state, 1);
}
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return ret;
}
* - mask passed in arg for lines of interest
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
* Caller should use TIOCGICOUNT to see which one it was
+ *
+ * FIXME: This wants extracting into a common all driver implementation
+ * of TIOCMWAIT using tty_port.
*/
static int
uart_wait_modem_status(struct uart_state *state, unsigned long arg)
{
struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
DECLARE_WAITQUEUE(wait, current);
struct uart_icount cprev, cnow;
int ret;
uport->ops->enable_ms(uport);
spin_unlock_irq(&uport->lock);
- add_wait_queue(&state->delta_msr_wait, &wait);
+ add_wait_queue(&port->delta_msr_wait, &wait);
for (;;) {
spin_lock_irq(&uport->lock);
memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
}
current->state = TASK_RUNNING;
- remove_wait_queue(&state->delta_msr_wait, &wait);
+ remove_wait_queue(&port->delta_msr_wait, &wait);
return ret;
}
unsigned long arg)
{
struct uart_state *state = tty->driver_data;
+ struct tty_port *port = &state->port;
void __user *uarg = (void __user *)arg;
int ret = -ENOIOCTLCMD;
if (ret != -ENOIOCTLCMD)
goto out;
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if (tty_hung_up_p(filp)) {
ret = -EIO;
}
}
out_up:
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
out:
return ret;
}
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
-
/* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
unsigned int mask = TIOCM_DTR;
if (!(cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags))
__uart_start(tty);
spin_unlock_irqrestore(&state->uart_port->lock, flags);
}
-
/* Handle turning on CRTSCTS */
- if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+ else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
spin_lock_irqsave(&state->uart_port->lock, flags);
if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
tty->hw_stopped = 1;
BUG_ON(!kernel_locked());
+ if (!state)
+ return;
+
uport = state->uart_port;
port = &state->port;
pr_debug("uart_close(%d) called\n", uport->line);
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if (tty_hung_up_p(filp))
goto done;
- if ((tty->count == 1) && (state->count != 1)) {
+ if ((tty->count == 1) && (port->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
+ * structure will be freed. port->count should always
* be one in these conditions. If it's greater than
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
+ "port->count is %d\n", port->count);
+ port->count = 1;
}
- if (--state->count < 0) {
+ if (--port->count < 0) {
printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n",
- tty->name, state->count);
- state->count = 0;
+ tty->name, port->count);
+ port->count = 0;
}
- if (state->count)
+ if (port->count)
goto done;
/*
*/
tty->closing = 1;
- if (port->closing_wait != USF_CLOSING_WAIT_NONE)
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait));
/*
* 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);
+ spin_lock_irqsave(&uport->lock, flags);
uport->ops->stop_rx(uport);
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irqrestore(&uport->lock, flags);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
tty_ldisc_flush(tty);
tty->closing = 0;
- port->tty = NULL;
+ tty_port_tty_set(port, NULL);
if (port->blocked_open) {
if (port->close_delay)
/*
* 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:
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
BUG_ON(!kernel_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line);
- mutex_lock(&state->mutex);
- if (state->flags & UIF_NORMAL_ACTIVE) {
+ mutex_lock(&port->mutex);
+ if (port->flags & ASYNC_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
- state->count = 0;
- state->flags &= ~UIF_NORMAL_ACTIVE;
- port->tty = NULL;
+ port->count = 0;
+ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+ tty_port_tty_set(port, NULL);
wake_up_interruptible(&port->open_wait);
- wake_up_interruptible(&state->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
}
/*
unsigned int mctrl;
port->blocked_open++;
- state->count--;
+ port->count--;
add_wait_queue(&port->open_wait, &wait);
while (1) {
/*
* If the port has been closed, tell userspace/restart open.
*/
- if (!(state->flags & UIF_INITIALIZED))
+ if (!(port->flags & ASYNC_INITIALIZED))
break;
/*
if (mctrl & TIOCM_CAR)
break;
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
schedule();
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if (signal_pending(current))
break;
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
- state->count++;
+ port->count++;
port->blocked_open--;
if (signal_pending(current))
static struct uart_state *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state;
+ struct tty_port *port;
int ret = 0;
state = drv->state + line;
- if (mutex_lock_interruptible(&state->mutex)) {
+ port = &state->port;
+ if (mutex_lock_interruptible(&port->mutex)) {
ret = -ERESTARTSYS;
goto err;
}
- state->count++;
+ port->count++;
if (!state->uart_port || state->uart_port->flags & UPF_DEAD) {
ret = -ENXIO;
goto err_unlock;
return state;
err_unlock:
- state->count--;
- mutex_unlock(&state->mutex);
+ port->count--;
+ mutex_unlock(&port->mutex);
err:
return ERR_PTR(ret);
}
{
struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
struct uart_state *state;
+ struct tty_port *port;
int retval, line = tty->index;
BUG_ON(!kernel_locked());
retval = PTR_ERR(state);
goto fail;
}
+ port = &state->port;
/*
* Once we set tty->driver_data here, we are guaranteed that
state->uart_port->state = state;
tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
tty->alt_speed = 0;
- state->port.tty = tty;
+ tty_port_tty_set(port, tty);
/*
* If the port is in the middle of closing, bail out now.
*/
if (tty_hung_up_p(filp)) {
retval = -EAGAIN;
- state->count--;
- mutex_unlock(&state->mutex);
+ port->count--;
+ mutex_unlock(&port->mutex);
goto fail;
}
/*
* Make sure the device is in D0 state.
*/
- if (state->count == 1)
+ if (port->count == 1)
uart_change_pm(state, 0);
/*
*/
if (retval == 0)
retval = uart_block_til_ready(filp, state);
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
/*
* 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);
}
- fail:
+fail:
return retval;
}
static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
{
struct uart_state *state = drv->state + i;
+ struct tty_port *port = &state->port;
int pm_state;
- struct uart_port *port = state->uart_port;
+ struct uart_port *uport = state->uart_port;
char stat_buf[32];
unsigned int status;
int mmio;
- if (!port)
+ if (!uport)
return;
- mmio = port->iotype >= UPIO_MEM;
+ mmio = uport->iotype >= UPIO_MEM;
seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
- port->line, uart_type(port),
+ uport->line, uart_type(uport),
mmio ? "mmio:0x" : "port:",
- mmio ? (unsigned long long)port->mapbase
- : (unsigned long long) port->iobase,
- port->irq);
+ mmio ? (unsigned long long)uport->mapbase
+ : (unsigned long long)uport->iobase,
+ uport->irq);
- if (port->type == PORT_UNKNOWN) {
+ if (uport->type == PORT_UNKNOWN) {
seq_putc(m, '\n');
return;
}
if (capable(CAP_SYS_ADMIN)) {
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
pm_state = state->pm_state;
if (pm_state)
uart_change_pm(state, 0);
- spin_lock_irq(&port->lock);
- status = port->ops->get_mctrl(port);
- spin_unlock_irq(&port->lock);
+ spin_lock_irq(&uport->lock);
+ status = uport->ops->get_mctrl(uport);
+ spin_unlock_irq(&uport->lock);
if (pm_state)
uart_change_pm(state, pm_state);
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
seq_printf(m, " tx:%d rx:%d",
- port->icount.tx, port->icount.rx);
- if (port->icount.frame)
+ uport->icount.tx, uport->icount.rx);
+ if (uport->icount.frame)
seq_printf(m, " fe:%d",
- port->icount.frame);
- if (port->icount.parity)
+ uport->icount.frame);
+ if (uport->icount.parity)
seq_printf(m, " pe:%d",
- port->icount.parity);
- if (port->icount.brk)
+ uport->icount.parity);
+ if (uport->icount.brk)
seq_printf(m, " brk:%d",
- port->icount.brk);
- if (port->icount.overrun)
+ uport->icount.brk);
+ if (uport->icount.overrun)
seq_printf(m, " oe:%d",
- port->icount.overrun);
+ uport->icount.overrun);
#define INFOBIT(bit, str) \
- if (port->mctrl & (bit)) \
+ if (uport->mctrl & (bit)) \
strncat(stat_buf, (str), sizeof(stat_buf) - \
strlen(stat_buf) - 2)
#define STATBIT(bit, str) \
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);
+ mutex_lock(&port->mutex);
- if (!console_suspend_enabled && uart_console(port)) {
- /* 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);
+ mutex_unlock(&port->mutex);
return 0;
}
- port->suspended = 1;
+ if (console_suspend_enabled || !uart_console(uport))
+ 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;
+ if (console_suspend_enabled || !uart_console(uport)) {
+ 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);
+ if (console_suspend_enabled || !uart_console(uport))
+ ops->shutdown(uport);
}
/*
* Disable the console device before suspending.
*/
- if (uart_console(port))
- console_stop(port->cons);
+ if (console_suspend_enabled && uart_console(uport))
+ console_stop(uport->cons);
- uart_change_pm(state, 3);
+ if (console_suspend_enabled || !uart_console(uport))
+ uart_change_pm(state, 3);
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
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};
-
- mutex_lock(&state->mutex);
+ struct uart_match match = {uport, drv};
+ struct ktermios termios;
- if (!console_suspend_enabled && uart_console(port)) {
- /* no need to resume serial console, it wasn't suspended */
- mutex_unlock(&state->mutex);
- return 0;
- }
+ mutex_lock(&port->mutex);
- tty_dev = device_find_child(port->dev, &match, serial_match_port);
- if (!port->suspended && device_may_wakeup(tty_dev)) {
- disable_irq_wake(port->irq);
- mutex_unlock(&state->mutex);
+ 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(&port->mutex);
return 0;
}
- port->suspended = 0;
+ uport->suspended = 0;
/*
* Re-enable the console device after suspending.
*/
- if (uart_console(port)) {
- struct ktermios termios;
-
- /*
- * First try to use the console cflag setting.
- */
- memset(&termios, 0, sizeof(struct ktermios));
- termios.c_cflag = port->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 (uart_console(uport)) {
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);
- 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;
- } else {
- /*
- * Failed to resume - maybe hardware went away?
- * Clear the "initialized" flag so we won't try
- * to call the low level drivers shutdown method.
- */
- uart_shutdown(state);
+ spin_lock_irq(&uport->lock);
+ ops->set_mctrl(uport, 0);
+ spin_unlock_irq(&uport->lock);
+ if (console_suspend_enabled || !uart_console(uport)) {
+ ret = ops->startup(uport);
+ if (ret == 0) {
+ uart_change_speed(state, NULL);
+ 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?
+ * Clear the "initialized" flag so we won't try
+ * to call the low level drivers shutdown method.
+ */
+ uart_shutdown(state);
+ }
}
- state->flags &= ~UIF_SUSPENDED;
+ clear_bit(ASYNCB_SUSPENDED, &port->flags);
}
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
return 0;
}
*/
int uart_register_driver(struct uart_driver *drv)
{
- struct tty_driver *normal = NULL;
+ struct tty_driver *normal;
int i, retval;
BUG_ON(drv->state);
* we have a large number of ports to handle.
*/
drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
- retval = -ENOMEM;
if (!drv->state)
goto out;
- normal = alloc_tty_driver(drv->nr);
+ normal = alloc_tty_driver(drv->nr);
if (!normal)
- goto out;
+ goto out_kfree;
drv->tty_driver = normal;
*/
for (i = 0; i < drv->nr; i++) {
struct uart_state *state = drv->state + i;
+ struct tty_port *port = &state->port;
- mutex_init(&state->mutex);
-
- tty_port_init(&state->port);
- state->port.close_delay = 500; /* .5 seconds */
- state->port.closing_wait = 30000; /* 30 seconds */
- init_waitqueue_head(&state->delta_msr_wait);
+ tty_port_init(port);
+ port->close_delay = 500; /* .5 seconds */
+ port->closing_wait = 30000; /* 30 seconds */
tasklet_init(&state->tlet, uart_tasklet_action,
(unsigned long)state);
}
retval = tty_register_driver(normal);
- out:
- if (retval < 0) {
- put_tty_driver(normal);
- kfree(drv->state);
- }
- return retval;
+ if (retval >= 0)
+ return retval;
+
+ put_tty_driver(normal);
+out_kfree:
+ kfree(drv->state);
+out:
+ return -ENOMEM;
}
/**
/**
* uart_add_one_port - attach a driver-defined port structure
* @drv: pointer to the uart low level driver structure for this port
- * @port: uart port structure to use for this port.
+ * @uport: uart port structure to use for this port.
*
* This allows the driver to register its own uart_port structure
* with the core driver. The main purpose is to allow the low
* level uart drivers to expand uart_port, rather than having yet
* more levels of structures.
*/
-int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
{
struct uart_state *state;
+ struct tty_port *port;
int ret = 0;
struct device *tty_dev;
BUG_ON(in_interrupt());
- if (port->line >= drv->nr)
+ if (uport->line >= drv->nr)
return -EINVAL;
- state = drv->state + port->line;
+ state = drv->state + uport->line;
+ port = &state->port;
mutex_lock(&port_mutex);
- mutex_lock(&state->mutex);
+ mutex_lock(&port->mutex);
if (state->uart_port) {
ret = -EINVAL;
goto out;
}
- state->uart_port = port;
+ state->uart_port = uport;
state->pm_state = -1;
- port->cons = drv->cons;
- port->state = state;
+ uport->cons = drv->cons;
+ uport->state = state;
/*
* If this port is a console, then the spinlock is already
* initialised.
*/
- if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
- spin_lock_init(&port->lock);
- lockdep_set_class(&port->lock, &port_lock_key);
+ if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
+ spin_lock_init(&uport->lock);
+ lockdep_set_class(&uport->lock, &port_lock_key);
}
- uart_configure_port(drv, state, port);
+ uart_configure_port(drv, state, uport);
/*
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
- tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
+ tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
if (likely(!IS_ERR(tty_dev))) {
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",
- port->line);
+ uport->line);
/*
* Ensure UPF_DEAD is not set.
*/
- port->flags &= ~UPF_DEAD;
+ uport->flags &= ~UPF_DEAD;
out:
- mutex_unlock(&state->mutex);
+ mutex_unlock(&port->mutex);
mutex_unlock(&port_mutex);
return ret;
/**
* uart_remove_one_port - detach a driver defined port structure
* @drv: pointer to the uart low level driver structure for this port
- * @port: uart port structure for this port
+ * @uport: uart port structure for this port
*
* This unhooks (and hangs up) the specified port structure from the
* core driver. No further calls will be made to the low-level code
* for this port.
*/
-int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
+int uart_remove_one_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;
BUG_ON(in_interrupt());
- if (state->uart_port != port)
+ if (state->uart_port != uport)
printk(KERN_ALERT "Removing wrong port: %p != %p\n",
- state->uart_port, port);
+ state->uart_port, uport);
mutex_lock(&port_mutex);
* Mark the port "dead" - this prevents any opens from
* succeeding while we shut down the port.
*/
- mutex_lock(&state->mutex);
- port->flags |= UPF_DEAD;
- mutex_unlock(&state->mutex);
+ mutex_lock(&port->mutex);
+ uport->flags |= UPF_DEAD;
+ mutex_unlock(&port->mutex);
/*
* Remove the devices from the tty layer
*/
- tty_unregister_device(drv->tty_driver, port->line);
+ tty_unregister_device(drv->tty_driver, uport->line);
- if (state->port.tty)
- tty_vhangup(state->port.tty);
+ if (port->tty)
+ tty_vhangup(port->tty);
/*
* Free the port IO and memory resources, if any.
*/
- if (port->type != PORT_UNKNOWN)
- port->ops->release_port(port);
+ if (uport->type != PORT_UNKNOWN)
+ uport->ops->release_port(uport);
/*
* Indicate that there isn't a port here anymore.
*/
- port->type = PORT_UNKNOWN;
+ uport->type = PORT_UNKNOWN;
/*
* Kill the tasklet, and free resources.