Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccce6deb authored by Alan Cox's avatar Alan Cox Committed by Live-CD User
Browse files

serial: move the flags into the tty_port field



Fortunately the serial layer was designed to use the same flag values but
with different names. It has its own SUSPENDED flag which is a free slot in
the ASYNC flags so we allocate it in the ASYNC flags instead.

Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 91312cdb
Loading
Loading
Loading
Loading
+77 −76
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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)
+19 −29
Original line number Diff line number Diff line
@@ -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);
			}
		}
	}