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: Alan Cox <alan@linux.intel.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Родитель
dba05832cb
Коммит
9aba8d5b01
|
@ -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 {
|
||||||
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 *);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче