Commit 9aba8d5b authored by Russell King's avatar Russell King

SERIAL: core: add throttle/unthrottle callbacks for hardware assisted flow control

Add two callbacks for hardware assisted flow control; we need to know
when the tty layers want us to stop and restart due to their buffer
levels.

Call a driver specific throttle/unthrottle function if and only if the
driver indicates that it is using an enabled hardware assisted flow
control method, otherwise fall back to the non-hardware assisted
methods.
Acked-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent dba05832
...@@ -610,27 +610,50 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) ...@@ -610,27 +610,50 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
static void uart_throttle(struct tty_struct *tty) static void uart_throttle(struct tty_struct *tty)
{ {
struct uart_state *state = tty->driver_data; 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->throttle(port);
mask &= ~port->flags;
}
if (mask & UPF_SOFT_FLOW)
uart_send_xchar(tty, STOP_CHAR(tty)); uart_send_xchar(tty, STOP_CHAR(tty));
if (tty->termios.c_cflag & CRTSCTS) if (mask & UPF_HARD_FLOW)
uart_clear_mctrl(state->uart_port, TIOCM_RTS); uart_clear_mctrl(port, TIOCM_RTS);
} }
static void uart_unthrottle(struct tty_struct *tty) static void uart_unthrottle(struct tty_struct *tty)
{ {
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port; 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) if (port->x_char)
port->x_char = 0; port->x_char = 0;
else else
uart_send_xchar(tty, START_CHAR(tty)); uart_send_xchar(tty, START_CHAR(tty));
} }
if (tty->termios.c_cflag & CRTSCTS) if (mask & UPF_HARD_FLOW)
uart_set_mctrl(port, TIOCM_RTS); uart_set_mctrl(port, TIOCM_RTS);
} }
......
...@@ -46,6 +46,8 @@ struct uart_ops { ...@@ -46,6 +46,8 @@ struct uart_ops {
unsigned int (*get_mctrl)(struct uart_port *); unsigned int (*get_mctrl)(struct uart_port *);
void (*stop_tx)(struct uart_port *); void (*stop_tx)(struct uart_port *);
void (*start_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 (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *); void (*stop_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *); void (*enable_ms)(struct uart_port *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment