|
@@ -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);
|
|
|
}
|
|
|
|