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 | |
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>
-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 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 | ||
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e2cda5d04e48..c6690a2a27fb 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -46,6 +46,8 @@ struct uart_ops { | |||
46 | unsigned int (*get_mctrl)(struct uart_port *); | 46 | unsigned int (*get_mctrl)(struct uart_port *); |
47 | void (*stop_tx)(struct uart_port *); | 47 | void (*stop_tx)(struct uart_port *); |
48 | void (*start_tx)(struct uart_port *); | 48 | void (*start_tx)(struct uart_port *); |
49 | void (*throttle)(struct uart_port *); | ||
50 | void (*unthrottle)(struct uart_port *); | ||
49 | void (*send_xchar)(struct uart_port *, char ch); | 51 | void (*send_xchar)(struct uart_port *, char ch); |
50 | void (*stop_rx)(struct uart_port *); | 52 | void (*stop_rx)(struct uart_port *); |
51 | void (*enable_ms)(struct uart_port *); | 53 | void (*enable_ms)(struct uart_port *); |