diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-04-17 12:23:14 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-11-04 06:25:56 -0500 |
commit | 9aba8d5b011193c8e01d565c5b585df5b94f1db2 (patch) | |
tree | 4f45580d7310ea7ea7dba87a237732f0580ecb36 /drivers/tty | |
parent | dba05832cbe4f305dfd998fb26d7c685d91fbbd8 (diff) |
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9d8796e77188..098bb99c2b9f 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) | |||
610 | static void uart_throttle(struct tty_struct *tty) | 610 | static void uart_throttle(struct tty_struct *tty) |
611 | { | 611 | { |
612 | struct uart_state *state = tty->driver_data; | 612 | struct uart_state *state = tty->driver_data; |
613 | struct uart_port *port = state->uart_port; | ||
614 | uint32_t mask = 0; | ||
613 | 615 | ||
614 | if (I_IXOFF(tty)) | 616 | if (I_IXOFF(tty)) |
617 | mask |= UPF_SOFT_FLOW; | ||
618 | if (tty->termios.c_cflag & CRTSCTS) | ||
619 | mask |= UPF_HARD_FLOW; | ||
620 | |||
621 | if (port->flags & mask) { | ||
622 | port->ops->throttle(port); | ||
623 | mask &= ~port->flags; | ||
624 | } | ||
625 | |||
626 | if (mask & UPF_SOFT_FLOW) | ||
615 | uart_send_xchar(tty, STOP_CHAR(tty)); | 627 | uart_send_xchar(tty, STOP_CHAR(tty)); |
616 | 628 | ||
617 | if (tty->termios.c_cflag & CRTSCTS) | 629 | if (mask & UPF_HARD_FLOW) |
618 | uart_clear_mctrl(state->uart_port, TIOCM_RTS); | 630 | uart_clear_mctrl(port, TIOCM_RTS); |
619 | } | 631 | } |
620 | 632 | ||
621 | static void uart_unthrottle(struct tty_struct *tty) | 633 | static void uart_unthrottle(struct tty_struct *tty) |
622 | { | 634 | { |
623 | struct uart_state *state = tty->driver_data; | 635 | struct uart_state *state = tty->driver_data; |
624 | struct uart_port *port = state->uart_port; | 636 | struct uart_port *port = state->uart_port; |
637 | uint32_t mask = 0; | ||
625 | 638 | ||
626 | if (I_IXOFF(tty)) { | 639 | if (I_IXOFF(tty)) |
640 | mask |= UPF_SOFT_FLOW; | ||
641 | if (tty->termios.c_cflag & CRTSCTS) | ||
642 | mask |= UPF_HARD_FLOW; | ||
643 | |||
644 | if (port->flags & mask) { | ||
645 | port->ops->unthrottle(port); | ||
646 | mask &= ~port->flags; | ||
647 | } | ||
648 | |||
649 | if (mask & UPF_SOFT_FLOW) { | ||
627 | if (port->x_char) | 650 | if (port->x_char) |
628 | port->x_char = 0; | 651 | port->x_char = 0; |
629 | else | 652 | else |
630 | uart_send_xchar(tty, START_CHAR(tty)); | 653 | uart_send_xchar(tty, START_CHAR(tty)); |
631 | } | 654 | } |
632 | 655 | ||
633 | if (tty->termios.c_cflag & CRTSCTS) | 656 | if (mask & UPF_HARD_FLOW) |
634 | uart_set_mctrl(port, TIOCM_RTS); | 657 | uart_set_mctrl(port, TIOCM_RTS); |
635 | } | 658 | } |
636 | 659 | ||