diff options
| -rw-r--r-- | drivers/tty/serial/serial_core.c | 31 | ||||
| -rw-r--r-- | include/linux/serial_core.h | 2 | 
2 files changed, 29 insertions, 4 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9d8796e7718..098bb99c2b9 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -610,27 +610,50 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)  static void uart_throttle(struct tty_struct *tty)  {  	struct uart_state *state = tty->driver_data; +	struct uart_port *port = state->uart_port; +	uint32_t mask = 0;  	if (I_IXOFF(tty)) +		mask |= UPF_SOFT_FLOW; +	if (tty->termios.c_cflag & CRTSCTS) +		mask |= UPF_HARD_FLOW; + +	if (port->flags & mask) { +		port->ops->throttle(port); +		mask &= ~port->flags; +	} + +	if (mask & UPF_SOFT_FLOW)  		uart_send_xchar(tty, STOP_CHAR(tty)); -	if (tty->termios.c_cflag & CRTSCTS) -		uart_clear_mctrl(state->uart_port, TIOCM_RTS); +	if (mask & UPF_HARD_FLOW) +		uart_clear_mctrl(port, TIOCM_RTS);  }  static void uart_unthrottle(struct tty_struct *tty)  {  	struct uart_state *state = tty->driver_data;  	struct uart_port *port = state->uart_port; +	uint32_t mask = 0; -	if (I_IXOFF(tty)) { +	if (I_IXOFF(tty)) +		mask |= UPF_SOFT_FLOW; +	if (tty->termios.c_cflag & CRTSCTS) +		mask |= UPF_HARD_FLOW; + +	if (port->flags & mask) { +		port->ops->unthrottle(port); +		mask &= ~port->flags; +	} + +	if (mask & UPF_SOFT_FLOW) {  		if (port->x_char)  			port->x_char = 0;  		else  			uart_send_xchar(tty, START_CHAR(tty));  	} -	if (tty->termios.c_cflag & CRTSCTS) +	if (mask & UPF_HARD_FLOW)  		uart_set_mctrl(port, TIOCM_RTS);  } diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e2cda5d04e4..c6690a2a27f 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -46,6 +46,8 @@ struct uart_ops {  	unsigned int	(*get_mctrl)(struct uart_port *);  	void		(*stop_tx)(struct uart_port *);  	void		(*start_tx)(struct uart_port *); +	void		(*throttle)(struct uart_port *); +	void		(*unthrottle)(struct uart_port *);  	void		(*send_xchar)(struct uart_port *, char ch);  	void		(*stop_rx)(struct uart_port *);  	void		(*enable_ms)(struct uart_port *);  |